Module 3 - Serial Port
- Introduction to USART
- USART Register Architecture of ATmega328p
- Implementation and Assembly Code Examples
Introduction to USART
1. USART Definition
USART (Universal Synchronous/Asynchronous Receiver/Transmitter) is a communication protocol used to transfer data between electronic devices, such as microcontrollers, sensors, and other components. This protocol is highly flexible as it supports two main modes:
- Synchronous
- Asynchronous
2. UART vs. USART
While often used interchangeably, there is a technical difference:
- UART (Universal Asynchronous Receiver/Transmitter): Supports only asynchronous communication. It requires no clock signal as it relies on start/stop bits and pre-defined baud rates.
- USART (Universal Synchronous/Asynchronous Receiver/Transmitter): A superset of UART. It supports both asynchronous and synchronous modes. In synchronous mode, a dedicated clock pin (XCK) is used to synchronize data.
3. Operating Modes
A. Asynchronous Mode
In this mode, the USART module transmits data without an external clock signal. Synchronization is achieved using data frames consisting of:
- Start Bit: Indicates the beginning of transmission.
- Data Bits: Contains the primary information (typically 5-9 bits).
- Parity Bit (Optional): Used for error detection (Even, Odd, or None).
- Stop Bit: Indicates the end of transmission.
Characteristics: Suitable for long-distance communication or between devices that do not share the same clock.
B. Synchronous Mode
Uses a clock signal to synchronize data transfer between the transmitter and the receiver.
- Requires the same clock configuration on both devices.
- Allows for faster and more reliable data transfer compared to asynchronous mode.
Characteristics: Ideal for multimedia applications or high-speed bulk data transfers.
4. Configuration and Baud Rate
To use USART, several parameters must be defined:
- Baud Rate: The speed of data transmission (bits per second).
- Data Format: The number of data bits, parity, and stop bits.
- Interrupt: Enables notifications when data is finished being sent or received.
5. USART and Arduino Serial Monitor
In the Arduino ecosystem (such as the Uno), the USART peripheral is the primary way the microcontroller communicates with your computer:
- Hardware Connection: The ATmega328P uses its USART pins (TX on Pin 1, RX on Pin 0). These are connected to an onboard USB-to-Serial converter chip.
- Serial Monitor: When you open the Serial Monitor or Serial Plotter in the Arduino IDE, it acts as the "Receiver" (RX) for data sent by the Arduino and the "Transmitter" (TX) for data you type in.
- Baud Rate Alignment: For communication to work, the baud rate selected in the Serial Monitor (e.g., 9600) must match the baud rate configured in your code. If they do not match, you will see "garbage" characters or no data at all.
In Proteus, follow these steps to simulate using a Virtual Terminal to mimic Serial Monitor functionality:
- Click on Virtual Instruments Mode in the left sidebar.

- Select the Virtual Terminal component and place it on the schematic.

- Add an Arduino Uno to your schematic. Then, connect the TX and RX pins of the Virtual Terminal to the RX and TX pins of the Arduino Uno respectively.

- Double-click on the Virtual Terminal to set the Baud Rate (e.g., 9600) to match your code.

Baud Rate Calculation Formula (UBRR)
The UBRR (USART Baud Rate Register) value is calculated based on the CPU clock frequency (F_CPU) and the desired Baud Rate:
UBRR = (F_CPU / (16 * BAUD)) - 1
Calculation Example:
If F_CPU = 16 MHz and the target BAUD = 9600 bps:
- UBRR = (16,000,000 / (16 * 9600)) - 1
- UBRR = 104.16 - 1
- UBRR ≈ 103 (Hex: 0x67)
USART Register Architecture of ATmega328p
The ATmega328p microcontroller uses several specific registers to control and monitor USART communication.
1. UBRR (USART Baud Rate Register)

A 16-bit register that determines the communication speed. It is divided into two 8-bit registers:
- UBRR0H: Stores the 8 most significant bits (MSB).
- UBRR0L: Stores the 8 least significant bits (LSB).
The following table provides a reference for UBRR0 (USART Baud Rate Register) settings corresponding to standard baud rates (bps). It details the required register values for three common oscillator frequencies (f_osc): 16.0000 MHz, 18.4320 MHz, and 20.0000 MHz. For each frequency, the table accounts for both normal speed (U2Xn = 0) and double speed (U2Xn = 1) modes, including the resulting percentage error for each configuration.

2. UDR (USART Data Register)

An 8-bit register that serves a dual purpose:
- TXB (Transmit Data Buffer): The location where data to be sent is written.
- RXB (Receive Data Buffer): The location where incoming data is read.
3. UCSR0A (USART Control and Status Register A)

