Mastering Serial Communication: From UART Basics to STM32 Implementation
This comprehensive guide explains serial communication fundamentals, covering UART/RS‑232/RS‑485 protocols, physical layer standards, baud‑rate calculations, data frame structures, duplex modes, and provides detailed STM32 configuration code for practical embedded development.
What is Serial Communication?
Serial communication transmits data bit‑by‑bit over a single pair of wires (one for transmitting, one for receiving) and a ground line. Although slower than parallel communication, it requires only two wires, making it simple and cost‑effective.
Serial Communication Protocols
Early interfaces used simple analog signals, evolving to RS‑232 for point‑to‑point links, which later gave way to RS‑485 for differential, multi‑drop, and noise‑resistant communication. RS‑485 can reach speeds above 10 Mb/s over distances up to 3 km, though speed decreases with longer cables.
Physical Layer
The RS‑232 standard defines signal meanings, connector types, and voltage levels. Because RS‑232 voltage levels (+15 V/‑15 V) differ from TTL levels (0 V/5 V), a level‑shifting chip converts between them before the controller can interpret the data.
Baud Rate
The baud rate indicates how many signal changes occur per second. For example, a 9600 bps rate means each bit lasts 1/9600 s (≈104 µs). Both devices must use the same baud rate; mismatched rates prevent successful communication.
Data Frame Structure
A typical UART frame consists of:
Start bit : a low (0) level lasting one bit time, signalling the beginning of a character.
Data bits : 5‑9 bits (commonly 8) transmitted LSB first.
Parity bit (optional): ensures an odd or even number of high bits.
Stop bits : one, 1.5, or two high (1) bits marking the end of the character.
Idle bits : high level between characters.
Duplex Modes
Serial links can operate in:
Simplex : data flows in one direction only.
Half‑duplex : bidirectional but only one direction at a time.
Full‑duplex : simultaneous two‑way transmission, effectively two independent simplex channels.
Serial Communication on STM32
STM32 microcontrollers provide two peripheral types: UART (asynchronous) and USART (synchronous/asynchronous). For example, the STM32F10x series includes three USARTs and two UARTs. TXD is the transmit pin, RXD the receive pin. Direct cross‑connection works between two STM32 boards sharing a common ground.
When connecting an STM32 to a PC, the PC typically uses an RS‑232 (DB9) port, so a level‑shifter is required to convert the STM32’s 0‑5 V TTL signals to RS‑232 voltage levels (+15 V/‑15 V). USB‑to‑serial adapters can also be used.
STM32 Serial Communication Code
Below is a typical configuration sequence using the STM32 Standard Peripheral Library.
1. USART initialization structure
typedef struct {
uint32_t USART_BaudRate; // Baud rate
uint16_t USART_WordLength; // Data word length
uint16_t USART_StopBits; // Stop bits
uint16_t USART_Parity; // Parity selection
uint16_t USART_Mode; // USART mode (Rx/Tx)
uint16_t USART_HardwareFlowControl; // Hardware flow control
} USART_InitTypeDef;2. NVIC interrupt priority configuration
void NVIC_Configuration(void) {
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}3. USART configuration function
void DEBUG_USART_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// 1) Enable GPIO clock and configure TX pin as alternate function push‑pull
DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);
// 2) Configure RX pin as floating input
GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
// 3) Enable USART peripheral clock
DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);
// 4) Set USART parameters
USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(DEBUG_USARTx, &USART_InitStructure);
// 5) Configure interrupt priority and enable RX interrupt
NVIC_Configuration();
USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);
// 6) Enable USART
USART_Cmd(DEBUG_USARTx, ENABLE);
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
