Making a pin go high

I found this great description of AVR I/O in the Proycon AVRLib. Click here to view a text file with the extract explaining AVR I/O.

Once you've read that description look here at the pin configuration of the AT90s2313. This is taken from the datasheet

You can see Port B running from pin number 12 to pin 19. In our example program we will make pin PB2 (pin 14) go high (5 volts).

By including #include <avr/io.h> in our code, we can access Port B by changing the values stored at PORTB.

Now, the needed line of code is:

PORTB |=(1<<2);

'|' Bitwise OR operator

The | operater is the bitwise 'OR' operator. Which looks at a pair of 1s or 0s and returns true (1) if one or both of the test set contain a 1.

10010001
11001100 'bitwise OR'

11011101

'|=' operator

In C, there are lots of shortcuts. One of them is adding an 'equals' sign after an operator. Any operator.

The effect of doing this is to shorten the following statement:

PORTB = PORTB | something

To just:

PORTB |= something

Both statements are the same and do the same thing.

'<<' Shift-Left operator

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

e.g.

0101 << 1 would result in 1010

00100000 << 2 would result in 10000000

00000001 << 4 would reuslt in 00010000

Thus in the example line of code we have for making a pin go high, the expression (1<<2) is the same as (00000001 << 2) and results in 00000100. The reason we use it is so when we want it to change another pin we just change the 2 to whatever we want. This allows us to not hardcode values if we want to not hardcode values. i.e. the '2' is pulled from a file of another function etc.

Putting it all together (Proof)

If PORTB was 00110011 to begin with and then we ran the line of code:

PORTB |=(1<<2);

The following would happen.

(1<<2) would be evaluated to 00000100 so we could instead write:

PORTB |=(00000100);

Another step would be to expand the |= shortcut, therefore:

PORTB = PORTB | (00000100);

Now the 'PORTB' on the right hand side of the equation represents what the value is, the one on the left is what we want it to be (the result will be stored in  the left hand side, thus the left PORTB represents the final result of the statement and changes PORTB to reflect this).

Thus we can substitute the 'before' value of PORTB in for the right hand side 'PORTB':

PORTB = 00110011 | (00000100);

This becomes:

PORTB = 00110111;

The underlines bit is the one that has changed.

Therefore the single bit that represents the third (PB2) pin on PORTB has been made to go high and no other pins have changed.

Any errors, questions, comments etc can be posted in the forum or sent via the emailpage.

Webpage subject the copyright. No reproduction without express permission of Webmaster (Dingo_aus)

AVR is a trademark of Atmel (see www.atmel.com)