Битовые операции, как правильно?
- Войдите на сайт для отправки комментариев
Втр, 08/11/2016 - 13:10
Есть устройство TEA5767
Читаем из него 5 байт информации, согласно даташиту, и сохраняем в переменную unsigned char teaBuf[5].
Опять же по даташиту в 4 байте есть 3 параметра:
1. 7-4 бит уровень сигнала
2. 3-1 бит идентифткатор чипа
1. 7-4 бит уровень сигнала
2. 3-1 бит идентифткатор чипа
3. 0 бит не используется.
Мне нужно получить уровень сигнала, делаю так:
byte level = (teaBuf[3] & 0xF0) >> 4;
То есть операцией & 0xF0 устанавливаем биты с 3 по 0 в 0, потом сдвигаем биты 7-4 на позицию 3-0 и получем результат в byte level от 0 до 15.
А можно ли не обнулять биты 3-0, а просто произвести сдвиг? То есть сделать так:
byte level = teaBuf[3] >> 4;
Я так понимаю в этом случе просто произойдет сдвиг вправо, и биты 3-0 заместатся битами 7-4? Не будет ли каких либо проблем?
Пробовал делать и как в первом варианте и как во втором, результат одинаковый, но хотелось бы знать какой метод более правильный.
Можно.
Более правильно - не использовать лишних команд.
Можно наложить маску в виде структуры и тогда не нужны "магические цифры" (3, 4, ...). Так более правильно, так как будут использоваться именованные поля, что проще в сопровождении.
По возможности нужно всегда избавляться от цифр, которые ни к чему явно не привязаны и не описаны, т.к. они делают трудной последующую отладку.
uni, Вы всерьез считаете, что при сдвиге на полбайта будет понятнее, если вместо "4" применить именованную константу?
Хотя, кто знает...
Я считать лучше использовать комментарий
И все. И не важно какого цвета кошка . Главное что бы она ловила мышей. А для тех кто сомнивается , то написать комментарий:"Это кошка. Она ловит тут мышей."
Спасибо за ответы, главное всетаки было убедится что в моем случае сдвига достаточно.
Да как вариант можно именовать переменные, например чтобы было созвучно даташиту на чип, ноя думаю это актиально если пишешь библиотеку не только для себя, так сказать соблюдения правил "хорошего тона".
В моем случае будет достаточно подробного комментирвоания кода.
Когда есть описание битовых полей, то нужно использовать структуру, в которой задать имена для этих битовых полей. Определить тип в виде этой структуры, создать указатель на структуру и присвоить ему значение указателя на буфер данных. Вот тогда у вас будут именованные поля в естественном виде без всяких ручных никому не нужных сдвигов. Сдвигами должен заниматься компилятор.
Точно так же делают, когда работают с заголовочниками bmp или wav файлов.
Дайте ссылку на используемый datasheet и я покажу как это обычно делается.
Дайте ссылку на используемый datasheet и я покажу как это обычно делается.
Даташит тут.
За пример использования буду признателен.
Как-то вот так (пояснение):
Спасибо отгромное, выглядит классно.
Я правильно понимаю что конструкция выше говорит о том что следующие за ней данные пишутся в новый байт?
И могу ли я использовать структуру так? То есть почему PTEA5767HN_READDATA определяется как сылка а TEA5767HN_READDATA нет?
Либо в условии
А структуру обязательно объявлять как глобальную?
У меня беда в том что делаю под управлением NANO на ATmega168 радиоприемник, памяти всего килобайт, выбрасывать ее жалко.
Пока прикрутил только экран на ssd1306 и начал прикручивать радио на tea5767, еще на очереди esp8266.
Поэтому на счету каждый байт :-)
Попробую сегодня сделать со структурой, посмотрю что с памятью будет.
Можно использовать только указатель PTEA5767HN_READDATA pData, переменную TEA5767HN_READDATA я указал для примера. Описание типа PTEA5767HN_READDATA обычно указывают глобально, а сами переменные этого типа могут объявлятся где угодно.
Да, можно, так и было задумано. Вы как-бы накладываете описание структуры на буфер с данными и через это описание обращаетесь к нужным вам полям в этом буфере. При этом не нужно думать о самих битовых полях в буфере, компилятор разберётся, используя описание структуры.
> То есть почему PTEA5767HN_READDATA определяется как сылка а TEA5767HN_READDATA нет?
Просто пример использования и переменной, и указателя. Специально объявлять переменную не нужно. Иногда бывает удобным хранить данные в виде переменной с таким типом. Можно ведь сделать и обратную операцию. Создать такую переменную и наложить на неё маску в виде указателя на массив байт. Тогда можно обращаться к каждому отдельному байту структуры по этому указателю.
В более сложных случаях struct совмещают с union, чтобы можно было обращаться к одной и той же области памяти как к целому объекту или как к набору полей.
В данном случае - да, это делитель на байты, но в общем случае компилятор считает сколько битов использовалось до делителя и делает выравнивание на целое число байт (я не проверял, но должно быть что-то вроде этого).
Медленно, но разбираюсь, а подскажите, как из структуры передать данные в массив байт?
Например поменял я часть значений в стркутурке, теперь хочу записать измеренные данные назад в приемник. Как пример изменил стерео на моно. теперь надо передать 1 байт в который входит бит Stereo. Для этого из структуры надо получить третий байт. А вот как преобразовать структуру в массив байт или один байт структуры в байт для записи в чип я не пойму. Подскажите пожалуйста как быть.
IMHO самое простое - берете адрес структуры, меняете его тип на указететь на байт или на символ и выбираете байты по нужному смещению.
Некузяво. Логичнее объявить union с массивом байтов и работать средствами языка, а не указателей фиг пойми на что.
Некузяво. Логичнее объявить union с массивом байтов и работать средствами языка, а не указателей фиг пойми на что.
Спасибо за подсказку, с union действительно красиво получается. Не все еще проверил, но часть что изменил работает.
А вот с указателями и вычислением адреса не понял как делать, то есть получить адрес структуры, и читать значения именно с адресов, а зная размер полей структуры можно адрес каждого байта рассчитать. Так?
Andrey12, загляните в соседнюю тему про фиксированную точку - там обсуждается похожая проблема. В т.ч. с примерами кода, результатами дизассемблирования и оценками производительности.
В одном из моих сообщений есть и реально проверенный код с указателями.
Andrey12, загляните в соседнюю тему про фиксированную точку....
Заглянул, почитал. Но вчера с union разобрался. Переделал, теперь работает как и хотел.
Всем спасибо за помощь.