Latest update

# Why does AVR code use bit shifting

2018-02-21 22:09:19

In AVR programming, register bits are invariably set by left-shifting a 1 to the appropriate bit position - and they're cleared by a ones' complement of the same.

Example: for an ATtiny85, I might set PORTB, b4 like this:

PORTB |= (1<

or clear it like this:

PORTB &= ~(1<

My question is: Why is it done this way? The simplest code ends up being a mess of bit-shifts. Why are bits defined as bit positions instead of masks.

For instance, the IO header for the ATtiny85 includes this:

#define PORTB _SFR_IO8(0x18)

#define PB5 5

#define PB4 4

#define PB3 3

#define PB2 2

#define PB1 1

#define PB0 0

To me, it would be much more logical to define the bits as masks instead (like this):

#define PORTB _SFR_IO8(0x18)

#define PB5 0x20

#define PB4 0x10

#define PB3 0x08

#define PB2 0x04

#define PB1 0x02

#define PB0 0x01

So we could do something like this:

PORTB |= PB5 | PB3 | PB0;

PORTB &= ~PB5

• The simplest code ends up being a mess of bit-shifts. Why are bits defined as bit positions instead of masks.

No. Not at all. The shifts are only in the C source code, not in the compiled machine code. All the examples you showed can and will be resolved by the compiler at compile time because they are simple constant expressions.

(1<

So it not only works, it does not create more code size.

It makes also sense for the human programmer to name the bits by their index (e.g. 5) and not by their bit mask (e.g. 32) because this way consecutive numbers 0..7 can be used to identify the bits instead of awkward power of two (1, 2, 4, 8, .. 128).

And there is another reason (maybe the main reason):

You not only want to use bit masks (which can be created from indices by bit shifting) but some AVR instructions for bit manipulation use bit indices as immediate operator in their instruction op code. If you identify bits of SFRs by indices you can u

2018-02-21 23:46:50