Serial Communication Interfaces in AVR Microcontrollers
USART · SPI · I2C — New Mansoura University, Embedded Systems Course
What is a communication protocol?
A defined system that allows two or more entities to exchange data. Protocols specify rules for syntax, semantics, error handling, flow control, addressing, and routing.
The three AVR protocols
USART
2 data wires
Async or sync
PC ↔ MCU, GPS, Bluetooth modules
SPI
4 wires
Synchronous only
Displays, Flash memory, SD cards
I2C
2 wires
Multi-device bus
Sensors, EEPROM, RTC modules
Choosing the right protocol
| Factor | USART | SPI | I2C |
|---|---|---|---|
| Wire count | 2 | 4 | 2 |
| Speed | Medium | High | Low–Medium |
| Devices on bus | 1 each | 1 per CS pin | Up to 127 |
| Clock | None (async) | Shared (SCLK) | Shared (SCL) |
| Duplex | Full | Full | Half |
UART / USART
Definitions
UART (Universal Asynchronous Receiver/Transmitter) — a hardware circuit inside the MCU that converts parallel data (from CPU) into serial bits for transmission, and vice versa on reception.
USART extends UART by also supporting synchronous mode, where both devices share a clock signal (XCK pin), allowing higher reliability and speed over short distances.
How two devices connect
Shift registers on both sides handle the serial ↔ parallel conversion. No external clock needed in async mode.
Duplex modes
Simplex
Data flows in one direction only. E.g. sensor → MCU only.
Half-duplex
Both directions, but not at the same time.
Full-duplex
Both directions simultaneously — standard UART mode.
Asynchronous
No shared clock. Both sides must agree on the same baud rate.
Baud rate
Speed is measured in bits per second (bps). Both devices must use the same baud rate or data will be garbled. Standard rates:
Example: 9600 baud at 16 MHz
UBRR = 16,000,000 / (16 × 9600) − 1 = 104.17 − 1 ≈ 103
UART frame structure
Every byte is wrapped in a frame. The receiver detects the start bit, samples each data bit at the correct time, checks parity, then waits for the stop bit.
Visual frame layout
Bit-by-bit reference
| Field | Value | Purpose |
|---|---|---|
| Start bit | always 0 | Signals frame start; transitions from idle HIGH to LOW, waking the receiver |
| Data bits | LSB first | Payload — usually 8 bits (1 byte). Can be 5, 6, 7, 8, or 9 bits |
| Parity bit | 0 or 1 | Optional error check: even parity, odd parity, or disabled |
| Stop bit(s) | always 1 | 1 or 2 bits. Marks end of frame; returns line to idle HIGH |
Parity modes
Even parity
Parity bit is set so total number of 1-bits (including parity) is even.
Odd parity
Parity bit is set so total number of 1-bits is odd.
No parity
Parity bit omitted. Most common in practice (shorter frames, faster).
Error detection limit
Parity only detects single-bit errors. For robust error handling use CRC.
Example: sending 'A' (0x41)
0x41 = 01000001 binary. Sent LSB first = 1, 0, 0, 0, 0, 0, 1, 0
USART registers (ATmega32)
Five register groups control the entire USART peripheral. You configure them once in init, then use status flags during operation.
16-bit register split into high byte (UBRR0H, bits 11–8) and low byte (UBRR0L, bits 7–0). Stores the prescaler value.
| Bit | Name | Meaning |
|---|---|---|
| 7 | RXC0 | Receive Complete — set when unread data is in UDR0. Poll before reading. |
| 6 | TXC0 | Transmit Complete — set when transmit buffer is empty and shift register done. |
| 5 | UDRE0 | Data Register Empty — set when UDR0 is ready for new data. Poll before writing. |
| 4 | FE0 | Frame Error — stop bit was not 1. Indicates sync problem. |
| 3 | DOR0 | Data OverRun — receive buffer full, incoming byte lost. |
| 2 | PE0 | Parity Error — received parity bit doesn't match data. |
| Bit | Name | Meaning |
|---|---|---|
| 7 | RXCIE0 | RX Complete Interrupt Enable — fires ISR when RXC0 is set |
| 6 | TXCIE0 | TX Complete Interrupt Enable — fires ISR when TXC0 is set |
| 5 | UDRIE0 | Data Register Empty Interrupt Enable |
| 4 | RXEN0 | Receiver Enable — must be 1 to receive data |
| 3 | TXEN0 | Transmitter Enable — must be 1 to transmit data |
| 2 | UCSZ20 | Character size MSB (combined with UCSZ1:0 in UCSR0C) |
Character size (UCSZ2:1:0)
0 1 1 → 8 bits (most common)0 1 0 → 7 bits1 1 1 → 9 bits
Parity (UPM1:0)
0 0 → disabled1 0 → even parity1 1 → odd parity
Stop bits (USBS)
0 → 1 stop bit (default)1 → 2 stop bits
Mode (UMSEL)
0 → Asynchronous (UART)1 → Synchronous (USART)
The single data register that serves as both transmit buffer (write to it) and receive buffer (read from it). The hardware handles all serial bit-shifting automatically.
To transmit
Wait for UDRE0 = 1, then write: UDR0 = myByte;
To receive
Wait for RXC0 = 1, then read: data = UDR0;
Bit-shift trick explained
How does (1 << RXEN0) work? RXEN0 is just a number (4). The operation shifts binary 1 left by 4 positions:
Complete code example
Sending and receiving a byte over USART — 8-bit data, no parity, 1 stop bit, 9600 baud at 16 MHz.
Define constants and include header
Initialize USART
Transmit a byte (polling)
Receive a byte (polling)
Main program
Polling vs interrupts
Polling (used above)
CPU loops waiting for the flag. Simple but blocks execution. Fine for simple programs.
Interrupt-driven
Set RXCIE0 / TXCIE0 in UCSR0B. ISR fires automatically. CPU is free for other work.
MCQ Quiz — Lecture 06
12 questions covering all topics. Select an answer — instant feedback after each one.