Thursday, 5 July 2012

Introduction to C language bitwise operators and relevant truth tables. in AVR uC's

As we seen in the last tutorial, sometimes bitwise operators are needed, in order to change just a pin, shit a bit, etc..
So lets start by revising quickly the logic truth tables, so we understand a bit better what we on about.

There are logical operators called AND, OR, NOT and XOR among others, that are the ones we will discuss now.
*While in digital systems, the gates work with 2 inputs at least, here we have to work with the 8 bits ! 

Example AND binary number operation (the "&" is used in C programming for AND):


01001011 &
10001101
     =
00001001

Example OR binary number operation ( the character " | " is the ORused in C programming )

01001011 |
10001101
     =
11001111



Example XOR - Exclusive OR - binary number operation ( the character   "^"  is the ORused in C programming )
    01001011 ^
    10001101
    equals
    11000110
    
    
    
    
    * The NOT operator inverts the sense of the bit, so a 1 becomes a 0, and a 0 becomes a 1.
    

       |       =     bit OR
       &     =    bit AND
       ~      =    bit NOT
       ^      =    bit EXLUSIVE OR (XOR)
      <<    =    bit LEFT SHIFT
      >>    =    bit RIGHT SHIFT

    These operators work on bits and not logical values. Take two 8 bit bytes, combine with any of these operators, and you will get another 8 bit byte according to the operator's function. These operators work on the individual bits inside the byte.

    A truth table helps to explain each operation. In a truth table, a 1 bit stands for true, and a 0 stands for false.


    
    
So, we already know what the <avr/io.h> does, but the #include <util/delay.h> hasnt been spoken about; Just like the name implies, the delay.h will provide us with a way to create delays in our program (see http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html for more details). And Just like the name implies, the delay.h will provide us with a way to create delays in our program.
    So we know we have DDRD = 0b11111110
We need only to change the one bit: the pin 0 bit.If we look at the ways above, we can do this with the OR operator, using a binary mask.
    DDRD = DDRD | 0b00000001;
This will "OR" it to a mask. The mask is: 0b00000001. While this looks like the actual binary number, if the previous DDRD was, say, 0b01001010, then doing an OR to that with our mask would be: 0b01001010 | 0b00000001 = 0b01001011. So this result only the pin 0 bit has changed!
This statememt can be further compressed in C++:
DDRD |= 0b00000001;


So why "DDRD |= 1 << PIND0"?
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 PIND0 is a number of positions that the "1" will shift left. In essence, PIND0 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 PIND4? The statement would be: 1 << PIND4. 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.


We know how to set a specific bit in the binary number, but we don't know how to toggle a bit ( change it to 1 if it is a 0 and vice versa).

    #include <avr/io.h>
    #include <util/delay.h>
    int main(void)
       {
            DDRB |= 1 << PIND0; 
             while (1)
             {
               PORTB |= 1 << PINB0;
                _delay_ms(100);
               PORTB &= ~(1 << PINB0);
               _delay_ms(100);
              }
        }
    If the delay is going to be the same for on and off, we could shorten the previous four lines to only two and take advantage of the XOR operation.
    The " ^ " Bitwise operator toggles the bit, so that if it is a 1 will then become a 0, and vice versa

    #include <avr/io.h>

    #include <util/delay.h>

    int main(void)

    {

      DDRB |= 1 << PIND0; 

      while (1)
      {
        PORTB ^= 1 << PINB0;  */ The " ^ " Bitwise operator toggles the bit, so that if it is a 1 will then become a 0, and vice versa*/
    _delay_ms(100);
      }
    }
    *(...to be continued)

No comments:

Post a Comment

Feel free to contact me with any suggestions, doubts or requests.

Bless