Using the USART of AVR Microcontrollers : Reading and Writing Data
Till now we have seen the basics of RS232 communication, the function of level converter and the internal USART of AVR micro. After understanding the USART of AVR we have also written a easy to use function to initialize the USART. That was the first step to use RS232. Now we will see how we can actually send/receive data via rs232. As this tutorial is intended for those who are never used USART we will keep the things simple so as to just concentrate on the "USART" part. Of course after you are comfortable with usart you can make it more usable my using interrupt driven mechanism rather than "polling" the usart.
So lets get started! In this section we will make two functions :-
- USARTReadChar() : To read the data (char) from the USART buffer.
- USARTWriteChar(): To write a given data (char) to the USART.
This two functions will demonstrate the use of USART in the most basic and simplest way. After that you can easily write functions that can write strings to USART.
Reading From The USART : USARTReadChar() Function.
This function will help you read data from the USART. For example if you use your PC to send data to your micro the data is automatically received by the USART of AVR and put in a buffer and bit in a register (UCSRA) is also set to indicate that data is available in buffer. Its now your duty to read this data from the register and process it, otherwise if new data comes in the previous one will be lost. So the funda is that wait until the RXC bit (bit no 7) in UCSRA is SET and then read the UDR register of the USART.
(See the full description of USART registers)
char USARTReadChar()
{
//Wait untill a data is available
while(!(UCSRA & (1<<RXC)))
{
//Do nothing
}
//Now USART has got data from host
//and is available is buffer
return UDR;
}
Writing to USART : USARTWriteChar()
This function will help you write a given character data to the USART. Actually we write to the buffer of USART and the rest is done by USART, that means it automatically sends the data over RS232 line. One thing we need to keep in mind is that before writing to USART buffer we must first check that the buffer is free or not. It its not we simply wait until it is free. If its not free it means that USART is still busy sending some other data and once it finishes it will take the new data from buffer and start sending it.
Please not that the data held in the buffer is not the current data which the USART is busy sending. USART reads data from the buffer to its shift register which it starts sending and thus the buffer is free for your data. Every time the USART gets it data from buffer and thus making it empty it notifies this to the CPU by telling "USART Data Register Ran Empty" (UDRE) . It does so by setting a bit (UDRE bit no 5) in UCSRA register.
So in our function we first wait until this bit is set (by the USART ), once this is set we are sure that buffer is empty and we can write new data to it.
(See the full description of USART registers)
void USARTWriteChar(char data)
{
//Wait until the transmitter is ready
while(!(UCSRA & (1<<UDRE)))
{
//Do nothing
}
//Now write the data to USART buffer
UDR=data;
}
Note: Actually their are two separate buffers, one for transmitter and one for receiver. But they share common address. The trick is that all "writes" goes to the Transmitter's buffer while any "read" you performs comes from the receiver's buffer.
That means if we read UDR we are reading from receivers buffer and when we are writing to UDR we are writting to transmitters buffer.
UDR=some_data; //Goes to transmitter
some_data=UDR; //Data comes from receiver
(See the full description of USART registers)
Sample program to use AVR USART
The following program makes use of the two functions we developed. This program simply waits for data to become available and then echoes it back via transmitter but with little modification. For example if you send "A" to it, it will send you back "[A]" that is input data but surrounded by square bracket. This program is enough to test the USART yet easy to understand.
/*
A simple program to demonstrate the use of USART of AVR micro
*************************************************************
See: www.eXtremeElectronics.co.in for more info
Author : Avinash Gupta
E-Mail: me@avinashgupta.com
Date : 29 Dec 2008
Hardware:
ATmega8 @ 16MHz
Suitable level converter on RX/TX line
Connected to PC via RS232
PC Software : Hyper terminal @ 19200 baud
No Parity,1 Stop Bit,
Flow Control = NONE
*/
#include <avr/io.h>
#include <inttypes.h>
//This function is used to initialize the USART
//at a given UBRR value
void USARTInit(uint16_t ubrr_value)
{
//Set Baud rate
UBRRL = ubrr_value;
UBRRH = (ubrr_value>>8);
/*Set Frame Format
>> Asynchronous mode
>> No Parity
>> 1 StopBit
>> char size 8
*/
UCSRC=(1<<URSEL)|(3<<UCSZ0);
//Enable The receiver and transmitter
UCSRB=(1<<RXEN)|(1<<TXEN);
}
//This function is used to read the available data
//from USART. This function will wait untill data is
//available.
char USARTReadChar()
{
//Wait untill a data is available
while(!(UCSRA & (1<<RXC)))
{
//Do nothing
}
//Now USART has got data from host
//and is available is buffer
return UDR;
}
//This fuction writes the given "data" to
//the USART which then transmit it via TX line
void USARTWriteChar(char data)
{
//Wait untill the transmitter is ready
while(!(UCSRA & (1<<UDRE)))
{
//Do nothing
}
//Now write the data to USART buffer
UDR=data;
}
void main()
{
//This DEMO program will demonstrate the use of simple
//function for using the USART for data communication
//Varriable Declaration
char data;
/*First Initialize the USART with baud rate = 19200bps
for Baud rate = 19200bps
UBRR value = 51
*/
USARTInit(51); //UBRR = 51
//Loop forever
while(1)
{
//Read data
data=USARTReadChar();
/* Now send the same data but but surround it in
square bracket. For example if user sent 'a' our
system will echo back '[a]'.
*/
USARTWriteChar('[');
USARTWriteChar(data);
USARTWriteChar(']');
}
}
Running the USART Demo
You can run the above program in a ATmega8, ATmega16, ATmega32 cpu running at 16MHz without any modification. If you are using different clock frequency you have to change the UBRR value that we are passing to USARTInit() function. See previous tutorial for calculating UBRR value. The MCU should be connected to PC using a RS232 level convertor. In PC you can run hyper terminal to send/receive data via usart. Start hyper terminal and press keys on your keyboard. The keys you press will be sent via PC's serial port to the AVR micro where our program will echo it back but with surrounded brackets. The data sent by the MCU will be received by the PC's serial port and will be displayed by the Hyper terminal.
See Also
- Home Made AVR devboard - To experiment with AVR micros first make this.
- Making a RS232 level convertor.
- RS232 / USART related

