When you are working with Microcontrollers you often have to keep status flags for certain events, e-g when you are using a timer, you need to keep track of how much time in milliseconds or seconds have elapsed, but your timers only allows ticks in microseconds, so you count the number of microseconds say 1000 microseconds and “Set” the flag “one_ms” indicating one millisecond has elapsed. And more than likely, this flag “one_ms” is either a “char” type or an “int”. In either case, a char will take one whole byte and an int will take 16/32 bits depending on the architecture. But if you notice, what you needed to convey could have easily been conveyed or kept record of in one bit only. So for one status flag of one bit wide, you pay a price of unused extra bits. That is not all, you also end up having multiple status flag variables, meaning you are wasting a lot of useful resource (memory). And the code gets messy too.
However, there is a better way to keep status flags without wasting the memory or without making the code a mess. And that is by the use of “bit fields” in C programming.
Bit fields are a special structure member type. A bit field is of type integer but its width is specified by the programmer. For example, ARM7 is has a 32-bit integer, but when I use this “int” data type for a bit field, I can specify the actual size this integer will occupy in memory by specifying the size after a “:”.
unsigned int millisecond; //occupies 32 bits in memory
unsigned int millisecond : 4 ; //occupies 4 bits in memory}obj;
Bit Fields can be of type “signed integer” , “unsigned integer” or a “bool”.
Keep in mind, the specified size cannot exceed maximum default size of that data type. And, for portability and other holy reasons always specify if you want your bit fields signed or unsigned.
Useful example of Bit FieldsSuppose you are designing a stop watch you have one hardware timer which is capable of counting ticks in microseconds. But you want time in seconds and milliseconds. So what do you do ? You wait and count.
For the stop watch example:
int tick_counter ; //global tick counter
unsigned int start : 1 ; //one bit flag indicating whether the lap time has started or not
unsigned int millisecond : 1; //one bit flag indicating 1 millisecond
unsigned int ten_millisecond : 1; //one bit flag indicating 10 milliseconds
unsigned int second : 1; //one bit flag indicating 1 second
unsigned int laps_elapsed : 4; //4 bit wide elapsed laps counter
void timer_isr( ) //ticks every 10 microsecond
//disable low / equal priority interrupts
if(tick_counter == 100)
lap.millisecond = 1;
if(tick_counter == 1000)
lap.ten_millisecond = 1;
if(tick_counter == 10000)
lap.second = 1;
tick_counter = 0;
//enable low / equal priority interrupts
The isr written above is only generic code for the specified example, it does not assume any specific sort of hardware. That is why I have placed comments at the start and end of the ISR for hardware specific routines you need to do.
Link: Bit Fields on wikipedia
Technorati Tags: programming,bit fields,C