3.7) AVR Serial Port Programming: Basics of Serial Communication

posted by Hamid Sayyed • November 12, 2025 0 Comments

Serial communication is one of the most essential features in any microcontroller system, allowing data exchange between the AVR and external devices like computers, sensors, or other microcontrollers. In serial communication, data bits are transmitted one after another through a single data line, which saves hardware pins and simplifies long-distance data transfer. The AVR microcontroller family, such as the ATmega16, supports both synchronous and asynchronous serial communication through its built-in Universal Synchronous and Asynchronous Receiver and Transmitter (USART) module. Understanding serial communication is important because it forms the foundation of how embedded systems communicate with external peripherals such as Bluetooth modules, GSM modems, GPS units, and PCs. This topic introduces how serial communication works, how to configure USART registers in AVR, and how to implement simple transmit and receive programs in C.

What is Serial Communication

In serial communication, data is transmitted bit by bit over a single communication line instead of sending all bits simultaneously as in parallel communication. Serial communication can be asynchronous or synchronous. In asynchronous mode, data bits are transmitted with start and stop bits without any clock signal, whereas in synchronous mode, a shared clock line synchronizes data transmission. Serial data transfer is preferred for long-distance communication because it minimizes signal distortion and uses fewer wires, making it ideal for embedded applications.

Transmitter
(TXD)
Serial Line
(RX/TX)
Receiver
(RXD)

The above diagram represents a simple serial link between two devices. The transmitter converts parallel data into serial format and sends it bit by bit through the TXD pin. The receiver reads these bits on the RXD pin and reconstructs them back into parallel form. This full-duplex communication allows both sending and receiving simultaneously.

USART in AVR

AVR microcontrollers include a built-in USART module, which can work in either asynchronous or synchronous mode. It is responsible for handling serial data transmission and reception automatically, using specific control and data registers. The USART can be configured for different baud rates, parity bits, data lengths, and stop bits, making it flexible for interfacing with a wide range of serial devices. The important registers involved in serial communication are UBRRH, UBRRL (baud rate registers), UCSRA, UCSRB, UCSRC (control and status registers), and UDR (data register).

USART Register Overview

Register Function
UBRRH / UBRRL Used to set baud rate value for communication speed.
UCSRA Status register – indicates transmission and reception status.
UCSRB Control register – enables transmitter and receiver.
UCSRC Defines frame format (data bits, stop bits, parity).
UDR Holds the actual data byte to be transmitted or received.

Setting Baud Rate

Baud rate defines the number of bits transmitted per second. The AVR uses a formula to calculate the baud rate value stored in the UBRR registers:

Baud Rate = (F_CPU / (16 × (UBRR + 1))) for Normal Mode
Baud Rate = (F_CPU / (8 × (UBRR + 1))) for Double Speed Mode

For example, if the system clock is 8 MHz and the desired baud rate is 9600 bps, then UBRR = 51 in normal mode.

Program for Serial Transmission


#include <avr/io.h>
#define F_CPU 8000000UL
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1

void USART_Init(unsigned int ubrr)
{
    UBRRH = (unsigned char)(ubrr>>8);
    UBRRL = (unsigned char)ubrr;
    UCSRB = (1<<TXEN);          // Enable transmitter
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8-bit data
}

void USART_Transmit(unsigned char data)
{
    while(!(UCSRA & (1<<UDRE)));  // Wait for empty buffer
    UDR = data;                    // Send data
}

int main(void)
{
    USART_Init(MYUBRR);
    while(1)
    {
        USART_Transmit('A');   // Transmit character 'A'
    }
}
  

Program for Serial Reception


#include <avr/io.h>
#define F_CPU 8000000UL
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1

void USART_Init(unsigned int ubrr)
{
    UBRRH = (unsigned char)(ubrr>>8);
    UBRRL = (unsigned char)ubrr;
    UCSRB = (1<<RXEN);          // Enable receiver
    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); // 8-bit data
}

unsigned char USART_Receive(void)
{
    while(!(UCSRA & (1<<RXC)));  // Wait for data to be received
    return UDR;                   // Get and return received data
}

int main(void)
{
    unsigned char received_data;
    USART_Init(MYUBRR);
    DDRC = 0xFF;
    while(1)
    {
        received_data = USART_Receive();
        PORTC = received_data; // Display received data
    }
}
  

Applications of Serial Communication

Serial communication enables the AVR to communicate efficiently with various external modules and computers. It is used in data logging, debugging, sending sensor data to PCs, interfacing with Bluetooth and GSM modules, and in automation systems. With proper configuration of the USART module, serial data can be exchanged accurately and at different baud rates, making AVR an effective platform for embedded data communication.

Conclusion

The AVR’s built-in USART module provides a powerful and flexible way to perform serial communication with external devices. By understanding the register settings and programming structure, students can easily develop applications for real-time communication between embedded systems and computers. Mastering serial communication forms the base for advanced embedded projects like wireless control, IoT communication, and system monitoring.

Comments

Post a Comment

Subscribe to Post Comments [Atom]