最近做项目有概率遇到串口进入中断(LED闪烁来判断),但是没有检查到接收数据位 USART_IT_RXNE ,导致一直卡在判断语句 USART_GetITStatus(USART2, USART_IT_RXNE) != RESET,导致程序卡死。通过keil 调试模式的软件复位都没有用,需要硬件复位才行。通过百度发现这个现象挺常见的。这边我也整理一下,方便后面的查看。
1.问题定位:通过硬件发现问题后,进入keil 调试模式判断下问题在何处
在接收判断前后加入printf,来定位问题在何处。通过PC串口输出来定位,发现只能输出111111,不输出222222,说明中断是有触发,但是没有检查到接收数据位
2.问题分析
遇到问题先百度:通过查看大佬的分析----产生ORE中断了,但使用USART_GetITStatus()函数却无法读到这个中断被SET起来!(https://blog.csdn.net/love_maomao/article/details/8234039)
本质问题:RXNE还没来得及复位(数据可能可能被读传走也有可能没有被传走),就接收到新的字符,导致溢出错误,从而触发串口2的中断相应,这和HardFault_Handler错误挺像的,都是都是溢出导致的硬件错误,后面也会讲下这个问题。
并不是RXNE 触发的USART2_IRQHandler中断,而是ORE触发USART2_IRQHandler中断,和我一开始理解的有误,我理解成是RXNE触发。
RXNE:读数据寄存器非空 (Read data register not empty):当RDR移位寄存器中的数据被转移到USART_DR寄存器中,该位被硬件置位。如果USART_CR1寄存器中的RXNEIE为1,则产生中断。对USART_DR的读操作可以将该位清零。RXNE位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。 0:数据没有收到; 1:收到数据,可以读出。
ORE:过载错误 (Overrun error):当RXNE仍然是’1’的时候,当前被接收在移位寄存器中的数据,需要传送至RDR寄存器时,硬件将该位置位。如果USART_CR1中的RXNEIE为’1’的话,则产生中断。由软件序列将其清零(先读USART_SR,然后读USART_CR)。 0:没有过载错误; 1:检测到过载错误。 注意:该位被置位时,RDR寄存器中的值不会丢失,但是移位寄存器中的数据会被覆盖。如果设置了EIE位,在多缓冲器通信模式下,ORE标志置位会产生中断的。 (ORE会导致硬件复位,如果遇到这个问题是没有办法通过软件复位决绝的,刚开始遇到这个问题,已经是我写的程序有问题,打算添加看门狗进行软件复位,发现没有效果)
在打开接收使能时,会一起开始ORE中断使能,没有办法通过关闭ORE使能来规避问题。因此需要检查到ORE标志位后,需要手动清除ORE标志位。
3.解决办法:
使用USART_ClearITPendingBit();无法清除ORE的标志位,该函数只有CTS,LDB,TC和RXNE。
查找库函数手册:
最终加一个判断:
if(USART_GetFlagStatus(USART2,USART_FLAG_ORE) == SET) // 检查 ORE 标志
{
USART_ClearFlag(USART2,USART_FLAG_ORE);
USART_ReceiveData(USART2);
rxIndex = 0;
}
标签:ORE,USART,中断,寄存器,RXNE,STM32,串口,接收数据,USART2 From: https://www.cnblogs.com/wuqudelinghun/p/18586494