Sunday, February 13, 2011

Set Operation


Setting a bit in a Register:

In Embedded C, binary numbers are represented with a '0b' prefix. To represent a hexadecimal number, put a '0x' instead of '0b'. Decimal numbers can be written directly, they don't need any prefixes.

Let us consider an 8 bit register, ADMUX. And our aim is to assign the 5th bit (the right most bit is the 1st bit) a value of logical 1. The syntax will be

ADMUX=0b00010000;

When the above statement is processed, the 5th bit will be set to 1, and the rest set to logical 0.
Now, if we want to set the 1st bit also 1, without changing the status of the 5th bit,
ADMUX=0b00010001;
Suppose the above line is the 1st line of our program, if we want to change the value of the 3rd bit of this register ADMUX, without changing the value of any other bit, we will have to retrace it back through our code, which will be very cumbersome. Hence, we use | (OR) bit wise operator. It performs bitwise OR.
Example:  0b11001101 | 0b00000010
            1 1 0 0 1 1 0 1
     OR   0 0 0 0 0 0 1 0
Result:  1 1 0 0 1 1 1 0

As we can see, in the 2nd number only the 2nd bit from the right was set to 1. When bitwise OR operation was performed of this number with 11001101, the result obtained was same as the first number except for the 2nd bit, which had changed to 1. Thus, the bit had been SET.
Hence, for Setting a particular bit of a register, without disturbing the contents of the other bits, we perform bitwise OR operation ( | ) of the register with a binary number which has a 1 at the position of the bit we want to set in the register.
e.g:  ADMUX= ADMUX | (0b00001000);
This can also be written as 
ADMUX|=(0b00001000);

In practice, each bit has got a name according to the function it performs. Let's say the 5th bit has got a name ADEN  (ADC Enable), it is used to enable the ADC. When it is set to 1, the ADC function of the microcontroller is enabled. When it is 0 it is disabled.
If we employ the syntax explained above, we will have to check the datasheet all the time to verify the position of ADEN. The following syntax circumvents that,

ADEN|=(1<<ADEN);

The << is called the left shift operator. It shifts the bits of the variable on its left hand side by the number of places specified by the number on its right hand side.

If we write.


A=1<<4;
then, 1, whose binary value is 00000001 is shifted 3 places to the left. The result is 00001000.
So, if ADEN is the 5th bit,
ADMUX|=(1<<ADEN);
will result in
ADMUX|=(1<<5);
which will result in
ADMUX|=(0b00100000);
What is this better? Why should I prefer this method?
This is why this method is much better:
  1. Readability of code: ADMUX|=(1<<ADEN); tells you what bit is being set. It tells you that here the ADC is being enabled. ADEN=5 is already defined in the header file of that microcontroller.
  2. Portable: Let's say that  you use this code is really useful and has been used several times in a very long program. You need this code to run on another microcontroller. This other microcontroller belongs to the same family as your old one, but the positions of the bits (bit scheme) is slightly different, i.e ADEN may be at bit 2 instead of 5. You'll have to find all occurences of ADMUX|=(0b00010000); and change them to ADMUX|=0b00000010; But, if you have used the other method you dont have to make any changes in your code as the position of ADEN would have been specified in the header file for that particular microcontroller. 

No comments:

Post a Comment