допустим, в ОЗУ по адресу 0x0100 находится некий регистр REG, младшие 4 бита которого соответствуют какому-то предделителю, а старшие 4 - это какие-то флаги.
определяем тип для обращения к этим битам:
Код: Выделить всё
typedef struct{
unsigned char DIV : 4; // младшие 4 бита - делитель
unsigned char FLAG1 : 1;
unsigned char FLAG2 : 1;
unsigned char FLAG3 : 1;
unsigned char FLAG4 : 1;
} reg_bits;но иногда нам будет надо работать с этим регистром сразу, как с байтом, поэтому создаем еще один тип-объединение:
Код: Выделить всё
typedef union{
reg_bits BITS; // это для доступа к битам
unsigned char BYTE; // это для доступа сразу к байту
} reg_type;теперь остается только "отмапить" этот тип на нужный адрес в ОЗУ, и все:
Код: Выделить всё
reg_type *REG = (void*)0x0100;теперь при необходимости мы можем записать в регистр число сразу
Код: Выделить всё
REG->BYTE = 0x00;Код: Выделить всё
REG->BITS.DIV = 5;Код: Выделить всё
char data = REG->BITS.FLAG2 ? 12 : 32;в общем, как-то так... на сколько я в курсе, подобным образом вся периферия ARM описана в соответствующих хедерах, и вся работа с нею ведется подобным образом
свежие версии компиляторов поддерживают и безымяные структуры внутри union-ов, поэтому можно чуть-чуть упростить:
Код: Выделить всё
typedef union{
unsigned char BYTE;
struct{
unsigned char DIV : 4; // младшие 4 бита - делитель
unsigned char FLAG1 : 1;
unsigned char FLAG2 : 1;
unsigned char FLAG3 : 1;
unsigned char FLAG4 : 1;
};
} reg_type;Код: Выделить всё
REG->DIV = 12;
data = REG->FLAG2 ? 12 : 32;P.S. количество битовых полей в структуре может быть любым - компилятор выделит нужное количество целых байтов под структуру. но делать отдельное поле размером, например, 65 битов недопустимо, т.к. Си не имеет встроенных средств для работы с числами большими, чем long long. иначе говоря, каждое битовое поле может иметь размер в битах такой, чтобы уложиться внутри любого стандартного типа Си (кроме float).