Used to monitor communication status and configure the speed mode.
| Bit | Name | Description |
|---|---|---|
| RXC0 | Receive Complete | Set to 1 if there is new unread data in the UDR. |
| TXC0 | Transmit Complete | Set to 1 if all data has been transmitted. |
| UDRE0 | UDR Empty | Set to 1 if the UDR register is empty and ready for new data. |
| FE0 | Frame Error | Occurs when there is an error in the stop bit. |
| DOR0 | Data Overrun | Occurs when new data arrives before old data is read. |
| UPE0 | Parity Error | Occurs when there is a parity error in the received data. |
| U2X0 | Double Speed | If set to 1, the transmission speed is doubled. |
| MPCM0 | Multi-processor | Enables multi-processor communication mode. |
4. UCSR0B (USART Control and Status Register B)

Used to enable the module and interrupts.
- RXCIE0: Enables the receive complete interrupt.
- TXCIE0: Enables the transmit complete interrupt.
- UDRIE0: Enables the data register empty interrupt.
- RXEN0: Enables the Receiver.
- TXEN0: Enables the Transmitter.
- UCSZ02: Additional bit (along with UCSR0C) to determine data size (5-9 bits).
- RXB80 / TXB80: Holds the 9th data bit (if using 9-bit format).
5. UCSR0C (USART Control and Status Register C)

Used for frame format configuration and operating mode.
- UMSEL01:0: Selects the mode (Asynchronous or Synchronous).
- UPM01:0: Selects the Parity mode (None, Even, or Odd).
- USBS0: Selects the number of Stop Bits (1 or 2).
- UCSZ01:0: Determines the data size (paired with UCSZ02 in UCSR0B).
- UCPOL0: Clock polarity for synchronous mode.
Note: When writing to UCSR0C, ensure bit configurations are performed carefully according to the communication protocol requirements of the target device.
Implementation and Assembly Code Examples
This page contains basic implementation examples of USART serial communication using the Assembly programming language on an AVR Microcontroller (ATmega328p).
1. Printing Text to Serial Monitor
This code is used to repeatedly send the string "Programming Serial Interface!" to the Serial Monitor via the USART port.
;------------------------
; Assembly Code - Print Text
;------------------------
#define __SFR_OFFSET 0x00
#include "avr/io.h"
;------------------------
.global main
main:
CLR R24
STS UCSR0A, R24 ; Clear UCSR0A register
STS UBRR0H, R24 ; Clear UBRR0H
LDI R24, 103 ; Set UBRR value = 103 (9600 Baud Rate)
STS UBRR0L, R24
LDI R24, (1<<RXEN0) | (1<<TXEN0) ; Enable RX and TX
STS UCSR0B, R24
LDI R24, (1<<UCSZ00) | (1<<UCSZ01) ; Mode: 8-bit data, 1 stop bit, No Parity
STS UCSR0C, R24
print_msg:
LDI R30, lo8(message)
LDI R31, hi8(message) ; Z points to string message
agn:
LPM R18, Z+ ; Load character into R18
CPI R18, 0 ; Check if end of string (null)
BREQ ext ; If yes, exit loop
l1:
LDS R17, UCSR0A
SBRS R17, UDRE0 ; Wait until buffer is empty (UDRE0=1)
RJMP l1
STS UDR0, R18 ; Send character to Serial Monitor
RJMP agn ; Loop to next character
ext:
RCALL delay_sec ; Wait for a moment
RJMP print_msg ; Repeat string transmission
message:
.ascii "Programming Serial Interface!"
.byte 10, 13, 0
delay_sec: ; Delay Subroutine (~3 seconds)
LDI R20, 255
l4: LDI R21, 255
l5: LDI R22, 255
l6: DEC R22
BRNE l6
DEC R21
BRNE l5
DEC R20
BRNE l4
RET
2. Reading Input from Serial Monitor
This code reads characters sent from the Serial Monitor and controls an LED. If the character 'H' is received, the LED turns ON; if 'L' is received, the LED turns OFF.
;------------------------
; Assembly Code - Input Text and Control LED
;------------------------
#define __SFR_OFFSET 0x00
#include "avr/io.h"
;------------------------
.global main
main:
CLR R24
STS UBRR0H, R24
LDI R24, 103
STS UBRR0L, R24
LDI R24, (1<<RXEN0 | 1<<TXEN0)
STS UCSR0B, R24
LDI R24, (1<<UCSZ01 | 1<<UCSZ00)
STS UCSR0C, R24
SBI DDRB, 5 ; Set PB5 as output
wait_input:
; 1. Check if a byte arrived
LDS R17, UCSR0A
SBRS R17, RXC0 ; Wait for Receive Complete
RJMP wait_input
; 2. Read the character into R18
LDS R18, UDR0
; 3. Check if character is 'H'
CPI R18, 'H'
BREQ led_on
; 4. Check if character is 'L'
CPI R18, 'L'
BREQ led_off
RJMP wait_input
led_on:
SBI PORTB, 5 ; Turn LED ON
RJMP wait_input
led_off:
CBI PORTB, 5 ; Turn LED OFF
RJMP wait_input