Bit fields for control registers

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm writing a C++ abstraction layer for AVR modules and I found myself wondering if there wasn't a better way to set bit values in code.

Have people tried using unions to access bit values in control registers?

For example for the Timer control and status registers:

#define BITFIELD uint8_t BYTE; struct {uint8_t B0:1; uint8_t B1:1; uint8_t B2:1;\
uint8_t B3:1; uint8_t B4:1; uint8_t B5:1; uint8_t B6:1; uint8_t B7:1;}

typedef union {
 BITFIELD;
 struct {
  uint8_t WGML :2;
  uint8_t COMC :2;
  uint8_t COMB :2;
  uint8_t COMA :2;
 };
} tccra_t;

typedef union {
 BITFIELD;
 struct {
  uint8_t CS   :3;
  uint8_t WGMH :2;
  uint8_t      :1;
  union { // Using these unions to work for both the 8-bit and 16-bit timers.
   struct {
    uint8_t FOCB :1;
    uint8_t FOCA :1;
   };
   struct {
    uint8_t ICES :1;
    uint8_t ICNC :1;
   };
  };
 };
} tccrb_t;

typedef union {
 BITFIELD;
 struct {
  uint8_t      :5;
  uint8_t FOCC :1;
  uint8_t FOCB :1;
  uint8_t FOCA :1;
 };
} tccrc_t;

And to use, something like this:

volatile tccra_t * const TCCRA = (volatile tccra_t *)&TCCR1A; // A constant pointer to a volatile place in memory.

TCCRA->COMA = 3; // Set Compare Output Mode to 0b11
TCCRA->WGML = 2; // Set Waveform Generation Mode to 0b10

// Or individual bits
TCCRA->B1 = 0; // Clear bit 1

// Or the whole byte
TCCRA->BYTE = 255;

I'm curious if anyone else has tried this, whether it will even work, and it it's worth doing.

I have not had the chance to test these bit manipulations, so far it's all theoretical. I know the bit-order is compiler dependent but I'm staying with avr-gcc.

Pushing AVRs to their limits

Last Edited: Tue. Dec 8, 2009 - 04:29 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Felipe Maimon

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using bit fields makes the code more readable. I've been doing this for many years.

There are disadvantages also. Sometimes if you want to set more than one bit, you have to do each one separately. That often is the case when initializing. I don't worry about this when programming a PC, but the inefficiency is more serious when programming an AVR.

In AVR code, I usually define each bit using enums. That way I can "or" them together and set any number of bits in the same operation.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I knew I had seen that post before but when I searched for "bit field" I only got it for storing values smaller than a byte, not tying that into control registers.

However, this lets you do a little more than just access individual bits. It should also let you access 2-bit values like in the example.

Pushing AVRs to their limits

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cinderblock wrote:
However, this lets you do a little more than just access individual bits. It should also let you access 2-bit values like in the example.
Correct. I should have said one bitfield at a time, not one bit.