Welcome to the third part of my RS232 serial communication tutorial. Till now we saw the basics of RS232 communication and made our level converter. Now its time to understand the USART of AVR microcontroller and write the code to initialize the USART and use it to send and receive data.
Like many microcontrollers AVR also has a dedicated hardware for serial communication this part is called the USART - Universal Synchronous Asynchronous Receiver Transmitter. This special hardware make your life as programmer easier. You just have to supply the data you need to transmit and it will do the rest. As you saw serial communication occurs at standard speeds of 9600,19200 bps etc and this speeds are slow compared to the AVR CPUs speed. The advantage of hardware USART is that you just need to write the data to one of the registers of USART and your done, you are free to do other things while USART is transmitting the byte.
Also the USART automatically senses the start of transmission of RX line and then inputs the whole byte and when it has the byte it informs you(CPU) to read that data from one of its registers.
The USART of AVR is very versatile and can be setup for various different mode as required by your application. In this tutorial I will show you how to configure the USART in a most common configuration and simply send and receive data. Later on I will give you my library of USART that can further ease you work. It will be little complicated (but more useful) as it will have a FIFO buffer and will use interrupt to buffer incoming data so that you are free to anything in your main() code and read the data only when you need. All data is stored into a nice FIFO(first in first out queue) in the RAM by the ISR.
USART of AVR Microcontrollers.
The USART of the AVR is connected to the CPU by the following six registers.
- UDR - USART Data Register : Actually this is not one but two register but when you read it you will get the data stored in receive buffer and when you write data to it goes into the transmitters buffer. This important to remember it.
- UCSRA - USART Control and status Register A : As the name suggests it is used to configure the USART and it also stores some status about the USART. There are two more of this kind the UCSRB and UCSRC.
- UBRRH and UBRRH : This is the USART Baud rate register, it is 16BIT wide so UBRRH is the High Byte and UBRRL is Low byte. But as we are using C language it is directly available as UBRR and compiler manages the 16BIT access.
So the connection of AVR and its internal USART can be visualized as follows.
![]() |
Fig- AVR USART registers. |
Registers Explained
In order to write programs that uses the USART you need to understand what each register's importance. The scheme behind using the AVR USART is same as with any other internal peripheral (say ADC). So if you are new to this topic please see this tutorial, it shows you the basic idea of using peripherals.
I am not going to repeat what is already there in the datasheets, I will just tell about what is required for a quick startup. The datasheets of AVR provides you with all the details of every bit of every register so please refer to it for detailed info. Note bit names with RED background are of our interest here.
UDR: Explained above.
UCSRA: USART Control and Status Register A
*****************************************
Bit No |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Name |
RXC |
TXC |
UDRE |
FE |
DOR |
PE |
U2X |
MPCM |
Initial Val |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
0 |
RXC this bit is set when the USART has completed receiving a byte from the host (may be your PC) and the program should read it from UDR
TXC This bit is set (1) when the USART has completed transmitting a byte to the host and your program can write new data to USART via UDR
UCSRB: USART Control and Status Register B
*****************************************
Bit No |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Name |
RXCIE |
TXCIE |
UDRIE |
RXEN |
TXEN |
UCSZ2 |
RXB8 |
TXB8 |
Initial Val |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
RXCIE: Receive Complete Interrupt Enable - When this bit is written one the the associated interrupt is enabled.
TXCIE: Transmit Complete Interrupt Enable - When this bit is written one the the associated interrupt is enabled.
RXEN: Receiver Enable - When you write this bit to 1 the USART receiver is enabled. The normal port functionality of RX pin will be overridden. So you see that the associated I/O pin now switch to its secondary function,i.e. RX for USART.
TXEN: Transmitter Enable - As the name says!
UCSZ2: USART Character Size - Discussed later.
For our first example we won't be using interrupts so we set UCSRB as follows
UCSRB=(1<<RXEN)|(1<<TXEN);
UCSRC: USART Control And Status Register C
*****************************************
Bit No |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
Name |
URSEL |
UMSEL |
UPM1 |
UPM0 |
USBS |
UCSZ1 |
UCSZ0 |
UCPOL |
Initial Val |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
IMPORTANT : The UCSRC and the UBRRH (discussed below) register shares same address so to determine which register user want to write is decided with the 7th(last) bit of data if its 1 then the data is written to UCSRC else it goes to UBRRH. This seventh bit is called the
URSEL: USART register select.
UMSEL: USART Mode Select - This bit selects between asynchronous and synchronous mode. As asynchronous mode is more popular with USART we will be using that.
UMSEL |
Mode |
0 |
Asynchronous |
1 |
Synchronous |
USBS: USART Stop Bit Select - This bit selects the number of stop bits in the data transfer.
USBS |
Stop Bit(s) |
0 |
1 BIT |
1 |
2 BIT |
UCSZ: USART Character size - These three bits (one in the UCSRB) selects the number of bits of data that is transmited in each frame. Normally the unit of data in MCU is 8BIT (C type "char") and this is most widely used so we will go for this. Otherwise you can select 5,6,7,8 or 9 bit frames!
UCSZ2 |
UCSZ1 |
UCSZ0 |
Character Size |
0 |
0 |
0 |
5Bit |
0 |
0 |
1 |
6Bit |
0 |
1 |
0 |
7Bit |
0 |
1 |
1 |
8Bit |
1 |
0 |
0 |
Reserved |
1 |
0 |
1 |
Reserved |
1 |
1 |
0 |
Reserved |
1 |
1 |
1 |
9Bit |
So we set UCSRC as follows
UCSRC=(1<<URSEL)|(3<<UCSZ0);
UBRR: USART Baud Rate Register:
*********************************
This is the USART Baud rate register, it is 16BIT wide so UBRRH is the High Byte and UBRRL is Low byte. But as we are using C language it is directly available as UBRR and compiler manages the 16BIT access. This register is used by the USART to generate the data transmission at specified speed (say 9600Bps). To know about baud rate see the previous tutorial. UBRR value is calculated according to following formula.

