STM32 零基础系列第 5 篇:建立 MCU 与电脑、模块之间最实用的调试和通信通道。
第 8 章:UART/USART
章节介绍
UART 是入门阶段最重要的"眼睛和嘴巴"。它可以把变量、状态和错误打印到电脑,也可以接 GPS、蓝牙、无线模块。
专业名词
- 波特率 Baud Rate:每秒传输的符号数量,常用 115200 或 9600。
- TX/RX:发送和接收。
- 全双工:同时发送和接收。
- 帧:起始位、数据位、校验位和停止位组成的传输单位。
- 环形缓冲区:首尾相连的接收缓存,防止数据到达时丢失。
发送示例
c
char msg[] = "temperature=25\r\n";
HAL_UART_Transmit(&huart2,
(uint8_t *)msg,
sizeof(msg) - 1,
100);
中断接收一个字节
c
uint8_t rx_byte;
void StartUartReceive(void)
{
HAL_UART_Receive_IT(&huart2, &rx_byte, 1);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART2)
{
// 将 rx_byte 放入环形缓冲区
HAL_UART_Receive_IT(&huart2, &rx_byte, 1);
}
}
实际产品不建议只接收一个字节后直接解析,应该使用环形缓冲区和协议状态机。
本章掌握标准
- 能配置波特率、数据位、停止位和校验位。
- 能使用轮询、中断和 DMA 三种方式发送接收。
- 能设计帧头、长度、命令、数据、校验和。
未来使用场景
日志输出、Bootloader、上位机控制、GPS、蓝牙、4G、RS485 和 Modbus。
UART 三种接收方式怎么选
| 方式 | 特点 | 适用场景 |
|---|---|---|
| 轮询 | 简单但阻塞 CPU | 初始化、极少量数据 |
| 中断 | 每个事件触发回调 | 命令行、低速协议 |
| DMA + 空闲线 | CPU 占用低,可接收不定长帧 | 高频日志、模块和上位机通信 |
c
uint8_t uart_rx[128];
void UartReceiveStart(void)
{
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uart_rx, sizeof(uart_rx));
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t size)
{
if (huart->Instance == USART2)
{
Protocol_Parse(uart_rx, size);
HAL_UARTEx_ReceiveToIdle_DMA(&huart2, uart_rx, sizeof(uart_rx));
}
}
一个实用的数据帧
text
帧头 命令 长度 数据 校验
AA 55 01 02 12 34 XX
帧头帮助接收端重新找到边界,长度说明还要接收多少数据,校验用于发现传输错误。解析器应逐字节推进状态,而不是假设一次 UART 回调必然收到完整帧。
常见错误
- TX 和 RX 没有交叉连接,或者两端没有共地。
- 波特率、数据位、停止位或校验不一致。
- 回调中忘记重新启动下一次接收。
- 在中断回调中直接执行耗时协议或打印大量日志。