[digg=http://digg.com/programming/AVR_Tutorial_2_AVR_Input_Output]
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 Atmel AVR’s GPIO ports and actually ‘code’ for writing/reading data to/from port pins in this AVR tutorial. It is slightly confusing for beginners, however once you understand it, you will certainly appreciate the way it is designed. To get quick background about AVR microcontrollers, refer to Intoduction to AVR Tutorial on this blog.
[toc]
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
Atmel 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 |= 0b00000001; //set only 0th pin of port c as output PORTC |= 0b00000001; //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
Summary
Following table lists register bit settings and resulting function of port pins. Note: Convention of “x.n” is a psuedo code. You need to use appropriate AND (&), OR (|), and bitshift (<<, >>) operations to extract the desired bit field.
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; |
writing 1 toggles the state of the output pin. PINx.n = 1; |
Hands on …
- You can type following programs in CodeVisionAVR or Atmel Studio and test them on your development kit .
- To know, how to burn code into uC using PonyProg2000, refer to the post on Making and Using Simple AVR Programmer. You can also use USBasp and Avrdude to program AVR controllers. Refer to the Avrdude tutorial to understand how to download/burn programs on AVR microcontroller.
- 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.
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 &= 0b11111110; //turn LED off delay_ms(500); //wait for half second PORTB |= 0b00000001; //turn LED on delay_ms(500); //wait for half second }; }
Blink LEDs on PB with different patterns according to given input.
– 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 |= 0b00000011; //enable pull ups for //only first two pins while(1) { //# if SW0 is pressed show pattern 1 if((PINC & 0b00000001)==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 & 0b00000010)==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 } }; }
Other AVR Tutorials
- Lot more examples of AVR GPIO setup and control are listed in this post: ATMEL AVR Tips – Input Output Ports Code Snippets
- A Video lecture on Introductory AVR programming and GPIO configuration is here: AVR microcontroller video tutorial – Part 1
#atmel-avr #avr #gpio #pin #ddr #port #tutorial
#
Hi everybody!
How can I use adc with 2 inputs?
#
for a burglar alarm system having 8 digital and 2 analog presence detection sensor. Write a code for monitoring all the sensors contionously and display the values on serial terminal using serial port in the following format?
Can some one make the code in C language?
#
Awesome explanation. Thank you.
#
Thanks you, it help me a lot 😀
#
Thanks … please share it with your friends if you have liked it 🙂
#
really, good tutorial,why dont you continue this tutorials?
#
Thanks 😀 … I’m glad to know that even after so many years, it still holds value for the readers.
Your comments are encouraging. I will try to write more and more tutorials in celecromng months 🙂
#
hi,i am a bad bad beginner.Have a Question:
I want to send a message(Password) from mobile to bluetooth module HC05 and next, to AVR Atmega32a.
and in the AvR, check if it is the right string(password) defined in the AVR or not!
[if true], blink an LED.
[else] message back “Wrong Password”. and this message goes the other way round!(AVR–>Bluetooth module–>Mobile)
How to do this? Actually i have problem with the code,Dont know what to write for it?
i just did supply the power to HC05 and rx to tx of avr,and tx to rx of avr.
Thanks in advance
#
thank you, it helped me
#
all post by me r for aTmega 32 UC
#
to receive data on rx pin frm receiver module
is dis da correct command
DDRD=0X00;
PORTD.0= 1;
#
to get input on adc pins is dis da right command
DDRA= 0X00
PORTA0X00
REPLY ME FAST.
#
This arctile shows how pointer and its massive works.thanks
#
I am really loving the theme/design of your web site.
Do you ever run into any browser compatibility issues? A number of my
blog audience have complained about my website not operating correctly in Explorer but looks great in Firefox.
Do you have any solutions to help fix this problem?
#
This is developed using standard wordpress templates. These templates are well tried and tested and work properly on most of the platforms.
#
why we are not getting the voltage at the specified port
#
i have flashed the servo program in the ATMEGA 8L controller and practically checking the controller by connecting the servo . servo was not running and we didn’t get the voltage at the output port .
#
same characters data is given into microcontroller atmega16L but it is taking some of the continous same bits as different.
help to resolve the problem
#
i tried to read keypad from portA and use pull ups but it displayed random numbers. can you help??
#
The DDRC.0 = 1; format doesn’t work for me. I get something like:
expected ‘;’ before numeric constant
I have to mask the relevant bits to make it happen. Is it just me?
#
DDRC.0 = 1; >> This format is supported by CodeVisionAVR compiler. Other standard C compilers don’t support it, so you will have to do masking.
#
How can we do this type of programming in AVR Studios ?? I am not able to get how to address the particular pins of a port.
#
Here’s some example of how you can manipulate a single bit in AVR Studio
DDRx &= ~(1<<4); //To clear a bit (Same as DDRx.4 = 0)
DDRx |= ~(1<<4); //To set a bit (Same as DDRx.4 = 1)
DDRx ^= ~(1<<4); //TOGGLE bit 4 in DDRx register
x Can be A,B,C,D … depending on what you need to change
4 Can be 0-7 (the bit number you want to change)
You can also change an entire port value with 1 command
DDRB = 0xFF; //0b11111111
PORTB = 0x07 ; //0b00000111
#
DDRx &= ~(1<<4); //To clear a bit (Same as DDRx.4 = 0)
DDRx |= (1<<4); //To set a bit (Same as DDRx.4 = 1)
DDRx ^= (1<<4); //TOGGLE bit 4 in DDRx register
The first were OK 🙂
Hi
#
I don’t understand how to set an interupt. Can you help me, if I want to program atmega 8535 with interupt after 1 minute. I really need some help 🙁
#
THANKS A LOT. REALLY THANK YOU 🙂
#
Its a great start for freshers…thanks.
#
Now can you make a tutorial for AVR32? I can’t make a freakin port any which way and Atmel Studio 6 won’t let you..
#
thanks a lot
#
Thanks a lot, great tutorial for someone just starting with the Atmega series!
#
Very neat and easy tutorial about AVR I/O, the overall credit goes to omkar. The article presentation is very impressive!
#
#
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.
#
Thanks for the article, was quite helpful…
#
Thanks! With this info I can work with input! 🙂
#
How can i use ATmega16 16 bits timer to create delays
#
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.
#
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.
#
Thank you so much, your tutorial has given me a head start. I really appreciate your effort simplifying AVR programming
#
Thank you.
#
wow! I was really wondering how the hell was this PINx working? and I got the answer. Thankx admin
#
wow it had really helped me
#
#
#
thanks a lot for this information.. very nice.. and its give me some idea/clue to understand basic i/o for microcontroller…
#
What is the meaning of y[0]=(PINA & 0x01);
#
it means, y[0] will get the value of 0th bit of port A. It will be either 0 or 1.
#
i have error of above program so please tell me solution
#
how to declare the y[0] over here
#
Thanks a lot this gives a clear idea of the Input and Output configuration.
#
is there any tutorial for AVR assembler and c language??
#
well there is one at a time, first learn assmbly thn c,, thts recomendation,..
#
Thanx a lot. Its something exxactly, I was looking for.
#
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..
#
🙂 … thanks for appreciation.
#
#
Thanks alot Sir, Exactly what I was searching.
You really need a big round of applause…. Hats off.
#
#
#
sir i think u should include more led blinking programs to clear the concepts
#
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.
#
thx alot man!…this is wht i waz lookin 4…
#
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?
#
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.
#
superb tutorial, first para. gives idea of importance of this tut.
#
i really like ur tutorials.i have doubts in interfacing keyboard with atmega16 using code vision avr.please clarify me the concept and programming.
#
Thanx…this is what i was exactly looking for.
#
i can’t run portl and h & k in avr stadio4.micro is atmega2560
#
<codePINC.1==0</code Is this valid for atmega8 and all compilers? I've heard it doesn't work for all.
#
– 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 & 0x02) == 0)
#
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
#
you can use CodeVisionAVR compiler. Or in AVR Studio you can also write like this : PORTC.1 = 1;.is equivalent to : PORTC = PORTC | 0x01;
#
hey man.. what is the equivalent of PORTC.1 = 0; ?????
#
hey man.. what is the equivalent of PORTC.1 = 0; ????
#
“PORTC.1 = 0”
is equivalent to :
“PORTC = PORTC & 0b11111101”
#
Mate,
this is exactly what I wanted to know !
well done
fabrizio
#
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.
#
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
#
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!!
#
#
Thanks. This helped me understand Atmega1280 as well.
#
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 0x00
JMP MAIN
MAIN:
LDI R16,0X02
out TCCR0,R16
l1: SBIS TIFR,0
JMP L1
JMP MAIN
when compiling it shows the error
D:avrtimer.asm(13): error: Operand 1 out of range: 0x38
D:avr assemtimer.asm(22): No EEPROM data, deleting D:avr assemtimer.eep
please help me to find the error… hopefully
#
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
#
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
#
never mind, I found it. This site is very helpful, keep it up.
#
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
#
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.
#
How to burn a program from computer to atmega16 microcontroller using ping prong.
#
>>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.
#
Nice work. Have you tried overclocking avrs. Can the lower power versions (L) can be made to run with speed more than 8Mhz?
#
>>Sri Ram
I will post tutorial on interrupts soon.
#
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.
#
@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.
#
@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: }
#
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.
#
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….
#
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.
#
@Ashutosh
I didn’t get what u say.
#
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.
#
Elecrom, Can u created swf file?
Are we not suppose to upload files?
#