Making a pin single go low
Basically the command is:
PORTD &= ~(1 << 5);
This line makes the sixth pin on PORTD go low. Why the sixth (6)? Because the first pin is 0. Therefore the second pin is called 1, the third pin is called 2 and therefore pin 6 is called 5. If this is confusing, which it can be at first, run the sample program and simulate it in AVR Studio and then change the value and see which pin is taken low. If you wanted to make the first pin of PORTD go low you would use PORTD &= ~(1<<0);
How does it work? Well to the beginner this can look quite daunting but it is all quite simple.
Note this is the prefered method now as old commands supported by C such as cbi() amd sbi() have now be deprecated (dropped). I mention this here as some old code around may use cbi() or sbi(). These commands have actually been dropped from AVRGCC in the latest version, so any code using cbi() and sbi() will not compile. If you desparately want them still you'll need to write your own macro to re-implement them using the code presented here as the basic.
Anyway, onto the explanation.
Firstly, the "&=" part.
PORTD &= ~(1 << 5); is excactly the same as PORTD = PORTD & ~(1<<5); The "&=" is a shorthand way of writing it. It just means PORTD equals PORTD AND something.
The "&" part is the logical bitwise AND operator. This takes two binary numbers (1 or 0) and returns 1 if both are 1 or 0 for everything else.
1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0
When operating on longer numbers it works on each pair of bits individually.
~ (tilde) operator
Now the ~ (tilde). This is the "One's Complement" operator. Also known as logic NOT. Basically it takes 0 and returns 1, or takes 1 and returns 0. It just creates the opposite of whatever is to the right of it.
<< (Shift Left) operator
Finally, the << operator. This is called the "Shift left" operator. This operator exists in all ANSI compliant C compilers but is not usually highly utilised with PCs etc. It is great for microcontrollers though. The "Shift left" operator is interesting in that it takes a binary (1 and 0) number and shifts everything left and brings in 0s from the right.
The form of it is:
value << number of bit positions
0101 << 1 would result in 1010
00100000 << 2 would result in 10000000
00000001 << 4 would reuslt in 00010000
Putting it all together (proof)
If PORTD was 11111111 before this command it would be 11011111 afterwards. Remember that pin 0 is the right most binary digit.
How we get that is as follows:
PORTD starts as 11111111 (0xFF is the hex value for this)
(1<<5) is the same as (00000001 << 5) and works out to be 00100000
So we could now write:
PORTD &= ~(00100000)
Now I'll expand the equation to get rid of the "&=" part. (See above how it works).
Getting rid of "&=" gives us:
PORTD = PORTD & ~(00100000)
Now well will get rid of the ~ (tilde):
PORTD = PORTD & 11011111
Now we step away from proper mathematics and into programming order of operations.
PORTD starts out as 11111111 so we can substitute that for the second PORTD in our equation. (This is only because this is how the microprocessor and most computers do it). So this gives us:
PORTD = 11111111 & 11011111
Performing the & (AND) operator gives us:
PORTD = 11011111
And this is what the port will set at.
NOTE: By doing all these steps, only the one individual bit is changed and all others are left as they were
Therefore we made the sixth and only the sixth bit go low. I suggest you play around with the example code and see how changing it affects the output in the simualtion in AVR studio.
Any errors, questions, comments etc can be posted in the forum or sent via the email page
Webpage subject the copyright. No reproduction without express permission of Webmaster (Dingo_aus)
AVR is a trademark of Atmel (see www.atmel.com)