Bit Fields

Bit fields are specified numbers of bits that may or may not have an associated identifier. Bit fields offer a way of subdividing structures into named parts of user-defined sizes.

Structures and unions can contain bit fields that can be up to 16 bits.

You cannot take the address of a bit field.

  Note : If you need to handle specific bits of 8-bit variables (char and unsigned short) or registers, you don’t need to declare bit fields.
        Much more elegant solution is to use the mikroC PRO for PIC’s intrinsic ability for individual bit access — see Accessing Individual Bits for more information.

Bit Fields Declaration

Bit fields can be declared only in structures and unions. Declare a structure normally and assign individual fields like this (fields need to be unsigned):

struct tag {
  unsigned bitfield-declarator-list;
}

Here, tag is an optional name of the structure; bitfield-declarator-list is a list of bit fields. Each component identifer requires a colon and its width in bits to be explicitly specified. Total width of all components cannot exceed two bytes (16 bits).

As an object, bit fields structure takes two bytes. Individual fields are packed within two bytes from right to left. In bitfield-declarator-list, you can omit identifier(s) to create an artificial “padding”, thus skipping irrelevant bits.

For example, if there is a need to manipulate only bits 2–4 of a register as one block, create a structure like this:

struct {
  unsigned  : 2,  // Skip bits 0 and 1, no identifier here
     mybits : 3;  // Relevant bits 2, 3 and 4
                  // Bits 5, 6 and 7 are implicitly left out
} myreg;

Here is an example:

typedef struct {
  lo_nibble  : 4;
  hi_nibble  : 4;
  high_byte  : 8;} myunsigned;

which declares the structured type myunsigned containing three components: lo_nibble (bits 3..0), hi_nibble (bits 7..4) and high_byte (bits 15..8).

Bit Fields Access

Bit fields can be accessed in the same way as the structure members. Use direct and indirect member selector (. and ->). For example, we could work with our previously declared myunsigned like this:

// This example writes low byte of bit field of myunsigned type to PORTA:
myunsigned Value_For_PORTA;

// Declare a pointer to mybitfield type:
mybitfield *TimerControl;
void main() {
  TimerControl = (mybitfield *) (void *) &T2CON ;  // explicit casting of pointer to T2CON, so it can be assigned

  ...
  Value_For_PORTA.lo_nibble  = 7;
  Value_For_PORTA.hi_nibble  = 0x0C;
  PORTA = *(char *) (void *)&Value_For_PORTA;
      // typecasting :
        // 1. address of structure to pointer to void
        // 2. pointer to void to pointer to char
        // 3. dereferencing to obtain the value
}
Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!
Want more examples and libraries? 
Find them on LibStock - A place for the code