Dr_Quark:
While we're talking about port manipulation, I found the following in the Atmel reference library:
_BV(3) => 1 << 3 => 0x08
I have no clue what this means. Why would you say _BV(3) when it is just as easy to say digitalRead(3)? On further reading, it looks like the above line implies that _BV(3) is equivalent to 0x08. If that is true, what does _BV(PD7) even mean?
The "_BV()" thing is just a macro that gives you the numeric value of a binary bit.
Look at this example: I want to blink the built in LED on an Arduino UNO, and I'll show you two different ways which LOOK different but are exactly the same. First of all, I have to look something up: I know the LED is on Arduino UNO Pin #13, but I don't recall what port and bit that is (give me a sec).... ... OK looking at the UNO schematic I see that Pin 13 is connected to the Atmel MEGA328p chip's pin 19 which is Bit 5 of PORTB.
OK, now the code. First the "Arduino way":
void setup (void)
{
pinMode (13, OUTPUT); // set pin 13 to output
}
void loop (void)
{
digitalWrite (13, HIGH); // turn LED on
delay (500); // leave it on 1/2 second
digitalWrite (13, LOW); // LED off
delay (500); // leave off 1/2 second
}
Now, the "C way" using the ports and bits directly:
void setup (void)
{
DDRB |= _BV(5); // set the data direction register for PORTB, BIT5 as an output
}
void loop (void)
{
PORTB |= _BV(5); // set PORTB, bit 5 high (LED on)
delay (500); // 1/2 sec, same as first example
PORTB &= ~_BV(5); // PORTB, bit 5 low (LED off)
delay (500); // same as the others
}
OK, what the heck is this |= and &= stuff?
Well, first of all, realize that we COULD have just said [b]PORTB = _BV(5)[/b]
or [b]PORTB = 0[/b]
but that would "mess with" ALL EIGHT pins of PORTB. In a more complex program that had, say, a few motors and a few LED's, messing with the whole port might start or stop motors when you only want the LED to blink.
Look at an 8 bit byte and the value of each bit:
[tt][b]Bit 7 6 5 4 3 2 1 0
Hex 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01
Dec 128 64 32 16 8 4 2 1
[/b]
[/tt]
so, Bit 5 (i.e "_BV(5)") is actually 32 (or 0x20 in hex) and assuming ONLY bit 5 were set, the byte would look like this:
[tt][b]Bit 7 6 [color=red]5[/color] 4 3 2 1 0
0 0 [color=red]1[/color] 0 0 0 0 0
[/b]
[/tt]
Or, in a program if I did this (pseudo code):
Print hexValue (_BV(5));
...it would print out "0x20" and.....
Print decValue (_BV(5));
... would print out "32".
Now, the "|" character, in C, means "logical OR" and "|=" means "OR-equals". OR is used to set bits HIGH. Think of it like this: I ask you "do you have coffee?" and you have two cups. If the first one OR the other one OR both are full, then yes you do have coffee. Code example:
something = something | 0x20; // take value of "something" and set bit 5 high
something |= 0x20; // same exact thing, just simpler looking
OK, now we see that we use "OR" to turn a bit ON. To turn it off, we use AND. How AND works, in "coffee code":
I ask you "Are both of your cups filled with coffee?". If the first cup AND the second cup are full, then your answer is "YES", otherwise it's "NO". So if I want you NOT to have both cups of coffee, all I need do is empty ONE or the OTHER or BOTH and then your answer is "NO".
Now, here's the trick of turning OFF bit 5 without disturbing the others. The "~" (tilde) character means "invert all the bits" (if a bit is 1, make it 0. If it's 0, make it 1.
So let's say now we are looking at PORTB and you had turned ON the LED (that is, set bit 5 high). It looks looks this:
[tt][b]Bit 7 6 [color=red]5[/color] 4 3 2 1 0
PORTB X X [color=red]1[/color] X X X X X[/b]
[/tt]
The "X" means "I don't care what those bits are".
Remember the AND function? If I "AND" any bit in PORTB with a high (1), then the result will be whatever the bit was originally (i.e it won't change).
To turn off Bit 5, I need to make an "AND MASK" like this:
[tt][b]Bit 7 6 [color=red]5[/color] 4 3 2 1 0
_BV(5) 0 0 [color=red]1[/color] 0 0 0 0 0[/b]
[/tt]
[tt][b]~_BV(5) 1 1 [color=red]0[/color] [color=red][color=black]1[/color][/color] 1 1 1 1[/b]
(this is the "AND mask" made using the tilde)[/tt]
Now let's say PORTB has this state:
[tt][b]Bit 7 6 [color=red]5[/color] 4 3 2 1 0
value 1 0 [color=red]1[/color] 1 1 0 1 1[/b]
[/tt]
[tt][b]mask 1 1 [color=red]0[/color] 1 1 1 1 1
result 1 0 [color=red]0[/color] 1 1 0 1 1 (result after AND-ing in the mask)
[/b]
[/tt]
Notice that "result" is the same as "value" except that we changed bit 5 (and ONLY bit 5) from 1 to 0 (which turns off the LED).
Hope all this makes sense. If not, read it again. It's actually simple (it only looks scary).
Hope it helps.