An embedded project/product without a Universal Asynchrounous Receiver Transmiter (UART) interface is unimaginable. Even if the MCU is not talking to another serial device, you'll need it at-least during the development work to speak to your computer. UART also come in handy for firmware upgrade and enabling/disabling product features during it's lifetime. This probably one of the first interfaces you would want to include in your project.
So let's get started! As with the series, we will be using a Atmega32 for this tutorial, other AVRs should work the same way. Do do not forget to look at the datasheet once before trying out with other controllers.

Basics

I know you're getting your head around the acronym UART still, but do not worry it is simple. Don't know where the word Universal came from but, Asynchronous makes lot of sense. Figure below shows the typical connection of a serial device with the MCU. There are basically Transmit(Tx) and Receive(Rx) lines and a common ground.

UART Block.png

Now imagine we want to send some data as shown below:

Data tx.png

The duration of a '1' or '0' is unknown to the receiving device. Hence it asynchronous. This is solved by agreeing upon a common data rate by both the devices, known as baud Rate.

You'll find typical baud rates to be 4800, 9600, 19200, 115200 etc. Atmega32 allows you to select the baud rate you wish. You need to look at the baud rate of the interfacing device to know it's default value. Typically most devices are set to 9600. Do not take my word for it, do check the datasheet.

Let us go ahead and configure the Atmega32 Hardware UART to communicate with the computer and send/receive data strings. 0 UART main.gif

Hook up

Code

#include "uart.h"
int main() 
{
    UART_Init(9600);
 
    while(1)
    {
        UART_Printf("Welcome to AVR Serial Programming by ExploreEmbedded\n\r");
    }
    return (0);
}

Well, this looks cool isn't it? Just a one include uart.h and one UART_init(9600) function. Well it's dig a little deeper in the init function to see how it is set up.

UCSRA
USART Control and Status Register A
D7 D6 D5 D4 D3 D2 D1 D0
RXC TXC UDRE FE DOR PE U2X MPCM


UCSRB
USART Control and Status Register B
D7 D6 D5 D4 D3 D2 D1 D0
RXCIE TXCIE UDREIE RXEN TXEN UCSZ2 RXB8 TXB8

Bit 4 - RXEN: Receiver Enable

Writing this bit to one enables the USART Receiver.

Bit 3 - TXEN: Transmitter Enable

Writing this bit to one enables the USART Transmitter.

UCSRC
USART Control and Status Register C
D7 D6 D5 D4 D3 D2 D1 D0
URSEL UMSEL UPM1 UPM0 USBS UCSZ1 UCSZ0 UCPOL

Bit 2:1 - UCSZ1:0: Character Size

The UCSZ1:0 bits combined with the UCSZ2 bit in UCSRC sets the number of data bits ( Character Size) in a frame the Receiver and Transmitter use.

Bit 7 - URSEL: Register Select

The URSEL must be one when writing the UCSRC.

USART Baud Rate Register
UBRRH UBRRL
D15 D14 D13 D12 D11:D8 D7:D0
URSEL - - - UBRR[11:8] UBRR[7:0]

Bit 11:0 - UBRR11:0: USART Baud Rate Register

This is a 12 bit register which contains the USART baud rate. The UBRRH contains the four most significant bits, and UBRRL contains the 8 least significant bits of the USART baud rate.


void UART_Init(uint32_t v_baudRate_u32)
{
	UCSRA= 0x00;                 // Clear the UASRT status register
        UCSRB= (1<<RXEN) | (1<<TXEN);     // Enable Receiver and Transmitter
	UCSRC= (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0);   // Async-mode 
 
	UART_SetBaudRate(v_baudRate_u32);
}

The UART_SetBaudRate() function calcuates the values to the set for appropriate registers as below.

void UART_SetBaudRate(uint32_t v_baudRate_u32)
{
	uint16_t RegValue;       
 
	if((v_baudRate_u32 >= C_MinBaudRate_U32) && (v_baudRate_u32<=C_MaxBaudRate_U32))
	{
		/* Check if the requested baudate is within range,
	     If yes then calculate the value to be loaded into baud rate generator. */
		RegValue = M_GetBaudRateGeneratorValue(v_baudRate_u32);
	}
	else
	{
/*Invalid baudrate requested, hence set it to default baudrate of 9600 */
		RegValue = M_GetBaudRateGeneratorValue(9600);
	}
 
                UBRRL = util_ExtractByte0to8(RegValue);
	        UBRRH = util_ExtractByte8to16(RegValue);
 
}

The Explore Embedded AVR C library for UART includes several other functions which enable sending/receiving strings, numbers etc as shown below

void UART_Init(uint32_t v_baudRate_u32);
void UART_SetBaudRate(uint32_t v_baudRate_u32);
void UART_TxChar(char v_uartData_u8);
char UART_RxChar(void);
void UART_TxString(char *ptr_string);
uint8_t UART_RxString(char *ptr_string);
void UART_TxNumber(uint8_t v_numericSystem_u8, uint32_t v_number_u32, uint8_t v_numOfDigitsToTransmit_u8);
void UART_TxFloatNumber(float v_floatNumber_f32);
void UART_Printf(const char *argList, ...);

Video Tutorial

For those of you, who would like to watch instead of read we have made a video with all the gyan.


Downloads

Download the complete project folder from the below link: https://github.com/ExploreEmbedded/ATmega32_ExploreUltraAvrDevKit/archive/master.zip


Have a opinion, suggestion , question or feedback about the article let it out here!