@Raghu
That will require the knowledge abt the underlying robot hardware like sensor position and number etc …
January 9th, 2009 at 8:53 amHello Avinash
I can send data from my Pc “C#” to Usart ”Atmega32” with RS232 line, it work without problem.
Now I will send the information without RS232 line, I want send the information with Bluetooth. I need a Transmitter and receiver can you recommend me some who is easy to use?
Why you don’t program in CodeVisionAVR it is much easy? And the program is gratis but you must also use AVR Studio for simulation. But write code is much easy with CodeVisionAVR.
Thanks for all your help!!!!
Percy Villegas.
February 18th, 2009 at 4:18 pmhi use this code for intrnal oscilator atmega8 8Mhz baud rate 9600. what all must i change? UBRR=51 ? or what change in software AVR Studio
March 5th, 2009 at 6:25 pmHello Avinash,
you have used UCSRB=(1<<RXEN)|(1<<TXEN); for no interrupt , what should we use if there is a interrupt
March 9th, 2009 at 4:28 pmHello Avinash,
you have used UCSRB=(1<<RXEN)|(1<<TXEN); for no interrupt , what should we use if there is a interrupt, Can you plz help me
March 9th, 2009 at 4:29 pmhello avinash,
there is a program in your tutorial which counts from 0-999 .i want to interface RS232 in the program (USART) so that I can see the increment from 0 to 999 in hyperterminal . I tried to combined your USART program with that but unscessful….
can you please help me out
thanking you
March 16th, 2009 at 7:05 pmritesh kumar
Hello,
Does anyone has this kind of program for a AVR STK128 board with an ATmega128.
greetz
March 16th, 2009 at 7:15 pmhello avinash
March 31st, 2009 at 11:27 amnice job avinash, this is the best avr beginers forum i found on internet.
i have a problem with with an usart implementation.
i tried implementing an usart code for a quizbuzzer system (used 8mhz internal clk so i used USARTInit(25); ).The hyperterminal displayed junk values(like “..[ “) instead of the chars “1″ “2″ or “3″,when i used ur functions.
i even implemented the code given above, but the heyperterminal wasn’t accepting any input or displaying any output.
what could be the fault in this case?
is there a way i can rectify it?
i used a pc with vista installed in it and i used a hyperterminal 6.3 version downloaded from the internet(since i couldn’t find hyperterminal on vista)
thanks
teja
Hello AVANISH
Now you can see what I have do with atmega_32 in the factory Talaris “Teller Cash Dispenser” there we regulate a motor. All the code is do in CodeVisionAVR. You can se the code and one video (10 minutes) about the project here.
http://villegastello.weebly.com/talaris_motorreglering.html
http://video.google.com/videoplaydocid=2332502783057173830
Why you don’t program in CodeVisionAVR? It is easier you know.
thanks
Percy Villegas
April 6th, 2009 at 12:18 pmhi avinash
May 22nd, 2009 at 3:46 pmI burned your code on to my atmega16(4 Mhz external) and 4800 baud using avr burnomat with the settings as fuse>>clock options>>external clock>> ceramic, 3 – 8Mhz. however the hyperterminal shows some garbage value whenever i type character….can you help
Hi Avinash!
Nice Tutorials!
I just tried to build the code in AVR Studio 4, and have a couple of errors due to URSEL. Below is the message screen:
Build started 31.5.2009 at 22:47:50
avr-gcc -mmcu=attiny2313 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT RS232.o -MF dep/RS232.o.d -c ../RS232.c
../RS232.c: In function ‘USARTInit’:
../RS232.c:49: error: ‘URSEL’ undeclared (first use in this function)
../RS232.c:49: error: (Each undeclared identifier is reported only once
../RS232.c:49: error: for each function it appears in.)
../RS232.c: At top level:
../RS232.c:95: warning: return type of ‘main’ is not ‘int’
make: *** [RS232.o] Error 1
Build failed with 3 errors and 1 warnings…
Am I missing a library? I never used ‘C’ before, and barely no anything about assembler….but learning!
Thanks for all your great work!!!!
June 1st, 2009 at 8:19 am-fab
@fabelizer
try compiling for ATmega8
June 1st, 2009 at 9:58 amWill try it. I did go to the tiny3213 data sheet and found there was no such designation. Didn’t have time to check the megas though. I do think that will solve it. Thanks!
June 1st, 2009 at 4:55 pm-fab
why 8051 uses standard baud rate of 9600bps????? reply to my mail
June 13th, 2009 at 12:25 pmHi! all…
July 2nd, 2009 at 10:46 pmI copied the source code into avr studio and build it with WinAvr..but the program doesn’t work…can somebody send the .hex file to romandini.luca@libero.it?? it is so urgent..
P.S. I’m using an atmega8 4MHz external clock 9600 boud..
Thanks for help!!!
July 2nd, 2009 at 10:46 pmHi!
July 13th, 2009 at 6:13 amAny plans to post something using interrupt-driven USART routines?
@Jeff
I have the routines ready but I have to create documentation so that I can post it here.
July 13th, 2009 at 8:18 am[...] introduction. You should also be familiar with RS232 communication. If you are new to it please see RS232 Serial Communication Tutorial. I also recommend using wireless link only after you have successfully tried wired RS232 [...]
August 11th, 2009 at 12:02 pmHello Avinash,
Again a great tutorial!! But “download a pdf version” tab is missing now..
August 11th, 2009 at 5:45 pmThank you for this tutorial it was really help full I used it in an atmega32p with small tweeks to enable dual USART communications at two different speeds. Interrupt driven usart routines will be also very helpful!. Xon/Xoff flow control is something that it been driving me nuts!, do you know where can i get a sample code? or where can i get a better idea of how to implement it?
August 12th, 2009 at 8:06 ami have tried to communicate my bot with pc through uart. i m using avr atmega8.but i m unable to transmit or receive the data. m using 16Mhz crystal.pls rply
September 20th, 2009 at 12:33 pmhi,
Thank u very much for all the tuts.I tried the above said program but when ever I type a letter in hyperteminal I only get a bunch of 9 C’s
October 24th, 2009 at 6:07 pmI dont understand.max232 cirkt is working.I looped it back and saw that working.
Please reply to me as soon as possible.Your solution is worth to me.
hi, really excellent beginner’s tutorial.
Thanks for the job boss.
November 2nd, 2009 at 1:15 amHow do i test serial communication using windows vista (no hyperterminal with vista).
regards,
Ray
November 2nd, 2009 at 7:02 amHello Avinash
today i compile the code given by you in usart_demo.c but when i press f it give fþ6-
and with other like that
c >> f&-
g >> æf
can you tell me what is wrong here
November 29th, 2009 at 1:55 amnow i change MCU freqency to 12MHz,still error is same but echo back in other symbol.
November 29th, 2009 at 2:06 amwhat freqency should i used for propare work of this module
Thanks
If you have Vista and need a terminal google PuttY… a helpfull tool..
Skåååll
Blim
November 29th, 2009 at 5:44 am@Rakesh
WHY DON’T U USE THE FREQ THAT THE PROGRAM IS DEVELOPED FOR ???????????
IT IS CLEARLY WRITTEN IN THE PROGRAM.
WHY ARE U DISTURBING OTHER WITH YOUR VERY SILLY MISTAKE ???
November 29th, 2009 at 8:39 amhey Avinash..
January 29th, 2010 at 1:40 amcongratulations!! Your AVR series of tutorials are among the best that can be found on the internet. Its hard to believe that these tutorials are free of charge. I am doing a project with Atmega32. It uses usart to communicate to a ericsson phone. But the problem is I want pc communication at the same time.As the mobile would take up the usart port how can i implement serial communication for pc?? might be a naive question to ask but I am really confused..
use a second software usart. if u know how usar works (given in details in one of the tuts) then u can easily implement in software . use it for less data intensive line.
January 29th, 2010 at 7:49 amhey avinash !!
January 29th, 2010 at 8:09 amThanx for the quick reply!! you are awesome!! Ya I found out how to use a software UART.Thanks.Cheerz
plz help me
i am using avr atmegs 32 and i am communication with pic microcontroller when i send character values like “ATP” it recognize n respond
and for instance i have to send it data like “0100″ it dosend respond
i am using functions defined above in this tutorial
bt when i send 0100 through hyperterminal the pic controller recognize why does not it recognize integer values from my controller plz helo
January 31st, 2010 at 12:49 amQasim,
You are really not sending an integer value, you are actually sending an ascii value. You must use a function such as atoi (ascii to integer) to convert to an integer if that is what you want to use. Check an ascii code table to see what integers the characters are really sending, and be sure your code can respond to them, or convert them.
-fab
January 31st, 2010 at 11:13 pmavinash,
February 17th, 2010 at 11:09 amgreat explanation! I am currently trying to put this on an ATMega128 board, and it is complaining about alot of things. I fixed alot of them by finding that the board this code was made for has 1 usart, while the one i am using has 2. however i think i got that working, now it is just complaining about the URSEL. any ideas?
hi
the above code is working fine on Atmega32 and 16 but not on attiny2313.I have changed the statement
UCSRC=(1<<URSEL)|(3<<UCSZ0);
February 27th, 2010 at 3:40 pmto
UCSRC = (1 << UCSZ1) | (1 << UCSZ0);
pls help…………