Saturday, February 19, 2011

Pull Ups and Pull Downs


Pull up and Pull Down.


Pull up and Pull down is a very simple concept.
Let's try to understand it through an example.

Take the case of a simple NOT gate. It simply negates the input.


Input
Output
0
1
1
0

But, What would appear at the output if the input is left unconnected? Will it be a Logic 0 or a Logic 1?
You might say that since there is no connection at the input, the voltage at the input pin would be Logic 0 and hence the output of the NOT gate shall be high. 
But, have any of you ever observed an output from a not gate without any input?. 


When nothing is connected to the input pin, the pin isn’t at zero volts but its “floating”. (In electronics, an unconnected input pin is termed as floating) In the digital world, particularly TTL, any floating input is considered as Logic 1. But it’s never a good idea to leave the input pins unconnected. Why? Well, that’s because noise generated by adjacent electrical activity can induce a significant amount of voltage across the input which could result in errant behavior of the system.


Hence, its always advisable to have a default value at the inputs. This can be achieved by connecting pull-up or pull-down resistors at the inputs.


The same logic applies while interfacing devices to the microcontroller. Most of the microcontrollers available have inbuilt pull-up resistors which can be enabled or disabled through software. These prove to be very handy while connecting external devices, say for example a switch. But, when internal pull-ups are not available, we need to connect external pull-ups. Pull-downs can also be connected, but we need to make sure that there are no internal pull-ups activated on that particular port.


In the figure above, the switch is connected in an active-low configuration. Which means whenever you press the switch, logic 0 appears at the input. Thus, the code will be written accordingly.
eg:
if (switch==0)
{
        //switch pressed
}
else   //switch open

There are no specific values for such pull-ups or pull-downs; they could be anywhere between 1K and 47K. 


( source: ThinkLabs Technosolutions)

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. 

Binary Numbers



While programming Microcontrollers in C, most of the time we have to deal with registers. We may have to 'SET' the bits of a register, 'CLEAR' the bits of a register or 'CHECK' the status of a particular bit of a register. Before we do all this, let us first take a look at binary numbers and conversion to decimal number system.


A register is simply a collection of some bits.
When you pick up a microcontroller's datasheet, it'll say that, that particular microcontroller is a '8 bit Microcontroller' or '4 bit microcontroller' etc. It means that the register is 8 bits or 4 bits long respectively.
Now, each bit of this register can hold either a '0' (zero) or '1' (one).


Let's consider a variable 'A' which has a binary value 1101 (read as, one one zero one).
To convert A to decimal form, follow the following steps:

  • Assign precedence values 0,1,2,3..and so on, to each binary bit starting from the right most bit.
  • Thus in the case of A:






  •  Now, multiply each bit with 2^precedence value. Then add up all the results. 

 Therefore, A (in decimal form) = 1x23 + 1x22 + 0x21 + 1x20 = 1x8 + 1x4 + 0x2 + 1x1 = 8+4+0+1=13
Thus, decimal form of 1101 is 13.
Here, A was a 4 bit register.
Now, consider A to be an 8 bit register. The maximum binary value possible for A=11111111.
Assigning precedence values to A




 Using the same method again, we get A (in decimal form)= 255. Thus, the maximum value of an 8 bit register is 255.


Binary Numbers in C:


When you write A=101, in a C program, the compiler will interpret it as one hundred and one, which is a decimal number. To specify that a number is binary, we need to prefix a '0b' before that number.
The statement, 


A=0b11001101;


implies that A stores a binary value 11001101 (one one zero zero one one zero one). The bit pattern 11001101 is assigned to A. Here, A is assumed to be a 8 but register. If A were a 4 bit register, then only the first 4 bits, from the right would be stored and the rest would be neglected.


Tuesday, February 1, 2011

DDR, PORT, PIN


The contents of DDR decide whether a particular pin of the microcontroller acts as an INPUT pin, that is, it’ll be used to get an input from the outside world, or as an output, that is, it’ll be used to give an output to the outside world.
For DDR register,
 1 --> Output
0 --> Input

If I set a particular bit of the DDR register as 1, it means that the pin number, corresponding to that  bit number will work as an output pin. If a bit is made 0, the pin number corresponding to that particular bit will act as in input.
Please note that pin number and bit number count starts from 0. That means, PA0 is the 1st pin and PA7 is the 8th pin.
Let’s say we want the 3rd pin ( that means, PA2) of Port A to function as an output pin. This is what the DDRA register will look like


Thus, while writing the program in WinAVR, we can simply write the statement as
DDRA=0x80;   // this statement will make PA2 an output pin

Similarly, PORTA is used for assigning a HIGH (1) or a LOW (0) signal to an output pin.
When we want to check whether an input pin is receiving a HIGH (1) or a LOW (0) we use PIN.