AVR : Tutorial 2 : AVR – Input / Output
Posted by Omkar on February 12, 2008
UPDATE : 10 FEB 08 – illustration added
Tutorial
Overview
You cannot imagine to use microcontroller without using any of its i/o pins. Finally its all about : taking input , processing it and generating output ! Thus i/o registers and their correct settings is indispensable part while learning to program any uC.
We will learn how to use AVR ports and actually ‘code’ for writing/reading data to/from port pins. It is slightly confusing for beginners, however once you understand it, you will certainly appreciate the way it is designed.
NOTE : I will frequently refer to ‘configuring pin’ or simply ‘pin’. Remember, a port has multiple pins. Thus in order to change setting for one port, you have to change setting for all port pins of that port. To change setting for one single pin of the port, you have to change a particular bit in associated register. Got that ? If not read this para again.
Registers
AVR is 8 bit microcontroller. All its ports are 8 bit wide. Every port has 3 registers associated with it each one with 8 bits. Every bit in those registers configure pins of particular port. Bit0 of these registers is associated with Pin0 of the port, Bit1 of these registers is associated with Pin1 of the port, …. and like wise for other bits.
These three registers are as follows :
(x can be replaced by A,B,C,D as per the AVR you are using)
- DDRx register
- PORTx register
- PINx register
DDRx register
DDRx (Data Direction Register) configures data direction of port pins. Means its setting determines whether port pins will be used for input or output. Writing 0 to a bit in DDRx makes corresponding port pin as input, while writing 1 to a bit in DDRx makes corresponding port pin as output.
example:
- to make all pins of port A as input pins :
DDRA = 0b00000000; - to make all pins of port A as output pins :
DDRA = 0b11111111; - to make lower nibble of port B as output and higher nibble as input :
DDRB = 0b00001111;
PINx register
PINx (Port IN) used to read data from port pins. In order to read the data from port pin, first you have to change port’s data direction to input. This is done by setting bits in DDRx to zero. If port is made output, then reading PINx register will give you data that has been output on port pins.
Now there are two input modes. Either you can use port pins as tri stated inputs or you can activate internal pull up. It will be explained shortly.
example :
- to read data from port A.
DDRA = 0x00; //Set port a as input x = PINA; //Read contents of port a
PORTx register
PORTx is used for two purposes.
1) To output data : when port is configured as output
When you set bits in DDRx to 1, corresponding pins becomes output pins. Now you can write data into respective bits in PORTx register. This will immediately change state of output pins according to data you have written.
In other words to output data on to port pins, you have to write it into PORTx register. However do not forget to set data direction as output.
example :
- to output 0xFF data on port b
DDRB = 0b11111111; //set all pins of port b as outputs PORTB = 0xFF; //write data on port
- to output data in variable x on port a
DDRA = 0xFF; //make port a as output PORTA = x; //output variable on port
- to output data on only 0th bit of port c
DDRC.0 = 1; //set only 0th pin of port c as output PORTC.0 = 1; //make it high.
2) To activate/deactivate pull up resistors – when port is configures as input
When you set bits in DDRx to 0, i.e. make port pins as inputs, then corresponding bits in PORTx register are used to activate/deactivate pull-up registers associated with that pin. In order to activate pull-up resister, set bit in PORTx to 1, and to deactivate (i.e to make port pin tri stated) set it to 0.
In input mode, when pull-up is enabled, default state of pin becomes ’1′. So even if you don’t connect anything to pin and if you try to read it, it will read as 1. Now, when you externally drive that pin to zero(i.e. connect to ground / or pull-down), only then it will be read as 0.
However, if you configure pin as tri state. Then pin goes into state of high impedance. We can say, it is now simply connected to input of some OpAmp inside the uC and no other circuit is driving it from uC. Thus pin has very high impedance. In this case, if pin is left floating (i.e. kept unconnected) then even small static charge present on surrounding objects can change logic state of pin. If you try to read corresponding bit in pin register, its state cannot be predicted. This may cause your program to go haywire, if it depends on input from that particular pin.
Thus while, taking inputs from pins / using micro-switches to take input, always enable pull-up resistors on input pins.
NOTE : while using on chip ADC, ADC port pins must be configured as tri stated input.
example :
- to make port a as input with pull-ups enabled and read data from port a
DDRA = 0x00; //make port a as input PORTA = 0xFF; //enable all pull-ups y = PINA; //read data from port a pins
- to make port b as tri stated input
DDRB = 0x00; //make port b as input PORTB = 0x00; //disable pull-ups and make it tri state
- to make lower nibble of port a as output, higher nibble as input with pull-ups enabled
DDRA = 0x0F; //lower nib> output, higher nib> input PORTA = 0xF0; //lower nib> set output pins to 0, //higher nib> enable pull-ups
Summery
Following table lists register bit settings and resulting function of port pins
| register bits → pin function↓ |
DDRx.n | PORTx.n | PINx.n |
| tri stated input | 0 | 0 | read data bit x = PINx.n; |
| pull-up input | 0 | 1 | read data bit x = PINx.n; |
| output | 1 | write data bit PORTx.n = x; |
n/a |
Hands on …
-You can type following programs in CodeVisionAVR and test them on your development kit .
- To know, how to burn code into uC using PonyProg2000, click here.
- If you don’t have development kit, simply connect 8 LEDs to PB (i.e port b).
- In Project>Configure>C compiler do not forget to set following options :
Chip : ATmega16 (or whatever you are using)
Clock : 16MHz (or whatever you are using)
- Experiment with these programs and try to learn more from it.
1) Blink LED on PB0 at a rate of 1Hz.
#include <mega16.h> #include <delay.h> void main() { DDRB = 0xFF; //PB as output PORTB= 0x00; //keep all LEDs off while(1) { PORTB.0=0; //turn LED off delay_ms(500); //wait for half second PORTB.0=1; //turn LED on delay_ms(500); //wait for half second }; }
Download Link for illustration.
- Kit : use SW0, SW1
- No Kit : Connect a 2 micro-switches between pin PC0,PC2 and ground. So that when you press the switch pin is pulled low.
#include <mega16.h> #include <delay.h> //declare global arrays for two patterns unsigned char p1[4] = { 0b10000001, 0b01000010, 0b00100100, 0b00011000 }; unsigned char p2[4] = { 0b11111111, 0b01111110, 0b00111100, 0b00011000 }; void main() { unsigned char i; //loop counter DDRB = 0xFF; //PB as output PORTB= 0x00; //keep all LEDs off DDRC = 0x00; //PC as input PORTC.0 = 1; //enable pull ups for PORTC.1 = 1; //only first two pins while(1) { //# if SW0 is pressed show pattern 1 if(PINC.0==0) { for(i=0;i<3;i++) { PORTB=p1[i]; //output data delay_ms(300); //wait for some time } PORTB=0; //turn off all LEDs } //# if SW1 is pressed show pattern 2 if(PINC.1==0) { for(i=0;i<3;i++) { PORTB=p2[i]; //output data delay_ms(300); //wait for some time } PORTB=0; //turn off all LEDs } }; }

