整理: MilerShao 曾多次碰到过有人在使用STM8或STM32的UART通信时因为相关接收中断请求标志未清除导致接收中断无限循环的问题,从而让人小受折磨。 STM8 与 STM32各系列MCU的UART功能框架基本是一样的。寄存器及相关位的定义和命名也基本一样,只是个别地方有些差异。围绕UART通信MCU可以产生发送中断、接收中断、出错中断以及其它特征信号中断。 STM8系列 MCU UART中断请求事件及标志列表与中断框架图 
 先看看STM8的UART接收中断。其接收中断使能位是RIEN,相应的中断请求事件有两个,一个接收数据寄存器非空,另一个是在接收数据寄存器非空情况下,又接收到新的数据,它们对应中断请求标志分别是RXNE和OR。也就是说,RXNE或OR事件都可以产生UART接收中断,而且OR事件是在RXNE事件的基础上进一步发生的。 既然这样,如果在UART接收中断里只检查RXNE标志以及清除动作,就有可能因为已经发生了OR中断请求而又未作处理。那麻烦就来了,OR中断请求事件会不停地产生UART接收中断,没完没了。遗憾的是,我们经常可能想不到是这里的原因。 鉴于此,建议在UART 接收中断里考虑做OR位的清除操作。对RXNE的清除可以通过读USART_DR寄存器或直接写0来清除。对OR标志的清除,稍微有点讲究,有人也在这犯错,对它简单直接写0是不会生效的。对OR清零要先读USART_SR,再读 USART_DR的操作。  如下示例代码里的1、2步就能做到清除RXNE和OR中断请求标志。 void USARTx_IRQHandler(void) { if(UARTx_GetITStatus(USARTx, UARTx_IT_RXNE)==SET) //1、读USART_SR { RxData = USARTx_ReceiveData(USARTx); //2、读USART_DR,清零RXNE //结合第1、2步也就清了OR位 ...... } } 再来简单看看STM32 MCU uart的接收中断。 同样,下面两幅图表是关于STM32F4系列 MCU UART中断请求事件及标志列表和中断框架图。相比上面STM8系列,可以很直观地看出除了些许表述上的差异和极个别地方外,STM8与STM32的UART中断框架及相关中断请求事件是一样的。
STM32F4系列 MCU UART中断请求事件及标志列表与中断框架图
 
还是看看STM32的UART接收中断。除了个别写法差异外,跟STM8基本一样,其接收中断使能位是RXNEIE,相应的接收中断请求事件也是两个,一个接收数据寄存器非空,另一个是在接收数据寄存非空情况下,又接收到新的数据,它们对应中断请求标志分别是RXNE和ORE。同样,RXNE或ORE事件都可以产生UART接收中断。 显然,跟上面STM8 uart谈到的一样,如果在STM32 UART接收中断里忽视了ORE事件及标志,同样可能会出现跟STM8 一样的情形,即UART接收中断没完没了循环进入的问题。 
为避免因为ORE中断请求标志未清除而导致UART接收中断循环进入的麻烦,处理办法跟上面STM8的一样。在接收中断里先读USART_SR,然后再读USART_DR.这样达到既清了RXNE又清了ORE位的目的。比如在下方官方库例程代码里,接收中断处理程序就做了RXNE和ORE的清除操作,他们由蓝色代码完成。 void USARTx_IRQHANDLER(void) { if(USART_GetITStatus(EVAL_COM1, USART_IT_RXNE) != RESET) // 1读_SR { /* Read one byte from the receive data register */ aRxBuffer[RxCounter++] = (USART_ReceiveData(EVAL_COM1) & 0x7F);//2读 _DR 。。。。。。 } 。。。。。。 } |