UART Reference
Free reference guide: UART Reference
About UART Reference
The UART Reference is a searchable cheat sheet for Universal Asynchronous Receiver-Transmitter communication, the most fundamental serial protocol in embedded systems. It covers the complete UART frame structure (start bit, 5-9 data bits, optional parity, 1-2 stop bits), standard baud rates from 9600 to 921600, parity bit calculation for error detection, and initialization code for both STM32 HAL and Arduino platforms.
This reference organizes over 25 entries across six categories: Configuration, Transmit, Receive, Flow Control, DMA, and Debugging. The Transmit section covers STM32 polling (HAL_UART_Transmit), interrupt-driven (HAL_UART_Transmit_IT), and printf redirection, plus Arduino Serial.print() and Serial.write(). The Receive section details polling, interrupt, IDLE line detection for variable-length packets, and ring buffer implementations for continuous data reception.
Beyond basic send/receive, this cheat sheet addresses advanced topics including hardware flow control with RTS/CTS signals, software XON/XOFF flow control, RS-232 voltage levels with MAX232 level shifting, RS-485 half-duplex differential signaling for long-distance multi-node networks, DMA transfers in normal and circular modes, the powerful DMA+IDLE combination for efficient variable-length reception using HAL_UARTEx_ReceiveToIdle_DMA, baud rate error calculation, logic analyzer debugging techniques, and a comprehensive list of common UART problems and their solutions.
Key Features
- UART frame structure: start bit, data bits (5-9), parity (None/Even/Odd), and stop bits (1-2) with 8N1 as default
- STM32 HAL API: polling, interrupt, and DMA modes for both transmit and receive with callback patterns
- Arduino Serial interface: Serial.begin() configuration, Serial.print()/println() for text, Serial.write() for binary
- DMA transfer modes: normal, circular, half-transfer callbacks, and DMA+IDLE for variable-length packets
- Flow control: RTS/CTS hardware handshaking and XON/XOFF software protocol for buffer management
- Physical layer standards: RS-232 voltage levels with MAX232, RS-485 differential signaling for multi-node buses
- Ring buffer implementation for interrupt-driven continuous reception without data loss
- Debugging guide: baud rate error calculation, logic analyzer waveform analysis, and common UART problem checklist
Frequently Asked Questions
What does 8N1 mean in UART configuration?
8N1 is the most common UART configuration: 8 data bits, No parity, 1 stop bit. Combined with the mandatory start bit, each byte requires 10 bit periods to transmit. At 115200 baud, this means approximately 11,520 bytes per second. Other configurations include 8E1 (8 data bits, Even parity, 1 stop bit) which adds error detection at the cost of slightly lower throughput.
What is the difference between polling, interrupt, and DMA receive modes?
Polling (HAL_UART_Receive) blocks the CPU until data arrives or timeout occurs, suitable only for simple applications. Interrupt mode (HAL_UART_Receive_IT) triggers a callback on each received byte, freeing the CPU between bytes but still requiring ISR overhead per byte. DMA mode (HAL_UART_Receive_DMA) transfers data directly to memory without CPU involvement, ideal for high-speed or continuous data streams where CPU should be free for other tasks.
How does IDLE line detection work for variable-length packets?
The IDLE interrupt fires when the UART line has been idle (no data) for one frame period after receiving data. Combined with DMA, you start a DMA receive for the maximum buffer size, and when the IDLE interrupt fires, you read the DMA counter to determine how many bytes were actually received. HAL_UARTEx_ReceiveToIdle_DMA wraps this pattern, calling HAL_UARTEx_RxEventCallback with the actual received size.
Why do I get garbled characters on UART?
The most common cause is baud rate mismatch between sender and receiver. Other causes include TX-RX wires not crossed (TX must connect to RX and vice versa), missing common ground connection, voltage level mismatch (3.3V MCU connected to 5V device without level shifter), and parity or stop bit configuration mismatch. Use a logic analyzer to verify the actual baud rate and frame format on the wire.
When should I use RS-485 instead of RS-232?
Use RS-485 for distances over 15 meters, multi-node networks, or noisy industrial environments. RS-485 uses differential signaling (two wires, A and B) which provides excellent noise immunity, supports cable runs up to 1200 meters, and allows up to 32-256 nodes on a single bus. However, RS-485 is half-duplex, requiring a Driver Enable (DE) pin to switch between transmit and receive modes, which adds software complexity.
How do I implement printf over UART on STM32?
Override the _write() function in your syscalls.c or a retarget file. Inside _write, call HAL_UART_Transmit(&huart1, (uint8_t*)ptr, len, HAL_MAX_DELAY) to redirect all printf output to UART1. This lets you use standard printf("Temp: %.1f\n", temp) for debugging. For production, consider using a ring buffer with DMA transmit to avoid blocking the CPU during printf calls.
What is a ring buffer and why is it needed for UART reception?
A ring buffer (circular buffer) is a fixed-size array with head and tail pointers that wraps around. In UART reception, the interrupt callback writes bytes at the head pointer, while the main loop reads from the tail pointer. This decouples the ISR timing from processing timing, preventing data loss when the main loop is temporarily busy. The buffer size should be large enough to hold data during the longest processing delay.
How do I calculate baud rate error and what is the acceptable tolerance?
Actual baud rate = PCLK / (16 * USARTDIV), where USARTDIV is the divider register value. The error percentage is |actual - target| / target * 100%. The acceptable tolerance is typically within 2% for reliable communication, though 1% or less is preferred. Clock frequency, prescaler settings, and divider granularity all affect the achievable accuracy. For example, a 72MHz clock achieves exact 115200 baud with USARTDIV = 39.0625.