串口数据溢出

事起缘由

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

现象

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

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

分析原因

硬件与配置

出现该现象时先是分析了硬件原因与配置原因:

  1. 是否波特率相同
  • 115200波特率的由来:

最初是由 11.0592MHz 的晶振 通过6分频, 然后在16分频后,得到的。

  • 115200波特率每秒可传输多少个字节?

如果设置波特率为115200,设置通信帧为1bit起始位+8bit数据帧+无校验+1bit停止位(传输1个char 需要10bit),那么每秒钟最多可以传输115200bit/10bit = 11520个字节(1个字节大约86.8us;实际使用时由于存在干扰及其他原因,可能要打个8折)。

  1. 是否频率相同
  • 两边设置的波特率都为115200,但是波特率是怎么计算呢?

在计算前需先明白什么是过采样:以GD32F330R8为例,串口接收器支持x16(默认)过采样和x8过采样,x16过采样即发送方发送数据后,串口接受器会将每个bit采样16次(对一个信号进行16分频采样, 即将信号分成16等分后进行采样,一般取中间的采样值),如果是x8过采样,则采用8次。

串口过采样图示

baud= uclk / usartdiv 即: 波特率 = 所选串口所在时钟总线的频率 / 波特率分频系数

baud:常见有 9600、19200、115200

uclk:根据不同芯片、不同主频、不同总线来选择,不过常配置为36MHz、54MHz、72MHz

usartdiv:不同过采样率计算方式不同;一般来讲:

x16过采样率计算方式为:usartdiv = uclk / (16 * baud) ;大多芯片默认为x16采样,也可自己配置,寄存器 USART_CTL0中的OVSMOD位,OVSMOD = 0 为x16,OVSMOD = 1 为x8

x8过采样率计算方式为:usartdiv = uclk / (8 * baud)

  • 时钟误差

采样数据的误差:在最后一个Bit位采样时,允许极限偏移为50%,假如用1个起始位+9个数据位+1个奇偶;校验位+1个停止位来计算,那么每位偏差最高为:±50% / 12 = ±4.16%

因此,对于串口通信来说,可以粗略认为,当时钟误差小于±2%时,通信是比较可靠的。

对于客户实际的应用系统,考虑到UART是一个异步通讯,通讯的稳定性取决于双方的时钟精度,不是说只有一方的精度满足要求,系统就能正常工作,所以需要全局考虑。

软件逻辑

将所有代码逐步屏蔽,最后定位到串口上。

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

以下是本次经验与教训:

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

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

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

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

解决办法

  • 提高中断优先级。

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

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

建议

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

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

补充

RC振荡器

RC振荡器中的“RC”代表电阻(Resistor)和电容(Capacitor)‌。

RC振荡器是一种利用电阻和电容元件构成的振荡器,通过这些元件的组合来产生振荡信号。

RC振荡器的基本工作原理

RC振荡器的工作原理基于RC网络提供的相移。RC网络在电路中产生相位差,通常需要至少两个单极RC网络来获得180度的相移,从而产生振荡。在实际应用中,由于每个RC级很难精确获得90度的相移,因此通常使用多个RC级级联来达到所需的相移。通过调整电阻和电容的值,可以在特定频率下实现稳定的振荡‌。

RC振荡器的类型和应用

RC振荡器有多种类型,包括桥式振荡电路和双T式振荡电路等。桥式振荡电路是最常用的类型之一,它利用RC串并联选频网络来实现振荡。这些不同类型的RC振荡器在电子设备中有广泛的应用,例如在无线电、通信系统、时钟电路等中‌。

参考文章

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

CSDN - 串口通信USART的波特率误差计算

CSDN - 串口通讯与时钟误差的影响

CSDN - 串口通讯到底有没有累积误差?对时钟精度到底有何要求?

CSDN - 串口通讯乱码

电子发烧友 - 波特率误差产生原因