AVR bitwise C operations

avr, bit-manipulation, c, gcc

Solution

for the sake of the demonstration:

here are two code compiled with avr-gcc-4.7.2:

void main() {
    DDRC |= (1<<5);
}

and another:

void main() {
    DDRC |= 0b100000;
}

 % diff -s t2.s t.s
Files t2.s and t.s are identical

that's because `1<<N` is detected at compile time, and transform to its constant equivalent, making both expressions identical when sent to the microcontroller.

About operations, please have a look at truth tables:

| a b -> a&b |        | a b -> a|b |
| 0 0    0   |        | 0 0    0   |
| 0 1    0   |        | 0 1    1   |
| 1 0    0   |        | 1 0    1   |
| 1 1    1   |        | 1 1    1   |

the hint to remember both truth tables is the following:

- if one of the operands is a `0` and you're doing a `&`, then the result will be `0` (force to 0)

- if one of the operands is a `1` and you're doing a `|`, then the result will be `1` (force to 1)

So if you take an example a bit more complicated:

101010 | 010101 = 111111
101010 & 010101 = 000000

and finaly, when you want to set a bit:

REGISTER = 00000001
REGISTER |= 1<<5      <=> REGISTER = 00000001 | 00100000
REGISTER == 00100001

if you want to reset that bit:

REGISTER &= ~(1<<5)   <=> REGISTER = 00100001 & ~(00100000)  <=> REGISTER = 00100001 & 11011111
REGISTER == 00000001

I hope it's making more sense… Though you'd better lookup for a course on combinatory logics, which is the basic to perfectly handle when doing embedded programming.

Now to answer your question:

if we know anyway a bit combination to simply write and maybe its faster and simpler?:

it's not necessarily faster, and not really simpler.

Consider the following made up register FOO:

  7   6   5   4   3   2   1   0
[ A | B | C | D | W | X | Y | Z ]

now consider that we have build a header that has preprocessor variables with the right values:

FOOZ = 0
FOOY = 1
FOOX = 2
FOOW = 3
FOOD = 4
FOOC = 5
FOOB = 6
FOOA = 7

and now we need to set up `A`, `C` and 'X' bits, which can be done as follows:

FOO |= 1<<FOOA | 1<<FOOC | 1<<FOOX

instead of:

FOO |= 0b10100100

which could more easily lead to errors.

Problem

I have a question about ATMEGA328P programming in Atmel Studio 6.1. Isn't it faster to assign a binary to register than making shift operation? If I understand correctly, but please correct this!! Let's say: ``` DDRC = 0b11001100; ``` I have to check initial bit condition before making bitwise operation before shifting any a bit to location? For example ``` DDRC |= (1<<DDRC0); ``` and we get: ``` 11001100 10011001 = 11011101 ``` Is this right? If we know anyway a bit combination to simply write and maybe it's faster and simpler?: ``` 0b11001101 ```

Original source