STM32 串口底层深度解析|USART 中断标志、硬件 FIFO,乱码根源底层定位

摘要

很多人调试 STM32 串口,只停留在 HAL 库HAL_UART_RxCpltCallback回调函数,遇到乱码、丢字节、偶发接收异常,只会怀疑波特率或者上位机。

但实际上大量工程里的串口玄学 bug,根源来自USART 硬件中断标志理解错误、硬件 FIFO 溢出、帧错误 / 噪声标志未及时清除 。

本文从寄存器底层讲清楚 STM32 USART 硬件机制,拆解中断标志、硬件 FIFO 工作逻辑,从硬件层面定位乱码、丢包的真实原因,附带极简测试代码与工程排查方法。

一、STM32 USART 硬件基础:不是简单 "收发寄存器"

STM32 的 USART 外设是独立硬件外设,内核 CPU 只是读取状态、搬运数据,串口收发是硬件自动移位完成 。

核心硬件单元:移位寄存器、TDR 发送数据寄存器、RDR 接收数据寄存器、状态寄存器 SR、硬件 FIFO(F4/F7/H7 等带 FIFO,F1 没有硬件 FIFO)。

关键底层逻辑:

  1. 发送:CPU 写入 TDR → 硬件自动把 TDR 数据转到移位寄存器,逐位输出;TDR 为空就置位 TXE 标志。
  2. 接收:硬件引脚采样到串行 bit,移入移位寄存器,一帧收完存入 RDR,置位 RXNE 标志。

⚠️ RDR 寄存器只有 1 字节缓存(F1 无 FIFO),如果 CPU 没及时读取 RDR,新数据进来直接覆盖旧数据,造成丢字节。

硬件 FIFO 作用(F4/H7 等带 FIFO 型号)

硬件 FIFO 是串口内置的硬件缓冲区,独立于 CPU。

  • 接收 FIFO:可以缓存多字节,缓解 CPU 来不及读取的压力,减少 RXNE 中断触发频次;
  • 发送 FIFO:批量填入待发数据,硬件自动依次发送,降低 CPU 占用。

坑点:很多人开启 FIFO 但不懂 FIFO 阈值,FIFO 满溢出(ORE 溢出标志),同样会丢数据、产生乱码。

二、核心中断标志位深度解析(SR 状态寄存器)

新手最容易踩坑:只看 RXNE,忽略 ORE、FE、NE 这些错误标志。

寄存器 SR(Status Register)关键标志:

  1. RXNE 接收数据非空
    收到 1 帧数据,RDR 寄存器有效,置 RXNE,触发接收中断。
    清零方式:读取 RDR 寄存器,硬件自动清除 RXNE。

坑:只清中断位,但不读 RDR,RXNE 标志永远不会清零,会反复进中断,程序卡死。

  1. TXE 发送寄存器空
    TDR 寄存器为空,可以写入下一个待发送字节。

坑:大量新手在中断里循环写数据,没判断 TXE,造成重复发送乱码。

  1. TC 发送完成标志****移位寄存器全部发送完毕 ,不是 TDR 写完。
    TXE=TDR 空;TC = 所有 bit 全部发送到 TX 引脚。
    项目场景:需要等待一整条报文发送完毕再切换 IO(比如 RS485 收发切换),必须用 TC,不能用 TXE,这是工控 RS485 最常见错误。
  2. ORE 溢出错误 Overrun error【乱码头号元凶】

底层原理:RDR 已经存有未读数据,新的一帧接收完成,硬件无法存放新数据 → ORE 置位。

后果:旧 RDR 数据丢失,新数据直接覆盖,出现随机丢字节、乱码。

触发场景:中断被长时间阻塞(高优先级中断长时间占用 CPU),CPU 来不及读取 RDR。

重点:ORE 标志必须软件清除,如果不清除,后续串口持续异常。

  1. FE 帧错误、NE 噪声错误
    FE:停止位异常(波特率偏差、信号毛刺、断线);
    NE:采样收到噪声,收到的 bit 不稳定。
    出现 NE/FE,硬件依然会把采样到的数据存入 RDR,这就是收到乱码数据的来源 。
    很多代码完全不判断 FE/NE,把错误帧直接当成有效数据解析,协议直接错乱。

底层重点:

只要 SR 寄存器里存在错误标志(ORE/NE/FE),RXNE 中断依然会触发。如果代码只读取 RDR,不清除错误标志,错误锁死,后续所有接收都会异常。

三、乱码、丢字节底层根源分类

1. 硬件层面

  • 波特率误差过大:串口外设时钟分频配置错误,采样点偏移,NE 噪声标志置位,采样出错;
  • 信号质量差:长线传输、缺少上拉,信号毛刺引入噪声;
  • 无硬件 FIFO 芯片(F1):高中断负载,CPU 读取不及时触发 ORE 溢出。

