Pages: [1]   Go Down
Author Topic: Please explain "TCCR1B |= (1 << CS12);"  (Read 1677 times)
0 Members and 1 Guest are viewing this topic.
UK
Offline Offline
Faraday Member
**
Karma: 101
Posts: 6169
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I realize that this code sets the bit called CS12 in the TCCR1B register.

But I can't find any explanation of why it is coded like that. I would expect the << operator to shift all of the bits in the register to the left but clearly that doesn't happen here.

Perhaps someone can explain it.

...R
Logged

Offline Offline
Edison Member
*
Karma: 32
Posts: 1377
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The (1<<CS12) creates a temporary operand that contains a 1 in the CS12 position. That temporary is then ORed with the TCCR1B variable(register) setting the CS12 bit and leaving the rest of TCCR1B alone.
Logged

Offline Offline
Newbie
*
Karma: 1
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

KeithRB is correct, but here's a step by step breakdown in case you wanted more detail:

CS12 has a value of 2 since it represents bit 2 of the TCCR1B register. 
(1 << CS12) takes the value 1 (0b00000001) and shifts it left 2 times to get (0b00000100).
The order of operations dictates that things in () happen first, so this is done before the "|=" is evaluated.
So now we get TCCR1B |= 0b00000100, which is the same as TCCR1B = TCCR1B | 0b00000100.
Since "|" is "OR", all the bits other than CS12 in TCCR1B are unaffected.

You can do this exact same thing with any of these:
Code:
bitSet(TCCR1B, CS12);
TCCR1B |= _BV(CS12);
TCCR1B |= bit(CS12);

I think TCCR1B |= CS12; would work as well, but it's not good practice and may throw a warning.
Logged

UK
Offline Offline
Faraday Member
**
Karma: 101
Posts: 6169
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for the comprehensive explanation and you also answered my follow-up question

...R

KeithRB is correct, but here's a step by step breakdown in case you wanted more detail:

CS12 has a value of 2 since it represents bit 2 of the TCCR1B register. 
(1 << CS12) takes the value 1 (0b00000001) and shifts it left 2 times to get (0b00000100).
The order of operations dictates that things in () happen first, so this is done before the "|=" is evaluated.
So now we get TCCR1B |= 0b00000100, which is the same as TCCR1B = TCCR1B | 0b00000100.
Since "|" is "OR", all the bits other than CS12 in TCCR1B are unaffected.

You can do this exact same thing with any of these:
Code:
bitSet(TCCR1B, CS12);
TCCR1B |= _BV(CS12);
TCCR1B |= bit(CS12);

I think TCCR1B |= CS12; would work as well, but it's not good practice and may throw a warning.
Logged

Offline Offline
Edison Member
*
Karma: 32
Posts: 1377
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

CS12 is a bit position - a number - not a mask. If it for example, '3', it has the binary value of 0b11, and if you or *that* with TCCR1B, you will not get the same as the original expression, i.e., CS12 != (1<<CS12) .
Logged

Pages: [1]   Go Up
Jump to: