Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVR bitwise C operations

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
like image 888
Dovydas Avatar asked Jun 26 '26 04:06

Dovydas


2 Answers

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.

like image 92
zmo Avatar answered Jun 27 '26 22:06

zmo


No, it is slower.

The reason for the usual syntax like DDRC |= (1<<DDRC0); is that the right side contains compile time constants. The compiler will convert it to a number before the processor sees it, so the processor doesn't perform the shift.

As for using the |= assignment operator, there may be an extra read operation. But the cost for efficiency for a one time assignment is vastly less than the cost to maintain the source code.

I'm not sure what you are doing with the arithmetic in your question. The statement takes the original contents of DDRC and ors it with something like 0b00000001 (where the 1 is in the DDRC0 position), and assigns it back to DDRC.

like image 23
uncleO Avatar answered Jun 27 '26 23:06

uncleO



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!