2. 软件层面(项目最高发)

  1. 中断服务函数里面写大量业务逻辑、延时、循环,阻塞中断;
  2. 只判断 RXNE,完全不检测 ORE、FE、NE 错误标志;
  3. 错误标志没有清除,错误状态锁死,后续接收持续异常;
  4. RS485 场景:用 TXE 判断发送完成,提前切换收发引脚,截断报文;
  5. 开启硬件 FIFO,FIFO 溢出阈值配置不合理,FIFO 溢出。

四、精简底层示例代码(标准库,F103,无硬件 FIFO)

只做硬件状态检测 + 数据接收,中断里面不做协议解析,业务逻辑放到主循环 ,工程推荐写法

void USART1_IRQHandler(void)

{

uint8_t ch;

if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET)

{

ch = USART_ReceiveData(USART1); //读RDR,硬件清RXNE

rx_bufrx_idx++ = ch;

if(rx_idx >= RX_BUF_MAX) rx_idx = 0;

}

// 检测溢出、帧错误、噪声错误

if(USART_GetFlagStatus(USART1, USART_FLAG_ORE | USART_FLAG_FE | USART_FLAG_NE) != RESET)

{

// 清除错误标志:读SR + 读DR,硬件清除错误标记

USART_ClearFlag(USART1, USART_FLAG_ORE | USART_FLAG_FE | USART_FLAG_NE);

}

}

代码要点:

  1. 中断仅做读取字节 + 缓存,解析放到主循环;
  2. 捕获 ORE/FE/NE 错误,一旦出现,直接清除标志,防止锁死串口;
  3. 不要在中断里调用 printf、复杂运算、延时。

HAL 库简要说明

HAL 库封装了底层寄存器,但是底层硬件机制不变。

HAL_UART_RxCpltCallback回调,本质是 RXNE 中断触发后 HAL 库读取 RDR。

HAL 大坑:HAL 默认不会自动处理 ORE 溢出标志,一旦发生溢出,串口直接卡死,很多项目踩坑。

HAL 库需要重写中断处理,检测HAL_UART_GetState(),识别 ORE 错误,调用HAL_UART_ErrorCallback做恢复。

五、工控项目实战排查步骤(定位串口乱码)

  1. 第一步:不看数据,读取 USART SR 寄存器,查看 ORE/NE/FE 标志位。
    • 有 ORE:CPU 来不及读取,中断阻塞、优先级配置不合理;
    • 有 NE/FE:信号质量、波特率、时钟问题;
  2. 第二步:抓取中断进入时机,确认接收中断是否被其他高优先级中断长时间抢占;
  3. 第三步:F4/H7 带 FIFO 型号,查看 FIFO 溢出标志,调整 FIFO 接收阈值;
  4. 第四步:RS485 场景,使用 TC 标志判断发送结束,再切换 DE/RE 引脚。

六、工程设计规范总结

  1. 中断服务函数极简:只搬运数据、清除硬件标志,禁止复杂业务;
  2. 必须检测硬件错误标志,并且做错误恢复,不能忽略 ORE、FE;
  3. 区分 TXE 和 TC:TXE = 寄存器空;TC = 全部 bit 发送完毕,RS485 必须用 TC;
  4. 带硬件 FIFO 的芯片,合理配置 FIFO 阈值,避免 FIFO 溢出;
  5. 串口协议解析放到主循环状态机,中断只负责原始字节缓存。

结尾

串口看着简单,但是所有异常都和硬件寄存器、硬件 FIFO、中断标志深度绑定。

很多人停留在 API 调用层面,遇到偶发乱码、丢包就无从下手。读懂 USART 硬件行为,才能从根源定位问题,而不是靠不断换波特率、改上位机去试错。

相关推荐
HQB20262 小时前
EG1198|屹晶微电子 120V 内置 MOS 异步降压 DC‑DC(高性价比)
嵌入式硬件·硬件工程
果壳science4 小时前
张祥前实验如何获取正电荷
笔记·科技·嵌入式硬件·硬件工程·制造
南山电子nscn4 小时前
中科芯CETC汽车电池管理系统BMS进口芯片国产型号替代指南
单片机·汽车·bms
沉淀的.晴天4 小时前
can总线
stm32
桀人5 小时前
认识AT24C02
stm32·单片机·嵌入式硬件
国科安芯6 小时前
星间激光通信终端CANFD控制网络的时延确定性与辐射可靠性
网络·嵌入式硬件·信息与通信·canfd·低轨卫星·商业航天·抗辐射
一直C6 小时前
嵌入式 Linux 驱动开发学习笔记:内核定时器、platform 总线与 I²C 驱动
linux·驱动开发·嵌入式硬件·学习·imx6ull
传感器与混合集成电路6 小时前
150MHz主频、8路DAC与6路PWM:JLH221360伺服控制SIP解析
嵌入式硬件
comyccccc6 小时前
STM32PID控制板设计全解析学习笔记
单片机·嵌入式硬件
碧海银沙音频科技研究院7 小时前
实现炬芯ATS308X的usb cdc 串口IAP 固件升级功能实现
人工智能·嵌入式硬件·深度学习·算法