串口数据溢出

事起缘由

串口单线通信,遇到一开串口,程序就“卡死”的情况,分析了原因,故有此文。

现象

程序在不断进串口中断函数,造成其他程序无法正常执行。

如果有串口溢出,可以在串口接收中断位置打断点,很容易触发该现象。

分析原因

出现该现象时先是分析了硬件原因,一无所获;又接着分析软件,将所有代码逐步屏蔽,最后定位到串口上。

网上查资料,查芯片用户手册,逐步定位到串口溢出(又称过载 - Overrun)上。以GD32F330为例,串口的溢出标志位(ORERR)位于USART_STAT寄存器中

以下是本次经验与教训:

串口溢出发生一般可能有以下几种情况:

  • 数据在接收缓冲区中未被及时读取。

  • 串口接收中断被更高优先级的中断打断,且打断时间比较长。

  • 擦写单片机内部flash时,耗时较长,导致串口中断无法响应。

解决办法

  • 提高中断优先级。

  • 判断并清除溢出中断标志(ORERR) - 只需读取一下串口数据寄存器(USART_RDATA)即可。

  • 关闭溢出检测功能(不推荐,此操作虽然可以解决”卡死”现象,但可能会使上个数据被覆盖,导致数据丢失)。

建议

  1. 中断程序(不仅仅是串口中断)要响应所有中断,不要只响应接收中断,其他错误中断也要处理,否则会频繁进入中断造成“卡死”。 2 STM32串口只有一个硬件BUF,个人认为是硬伤。115200波特率的情况下,大家算下一个字节是多少us? 只要串口中断被卡主住这么长时间不处理,就造成溢出。 3 把中断优先级提高、用DMA、人工优化。

  2. 尽量及时读取串口接收寄存器中的数据

参考文章

CSDN - GD32串口一直进溢出中断