问题描述:
客户工程师提出,在使用STM32F103 的USART 做串口通讯时,发现了一个问题,当设备正常通信一段时间后,串口就不再响应外部通信请求了。
调研分析:
一、基本情况:
1.1 客户除了使用USART 通信,还开启了定时器中断来进行数据采集.
1.2 定时器的优先级比串口接收的优先级高.
1.3 定时器处理数据操作比较频繁.
1.4 客户使用的STM32F1 标准库(版本V3.5.0).
二、经调试,进行现象重现与问题定位后发现:
2.1 出现异常问题的时,程序不断的进入串口接收中断,不能执行其它功能。
2.2 发现ORE 标志为‘1’,说明程序发生了串口溢出错误.
2.3 客户在进入串口中断后会调用USART_GetITStatus(USART2,USART_IT_RXNE)
来获取RXNE的值.如果RXNE为1 则去读取DR寄存器的数据,读取后RXNE为0,但是ORE 的标志仍为1,依然进入了串口中断.
三、 经过分析和阅读ST MCU芯片参考手册可得到以下信息:
3.1 程序不断进入串口中断是因为ORE标志始终为1,没有被用户清除掉:
从上图红色部分我们可以看到,如果串口接收中断开启了,那么ORE为1 时也会产生中断.
3.2.从下图我们可以看到,顺序执行对USART_SR 和USART_DR 的操作就会清除ORE的标志,客户在中断中执行了以下操作,那为什么ORE标志还没有被清除呢?(R1执行了读USART_SR 操作,R2执行了读USART_DR 操作).
3.3 我们可以看下方手册中的相关解释:
3.3.1 ORE表征的是个历史事件,当ORE为1时,表明至少有1个数据已经丢失。
3.3.2 还有2种可能发生的情况,RXNE为1的情况R3和RXNE为0的情况R4。
3.3.3 我们从上图可以看出,3.2 处截图中的R1+R2 操作只是处理了RXNE 为1的情况;当RXNE 为0的特殊情况, 也就是在读序列期间(在USART_SR 寄存器读访问和USART_DR 读访问之间)接收到新的数据,数据SR虽然被读过了,但是overrun事件依然发生了,R1+R2操作是不能处理的。
3.4 因此我们要在应用中对ORE标志进行处理,当判断发生ORE中断的时候,我们再读一次USART_DR的值,这样如果没有新的Overrun 溢出事件发生的时候,ORE会被清除,然后程序就不会因为ORE未被清除而一直不断的进入串口中断了,代码处理如下:
小结:
对于上述情况,当我们使能了USART串口接收中断,ORE中断也就开启了。为了消除在通过读序列(USART_SR/USART_DR)过程中产生的溢出错误,我们可以尝试在应用程序中针对ORE标志做些处理来清除ORE标志,使得串口通信可以正常的持续工作。客户也可以在做串口通信时增加帧检验功能,如CRC校验等,当发生ORE时,帧校验肯定是通不过的,这样以避免误响应。