Where fosc is your CPU frequency say 16MHz
Baud Rate is the required communication speed say 19200 bps (see previous tutorial for more info).
Example:
For above configuration our UBRR value comes to be 51.083 so we have to set
UBRR=51;
in our initialization section. Note UBRR can hold only integer value. So it is better to use the baud rates that give UBRR value that are purely integer or very close to it. So if your UBRR value comes to be 7.68 and you decided to use UBRR=8 then it has high error percentage, and communication is unreliable!
You may also use our Androd App for calculating the UBRR much easily ! It can run on Smartphones and Tablets running Android OS.
Fig. - AVR UBRR Calculator for Android |
Download
Initialization of USART
Before using the USART it must be initialized properly according to need. Having the knowledge of RS232 communication and Internal USART of AVR you can do that easily. We will create a function that will initialize the USART for us.
#include <avr/io.h>
#include <inttypes.h>
void USARTInit(uint16_t ubrr_value)
{
//Set Baud rate
UBRR= ubrr_value;
/*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);
}
Now we have a function that initializes the USART with a given UBRR value.
That's it for now friends. In next tutorial we will learn how to send and receive data over RS232 channel. Don't forget to post your opinion or doubts or any suggestion I would be very happy to see them. So don't wait post a comment now !
Other Parts of this Tutorial
- RS232 Communication – The Basics
- RS232 Communication – The Level Conversion
- Using the USART of AVR Microcontrollers.
- Using the USART of AVR Microcontrollers : Reading and Writing Data
- Visualize ADC data on PC Screen using USART – AVR Project




Brilliant series of microcontroller tutorials…!!! Hats off…!!
You must seriously write a book..
Btw, I wanted to ask if i can use a normal bluetooth dongle instead of a dedicated bluetooth module. My bluetooth dongle has an ISSC chipset that supports HCI UART. So can I use HCI on ATMega16..?
sir
i have gone through your tutorials all were very nice and helpful. as i am new to this uart i have a atmega 128 kit (uniboard) given from my college. i need to transmit a data from hyper terminal to the microcontroller and need to display the value in the lcd provided in it. can you give me some guidance in it.
thanking you
dam
@Sam Joshua,
Please ask Uniboard dealer or your college for any help. Because they are the one who are getting paid from your Pocket.
We are not here to do the real magic for free.
Yes I may sound rude. But I cannot do a free tech support for Other Companies Board.
So please keep away such topics from here.
@Avinach
But you are paid NOT to be rude…!
@Ariyo
Who the hell pays me? !!!
I love your blog, great article, many thanks!
Hi
It is very usefull to us….
Hi dear Avinash
Where can I find some tutorial to better understand of bitwise operations you use in functions? For example, what does this mean? !(UCSRA & (1<<RXC)) or UCSRB=(1<<RXEN)|(1<<TXEN);
@Mahadi,
See this
http://extremeelectronics.co.in/avr-tutorials/programming-in-c-tips-for-embedded-development/
Also remembering one fact will help you
“We are writing programs in C”
So you must know C language (this is NOT a magical advice!)
If you knew C you already understood the above line !!!
Now for the not so rude answer.
UCSRB=(1<<RXEN)|(1<<TXEN)
RXEN and TXEN are constants, 7 and 6 respectively. So 1<<RXEN is 1 shifted left 7 places or 10000000 and 1<<TXEN is 1 shifted left 6 place or 01000000. Then the two values are bitwise ORed and the result 11000000 is placed in the register UCSRB.
I answered this because on first glance, the shifts didn't make sense to me because I did not know the value of RXEN or TXEN.
Thanks!
Seems that UBRR is no longer directly handled via AVR Studio 5, immediate 16bit (2xregister) writing on UBRR doesn’t work, you should specify UBRRH,UBBRL independently.
Hello.How can I get/make a serial bootloader for an ATMEG16-16PU running at 16MHz? If the microcontroller has a bootloader (for 13.5Mhz) cold it be erase? Sorry if the subject is off topic.
Thanks
The frequency can only be changed by a crystal you need to solder on the two XTal pins. After doing that, you need to set the right “fuse bits” while flashing the MCU. Then the crystal is used, to alter the internal oscillator to the desired frequency.
Man I’m from mexico and my english is not the best but my congratuelations to you, this really helped me with my projects
Good Afternoon sir, thanks for your assistance that you have been rendering to many people, please sir i want a concise and comprehensive tutorial on PIC MICROCONTROLLERS because i am facing my final year project which is based on this type of MCU also i am appreciating the kind of simplicity of language you are using on this AVR MCu tutorial, Pls sir I need also the basics of LCD tutorial which is this part of your tutorials hoping my problems will be solved. Thanks Sir Avinash
If you’re looking for PIC samples go to mikroe.com but if you know “C” or “Pascal” the codes here are the same for PIC & AVR when you set the baud_rate and TX or RX a byte. the difference is in assembler code.
( 3<<ucsz0)
i can't ubderstand it
see this post
http://extremeelectronics.co.in/avr-tutorials/programming-in-c-tips-for-embedded-development/
Dear Sir
I want to control the speed of 230 V AC motor (submersible water Pump)through AVR 32A Mc. I have used PWM as well as also tried with 8 bit DAC (DAC0808) to Drive (BT12 A) TRIAC, but could not get the desired Output. Therefore need your help in this regard. What ckt should i use for controlling the speed of the AC motor,along with AVR 32A Mc.
please send me the solution on vishalmeshram2007@rediffmail.com OR
vishalgmeshram@gmail.com
Waiting eagerly for your reply
Regards
Vishal
look you need to sync the pwm with ac waves. So u need to sense the ac waves with an opto isolator. See this
http://extremeelectronics.co.in/avr-projects/avr-project-remote-controlled-fan-regulator/
Sir can i send a message from atmega8l connected to a mobile or we need a pc to interface this to device?
HI, i just wanted to know if there are any specific library files i NEED to include as whatever program i am writing for USART communication, my AVRSTUDIO is returting errors like :
../usart.c:10: error: ‘UCSRB’ undeclared (first use in this function)
../usart.c:10: error: (Each undeclared identifier is reported only once
../usart.c:10: error: for each function it appears in.)
../usart.c:11: error: ‘UCSRC’ undeclared (first use in this function)
../usart.c:11: error: ‘URSEL’ undeclared (first use in this function)
../usart.c:12: error: ‘UBRRH’ undeclared (first use in this function)
../usart.c:13: error: ‘UBRRL’ undeclared (first use in this function)
../usart.c:16: error: ‘UCSRA’ undeclared (first use in this function)
../usart.c:17: error: ‘UDR’ undeclared (first use in this function)
I am using Atmega128 MCU
I have the same problem. I’ also using Atmega128. Is there anyone who can fix this?
define
m128def.inc
first of all great tutorials.. all of them. learned a lot from them, thanks for that
i have question ,i am making a temperature data logger means i have used LM35 to measure the temperature and display it on lcd, till now its fine and i have also checked rs232 separetly its also working fine…thanks to your tuts.
Now i want to send these readings of temperature to PC using rs232 only..where i can display it on excel sheet with time HOW CAN I DO THIS?? ..PLZZ GUIDE ME..
i have that basic c prog ,but i still dont understand
3<<ucsz0
hello hw are U? fine
i do project using PIC 16f877 using mikroC and proteus for simulation and i want to programme it to parse data coming from GPS using usart only .how i can give a name for parsed data.example
$GPRMC,10,12,14,15,16.
i want the code which parse like below
$GPRMC,
latitude=10,
longitude=12,
time=14,
navigation=15,
dhsgds=16, so on and usart only write if first it get $ sign only unless doesnot write on usart.but the main thing is the numbers which come from GPS can vary but the order of the name which i give for the coming number is constant .
well done,layman can understand.Thank you,your sample codes are very useful.
Thanks Extremeelectronics.co.in
Can u tell what the statement 3<<UCSZ0 does precisely?
Hi,
When explaining the “UBRR: USART Baud Rate Register:”, the baud rate calculation has been shown.
It is said that Fosc is 16MHz and count for UBRR register is 51.
51 will come if 8MHz clock is used.
Below in the Android application calculation it shows as 103 which is the correct value.
Regards,
Sunil