Lab 2 - MNM B Comp
Lab 2 - MNM B Comp
Lab 2 - MNM B Comp
Objective
To learn setting or clearing a bit using bitwise and shift operators.
Introduction
There are logical operators called AND, OR, NOT and XOR that we are concerned with at this point. They
really do mean what they say. This is all for the sake of comparing two bits, "1" and "0". See? How can
just comparing two numbers be difficult! "1" AND "1" is True or "1". And yes, you guessed it, "0" AND
"0" is False or "0". But what is "0" AND "1" and vice versa?
Example
AND binary number operation (the "&" is used in C programming for AND):
01001011
00001001
Well, OR is even easier! "1" OR "1" is "1", obviously. "0" OR "0" is also "0". It's starting to look very
similar to AND, but here is the difference. If the two numbers are different, it will result in "1". So, "1"
OR "0" is "1". Let's use the same binary number for the example (that funny character "|" is the OR,
sometimes located above the "\" on the keyboard):
01001011 |
10001101 equals
11001111
Yes, it kept the ones in the first number and where there are ones in the second binary number, but not
the first, it changed those to ones. Very simple. NOT simply takes all of the bits and flips them. For
example, for this binary number:
01001101 will turn into 10110010. It turned the 0's into 1's and 1's into 0's, but don't get this confused
with the XOR. XOR is similar to OR but the "1" XOR "1" is actually "0". I'll just show the example and you
can figure out what happens.
01001011 ^
10001101 equals
11000110
This is not a very good way of manipulating the pins because we just changed all of the pins from 1 to 7
as input, but "what if" we had a larger program that used those pins for other things, like for instance,
pin 2 all pies brake pressure control for the anti-lock braking system. You wouldn't want to just
arbitrarily set that as an input. DDRB = 0b00000001; We need a way to ONLY affect one bit, the pin 0 bit.
Well, if you look above at the "OR", we can do this with a mask (not the carnival mask you are thinking,
but a binary mask. DDRB = DDRB | 0b00000001;
This will takes its former self and "OR" it to a mask. The mask is: 0b00000001. Yes this looks like the
actual binary number, but if the previous DDRB was, say, 0b01001010, then doing an OR to that with our
mask would be: 0b01001010 | 0b00000001 = 0b01001011. What is different in the result? That's right,
only the pin 0 bit is changed! This statement can be further compressed in C++:
DDRB |= 0b00000001;
So why "DDRB |= 1 << PINB0"? 1 << PINB0 is the act of creating the mask. The "1" represents what will
be inserted into the mask, the << is a left shift operator. It does EXACTLY what it says, and PINB0 is a
number of positions that the "1" will shift left. In essence, PINB0 is just equal to 0. So, you start with a
0b00000000, and you add a "1" to make 0b00000001 and then you shift it left 0 positions. So you are
left with 0b00000001, the same number from above. So, what if it was PINB4? The statement would be:
1 << PINB4. The "1" would be left shifted 4 times resulting in: 0b00010000. Remember, we are using a
zero index, so there is four 0s after the 1.
Let's move on to the While loop. You're right, we didn't have anything in the "infinite loop" before. Well,
now we need the microcontroller to show some action. This is only possible within the loop. The loop is
where the action is repeated over and over. If the action was located before the loop, then the action
would only happen once, like setting the direction of the pin, which is appropriate for this program. But
to create forever blinking, we need to turn the PINB0 on and off within the loop. Here is also where the
delays come in. If we didn't have delays, we would not see the LED blinking at all, it would look like it is
just on, since the blinking would occur faster than the eye could perceive, so we need to slow it down.
We know how to set a specific bit in the binary number, but we don't know how to make a specific bit
"0" if it is a "1" yet. The following code does just this, but you will notice that it is not what the program
shows. The first couple of lines turns the bit to "1" (5 volts, light), and pauses for 100 mili-seconds (by
the way, you can use microseconds by changing the "ms" to "us"). The second two lines turns the PINB0
bit to "0" (0 volts, no light). No, the AND comparison cannot just make a "0" from the bit, but if you NOT
"~" the binary number mask, it will turn all of the 0s to 1s and all of the 1s to 0s. This will permit you to
only affect the PINB0 bit and turn it into a "0". I added the parenthesis just to contain the masking
operation so the NOT could NOT the whole mask and not just the "1" before the left shift "<<".
Examples
Consider the Data Direction Register (DDRD) shown below. As you know we need to set or clear bits in
order to make the corresponding pin output or input respectively.
Now let us go ahead and clear the bit-2 and also assume this time that the DDRD value
is 0b01010101 we need to obtain 0b01010001
Lab Tasks
1- A door sensor is connected to bit 1 of PORTB, and an LED is connected to bit 7 of
PORTC. Write an AVR C program to monitor the door sensor and, when it opens, turn
on the LED.
void main()
3- Write and AVR C program to get the status of bit 5 of PORTB and send it to bit 7 of
port C continuously.
void main()
{
DDRB=DDRB&~(1<<5); //making 5th pin of port B as input
DDRC=DDRC|(1<<7); //making 7th pin of port C as output
while (1)
{ if(PINB&(1<<5))
{
PORTC=PORTC|(1<<7); //making 4th pin of port C as output }
else
{ PORTC=PORTC&~(1<<7); //making 4th pin of port C as input } }}
4- Write an AVR C program to get the status of bit 5 of PORTB and send it to bit 7 of
PORTC continuously.
void main()
{
DDRB=DDRB&~(1<<1); //making 2nd pin of port B as input
DDRC=DDRC|(1<<7); //making 7th pin of port C as output
while (1)
{
if(PINB&(1<<1))
{
PORTC=PORTC|(1<<7); //making 7th pin of port C as output }
else
{ PORTC=PORTC&~(1<<7); //making 7th pin of port C as input }}