3.10) AVR Serial Port Programming: C Programs for Data Transmission and Reception

posted by Hamid Sayyed • November 12, 2025 0 Comments

Once the USART module in AVR microcontrollers is configured, we can easily write C programs for transmitting and receiving serial data. Serial communication plays a vital role in embedded systems as it allows data exchange between microcontrollers, computers, and various peripheral modules. In embedded development, we often use the serial port for debugging, monitoring sensor data, sending commands, or communicating with external modules such as GSM, GPS, and Bluetooth. The AVR’s built-in USART hardware simplifies this task by handling most of the transmission and reception processes automatically. However, the programmer must correctly initialize baud rate registers, enable transmitter and receiver, and manage data registers. In this post, we will discuss how to program AVR for data transmission and reception using C language, step by step, with detailed explanation of each section and practical code examples that can be directly compiled using AVR Studio or Microchip Studio.

Concept of Data Transmission and Reception

The USART module handles serial communication in two directions — transmission (TXD) and reception (RXD). The transmitter sends out one byte of data at a time, converting it from parallel to serial form. The receiver listens on the RXD pin, reconstructs the incoming bits into a full byte, and stores it for the CPU to read. Both operations can occur simultaneously, making the USART full-duplex. Before any data exchange, the USART must be initialized with a specific baud rate and frame format (number of data bits, parity, and stop bits).

Block Diagram of Serial Communication Flow

Program 1: Serial Data Transmission

The following program demonstrates how to initialize the USART and continuously send characters from the AVR microcontroller to a terminal window (such as PuTTY or Arduino Serial Monitor). The baud rate is set to 9600 bps, which is a standard for most devices.

#include 
#define F_CPU 16000000UL
#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) | (3 << UCSZ0);  // 8-bit data, 1 stop bit
}

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

int main(void) {
  USART_Init(MYUBRR);
  while (1) {
    USART_Transmit('A');             // Send character 'A'
    for (volatile long i = 0; i < 30000; i++);  // Simple delay
  }
}
Explanation: The UBRR registers define the baud rate. TXEN enables the transmitter, and UDRE checks if the data register is ready. The loop continuously sends the character 'A' through the TXD pin every short delay, which can be viewed on the serial monitor.

Program 2: Serial Data Reception

Now let us see how to receive serial data sent from a computer or another device. The received data is stored in the UDR register and can be read once the RXC flag in UCSRA is set. The program below waits for incoming data and then echoes it back to the sender.

#include 
#define F_CPU 16000000UL
#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) | (1 << TXEN);     // Enable RX and TX
  UCSRC = (1 << URSEL) | (3 << UCSZ0);   // 8-bit data
}

unsigned char USART_Receive(void) {
  while (!(UCSRA & (1 << RXC)));         // Wait until data received
  return UDR;                            // Return received data
}

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

int main(void) {
  USART_Init(MYUBRR);
  unsigned char receivedChar;
  while (1) {
    receivedChar = USART_Receive();      // Wait and read data
    USART_Transmit(receivedChar);        // Echo back received character
  }
}
Explanation: The RXEN and TXEN bits enable both receiving and transmitting. The program reads a character received through RXD, then immediately sends it back via TXD. This is known as an echo program and is widely used for testing serial communication.

Conclusion

Programming serial communication in AVR using C is simple once the USART registers are understood. Initialization involves setting the correct baud rate, data format, and enabling transmitter and receiver. After that, data can be sent or received by simply reading and writing to the UDR register. The two sample programs above cover the basic techniques of serial transmission and reception. These form the foundation for advanced applications like sending sensor readings, user commands, or even interfacing wireless modules for IoT projects. Mastering USART programming in AVR helps students and hobbyists communicate with almost any serial device efficiently and reliably.

Comments

Post a Comment

Subscribe to Post Comments [Atom]