mohraz said
I was looking for tracking device code, my avr is connected with a atmel flash memory can someone help me regarding this.. I will be highly grateful to you.
Minimus usb (or my quest to flash some LEDs) « Kevin's Blog said
[...] so I looked up the basics of driving an AVR to make its input/output ports work. I stumbled on this explanation, telling me about the main three registers and pull-up resistors and so on, which was very [...]
Ariz Zubair said
it was quite useful .
Can u please help me with receiving 16 bit serial input on porta.1 and output the parallel data on portb and port c.
Thoufeeq said
Thanks for the article, was quite helpful…
Rafael said
Thanks! With this info I can work with input!
kingsley said
How can i use ATmega16 16 bits timer to create delays
Omkar said
Configure the timer in CTC top mode, set the top count in OCR register and wait till the count match occurs. This will give u variable delays.
kingsley said
Thanks for the hint, to be frank i’m new at using AVR. Can you give me any code in C that is used to create the delay.
kingsley said
Thank you so much, your tutorial has given me a head start. I really appreciate your effort simplifying AVR programming
Omkar said
Thank you.
Bishal Paudel said
wow! I was really wondering how the hell was this PINx working? and I got the answer. Thankx admin
DEEN BANDHU AGRAWAL said
wow it had really helped me
PORTD as an input and PORTC as an output said
[...] [...]
atmega 8535 pullup and pull down and sensor input said
[...] [...]
hafxx said
thanks a lot for this information.. very nice.. and its give me some idea/clue to understand basic i/o for microcontroller…
manisha said
What is the meaning of y[0]=(PINA & 0×01);
Omkar said
it means, y[0] will get the value of 0th bit of port A. It will be either 0 or 1.
gautam said
i have error of above program so please tell me solution
kedarnath reddy said
Thanks a lot this gives a clear idea of the Input and Output configuration.
Iqbal said
is there any tutorial for AVR assembler and c language??
hassan said
well there is one at a time, first learn assmbly thn c,, thts recomendation,..
Shakhawat said
Thanx a lot. Its something exxactly, I was looking for.
anoop said
Sir i am saying you my extreme thanks..Actually i was in a problem with the port setting of my ATmega32 controller.Your tutorial help me a lot…Once again i am thanking you..Expect more like this from you..
Omkar said
2010 in review « Electronics – Tuts, tips and much more … said
[...] Posts How to make simple Infrared Sensor ModulesAVR : Tutorial 2 : AVR – Input / OutputMake your own, ultra simple, universal AVR programmer !!Anode and Cathode of LED !AVRDude Tutorial : [...]
Owais said
Thanks alot Sir, Exactly what I was searching.
You really need a big round of applause…. Hats off.
AVR – Input / Output (via Electronics – Tuts, tips and much more …) « $/-/R!J!T's Blog said
[...] Good information about configuring the ports for input/output. UPDATE : 10 FEB 08 – illustration added Tutorial Overview You cannot imagine to use microcontroller without using any of its i/o pins. Finally its all about : taking input , processing it and generating output ! Thus i/o registers and their correct settings is indispensable part while learning to program any uC. We will learn … Read More [...]
Eclipse and the AVR Toolchain « EsotericAlgorithm's Blog said
[...] line up the m328p schematic so I’ve often misplaced a pin and had to test it a couple times. This is very useful especially in its explanation of ports. I’m unsure on why part of that code [...]
rajput vikas singh said
sir i think u should include more led blinking programs to clear the concepts
Munish said
DDRx.n, PORTx.n and PINx.n (n=0..7)do not work in WINAVR. Would have been nice if you added code for that too.
sabeeh said
thx alot man!…this is wht i waz lookin 4…
Marco said
Thank you for the superb tutorial, but there is one thing I don’t fully understand.
I have an input signal and I want it to be 0 when the output device is not connected. You mention to set the PORTX high to achieve pull-up, and set it to zero to achieve tri-state. But I want to achieve pull-down. It isn’t mentioned in the tutorial how to do this. I tried setting neither and just let it choose by it’s own, but I’m not getting a pull-down. Could anyone help me with this?
Omkar said
To do this, make port pin tri stated and then connect external 10K resistor between port pin and ground pin. This 10k resistor will act as a ‘pull down’ resistor. In this way, when device is not connected, pin will get pulled down to ground potential.
kiran said
superb tutorial, first para. gives idea of importance of this tut.
rishi said
i really like ur tutorials.i have doubts in interfacing keyboard with atmega16 using code vision avr.please clarify me the concept and programming.
Priyanka said
Thanx…this is what i was exactly looking for.
saeed said
i can’t run portl and h & k in avr stadio4.micro is atmega2560
Elliot Brown said
<codePINC.1==0</code Is this valid for atmega8 and all compilers? I've heard it doesn't work for all.
Omkar said
- ATmega8 has PORTC and hence you can use the statement if(PINC.1==0) – This statement is valid only in those compilers which support bit level access. For other compilers you can use : if( (PINC & 0×02) == 0)
Tony said
i use AVR Studio, and it doesnt work with single bit acces (PORTC.1 = 1;).
What compiler should i use to make it works?
I work with ATMega16 THX
Omkar said
you can use CodeVisionAVR compiler. Or in AVR Studio you can also write like this : PORTC.1 = 1;.is equivalent to : PORTC = PORTC | 0×01;
MP said
hey man.. what is the equivalent of PORTC.1 = 0; ?????
MP said
hey man.. what is the equivalent of PORTC.1 = 0; ????
Omkar said
“PORTC.1 = 0″
is equivalent to :
“PORTC = PORTC & 0b11111101″
fabrizio said
Mate,
this is exactly what I wanted to know !
well done
fabrizio
zayed said
Design and implement a a communication link of two AVR’s using SPI. One AVR is connected to
switches through its GPIO lines. It reads the status of the switches and send it to another using
SPI. The second AVR reads the received data and display it on 7-segment displays. Include a
snapshot of the serial clock and data lines as seen on an oscilloscope.
divyanaidu said
yeah,in a very simple and understanding way explained ,its very helpful for begginers,
i am using atmega2560 –from external sensors to adc through spi communication i suppose to do
would any one send me any source code or something how to implement
naz said
Im including a list of great AVR tutorials on my blog, so ill have to sift through your work and see if I can include your tutorials!!
Command Line Interface (CLI) For AVR « Ashish’s Weblog said
[...] AVR : Tutorial 2 : AVR – Input / Output [...]
almostnone said
Thanks. This helped me understand Atmega1280 as well.
noufal said
Halo, I’m just beginner of programming AVR and I have some problems. I’m working with AVR Studio 4 and writing a program for ATmega16 TIMER0 normal mode in assembly language..the code is
.equ TCCR0=$33
.equ TCNT0=$32
.equ TIFR=$38
.cseg
.org 0×00
JMP MAIN
MAIN:
LDI R16,0X02
out TCCR0,R16
l1: SBIS TIFR,0
JMP L1
JMP MAIN
when compiling it shows the error
D:\avr\timer.asm(13): error: Operand 1 out of range: 0×38
D:\avr assem\timer.asm(22): No EEPROM data, deleting D:\avr assem\timer.eep
please help me to find the error… hopefully
praveen said
please post AVR : Tutorial 3.
Ur first two were very informative, so please post AVR : Tutorial 3
write abt advance prog n burning da hex file in da uC
Niklas said
Very nice and informative tutorial. Please post more of these tutorials they are really usefull for me, on the right level so to speak.
Perhaps you can recommend some other resoures for beginners, perhaps the ones who helped you when you first got started.
I look forward to your next post, its been 8 months!
/Niklas
josh said
never mind, I found it. This site is very helpful, keep it up.
josh said
hi, where can i find the mega16 and delay header file? I have the original AVR library but has none of those file in it.
Josh
aak fajar said
In datasheet ATMega8535, ADC has 10-bir resolution. But I can’t setting ADC in this resolution (10-bit). May u can help me how to setting ADC in ATMega8535 with 10-bit resolution. Or may be i must to add other circuit to use ADC 10-bit?
I hope u can reply this question ini my mail. Thanks.
harsh said
How to burn a program from computer to atmega16 microcontroller using ping prong.
Omi said
>>Avinash
I don’t think its possible to overclock low speed (L) versions. I have tried overclocking 16PU versions and they work fine. 16PU can be overclocked upto 24MHz, but you should give supply voltage of 5.5 and not 5.0. Whenever you overclock, you should increase supply voltage upto (just less than) maximum limit of the chip for proper operation at elevated clock rate. However don’t run it at 24MHz unless really required. In my opinion you can run it safely upto 20MHz.
Avinash Gupta said
Nice work. Have you tried overclocking avrs. Can the lower power versions (L) can be made to run with speed more than 8Mhz?
Omi said
>>Sri Ram
I will post tutorial on interrupts soon.
Sri Ram Kishore said
Thank you very much. U tutorial really helped me in understanding i/o ports. Though I did not understand clearly (I am not EEE) the concept of impedance for tri state input, but it clarified the main concept how to use ports for different purposes. It seems to me your knowledge of AVR programming was mastered, can you please send me tutorial on interrupts and interrupt vectors (mega128 or similar) to my mail vsriramkshdev@gmail.com if you have any. Any help will be much appreciapted. Thank you.
Omi said
@Donatas : Whats this “delay.h” stuff ???
CONTINUED …..
In above function some delay will be generated by loop at line 5. You can change the loop count to adjust the delay. You can fix the loop count by some trial and error for 1ms or so and then use that function. You can also put lots of assembly “NOP” instructions inside loop at line 5 and get some predictable delay. For example if your uC is operating at 8MHz, then one NOP will take 125ns …
001: void my_delay_ms(unsigned int m )
002: {
003: unsigned char p;
004: for( ;m>0;m=m-1 )
005: for(p=0;p<100;p++) //This will generate approximate delay
006: { //of 1ms using NOPs
007: #asm(“nop” )
008: #asm(“nop” )
009: #asm(“nop” )
010: #asm(“nop” )
011: #asm(“nop” )
012: // … repeate total 80 times. So these NOPs will
013: // give delay of 80 x 125ns = 10uS
014:
015: }
016: }
This function will provide approximate delay in multiples of 1ms. Delay is approximate because, delay occured by instructions required for looping are ignored. Because of this actual delay will be slightly more than the specified one.
Omi said
@Donatas : Whats this “delay.h” stuff ???
You have mentioned AVR studio 4 but not mentioned which compiler you are using. Anyways … many AVR C compilers have built-in delay functions to ease programming. They are defined in delay.h.
In above program, to generate delay I am using such library function “delay_ms()”. It is defined in “delay.h” (for this specific compiler, i.e. codevisionavr) and hence included. See the code vision avr help for more details of “delay_ms()”.
For avr-gcc, similar file is “util/delay.h”. See this for more information about this file.
http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html
Alternatively, if you don’t want to use built in delay, you can make some function like this :
001: void some_delay(unsigned int some_number )
002: {
003: unsigned long int p;
004: for( ;some_number>0;some_number=some_number-1 )
005: for(p=0;p<300000;p++ )
006: {
007: }
008: }
Donatas said
Hi, I’m just beginner of programming microcontrollers and I have some problems. I’m working with AVR Studio 4 and writing a program for ATmega16. In your examples and in a lot of other examples delay.h is included, but I can’t find it and for this reason I have an error. What I should do and where I can find this file?
P.S.: it would be very nice if you write some examples about processor sleep mode and saving battery when mC is doing nothing.
Benzun said
I must say your tutorial is very good.. i am just entering second yr… and was never clear about avr pin setting.. but your tutorial cleared a lot of doubts.. can u just explain me the purpose of pull up… i dont understand it clearly.. if u have time can u pls mail me at benzun1999@gmail.com ?? must say your work is awesome.. you have a very clear understanding of avr programming….
Ashutosh said
Actually iam using two ir sensors kept at a fixed distance.Both connected to two adc pins of atmega8L.When a object passes in front of first sensor,the analogue signal is taken and converted into digital and goes to pc via parallel port,here a timer starts as the signal is received and stops on receiving second signal.As distance is known and time ir there,speed can be calculated.I want to know abt how to go for programing.
elecrom said
@Ashutosh
I didn’t get what u say.
Ashutosh said
Hey i need to use adc port of atmega8L to receive input from ir sensors and then send to the parallel port to measure speed. Guide me in programming part.
ashishd said
Omkar, Can u created swf file?
Are we not suppose to upload files?
Tachometer using AVR Atmega16 « Ashish’s Weblog said
[...] AVR : Tutorial 2 : AVR – Input / Output [...]