解决STM32串口溢出中断问题(一直进中断服务函数)

现象:MCU为STM32L431,使用uCOS-III作为实时操作系统,使用串口接收升级数据包后,失能串口及串口中断,此时不能进行任务调度,发现程序没有跑飞,而是一直进入串口中断。串口的ISR寄存器如下:
解决STM32串口溢出中断问题(一直进中断服务函数)_第1张图片
串口中断服务函数的判断条件是:

if( SET == __HAL_UART_GET_IT_SOURCE(&huart[BLE_UART], UART_IT_RXNE))
{
}

但是没有数据的情况下,也能进入,查看手册中串口中断描述:
解决STM32串口溢出中断问题(一直进中断服务函数)_第2张图片

关于CR1寄存器中RXNEIE描述如下:
解决STM32串口溢出中断问题(一直进中断服务函数)_第3张图片
可以看到当ISR寄存器中ORE或者RXNE被置位时会产生串口中断,也就是说ORE中断在使能接收中断时被默认打开了。

关于ISR寄存器中RXNE描述如下:
解决STM32串口溢出中断问题(一直进中断服务函数)_第4张图片
当 RDR 移位寄存器的内容已传输到 USART_RDR 寄存器时,该位由硬件设置,此时数据已经准备好被读取。

关于ISR寄存器中ORE描述如下:
解决STM32串口溢出中断问题(一直进中断服务函数)_第5张图片
当 RXNE=1 时,当移位寄存器中当前接收的数据准备好传输到 RDR 寄存器时,该位由硬件置位,也就是说数据没有被及时读取,RXNE也就没有清零,因此还是产生接收中断,即使在没有数据的情况下,还是会一直进入串口中断服务函数。ORE位需要向USART_ICR寄存器中ORECF位写1来清零。

当准备使用__HAL_UART_GET_IT(HANDLE, INTERRUPT)或者__HAL_UART_GET_IT_SOURCE(HANDLE, INTERRUPT)函数读UART_IT_ORE中断时发现这两个函数不可以使用UART_IT_ORE作为参数,但可以使用UART_IT_ERR作为参数 ,此时要打开相应的UART_IT_ERR中断,ERR中断可以由Frame error, noise error或者overrun error产生。

不使能UART_IT_ERR中断时可以使用 __HAL_UART_GET_FLAG(HANDLE, FLAG)函数来读UART_FLAG_ORE标志,有关定义如下:

#define UART_FLAG_ORE                       USART_ISR_ORE           /*!< UART overrun error                        */

/*******************  Bit definition for USART_ISR register  ******************/
#define USART_ISR_PE_Pos              (0U)
#define USART_ISR_PE_Msk              (0x1UL << USART_ISR_PE_Pos)              /*!< 0x00000001 */
#define USART_ISR_PE                  USART_ISR_PE_Msk                         /*!< Parity Error */
#define USART_ISR_FE_Pos              (1U)
#define USART_ISR_FE_Msk              (0x1UL << USART_ISR_FE_Pos)              /*!< 0x00000002 */
#define USART_ISR_FE                  USART_ISR_FE_Msk                         /*!< Framing Error */
#define USART_ISR_NE_Pos              (2U)
#define USART_ISR_NE_Msk              (0x1UL << USART_ISR_NE_Pos)              /*!< 0x00000004 */
#define USART_ISR_NE                  USART_ISR_NE_Msk                         /*!< Noise Error detected Flag */
#define USART_ISR_ORE_Pos             (3U)
#define USART_ISR_ORE_Msk             (0x1UL << USART_ISR_ORE_Pos)             /*!< 0x00000008 */
#define USART_ISR_ORE                 USART_ISR_ORE_Msk                        /*!< OverRun Error */
#define USART_ISR_IDLE_Pos            (4U)
#define USART_ISR_IDLE_Msk            (0x1UL << USART_ISR_IDLE_Pos)            /*!< 0x00000010 */
#define USART_ISR_IDLE                USART_ISR_IDLE_Msk                       /*!< IDLE line detected */
#define USART_ISR_RXNE_Pos            (5U)
#define USART_ISR_RXNE_Msk            (0x1UL << USART_ISR_RXNE_Pos)            /*!< 0x00000020 */
#define USART_ISR_RXNE                USART_ISR_RXNE_Msk                       /*!< Read Data Register Not Empty */

#define __HAL_UART_GET_FLAG(__HANDLE__, __FLAG__) (((__HANDLE__)->Instance->ISR & (__FLAG__)) == (__FLAG__))

可以看到使用__HAL_UART_GET_FLAG函数读的就是ISR寄存器。当读到溢出中断后,直接调用__HAL_UART_CLEAR_FLAG函数操作ICR寄存器清除该中断就可以了。

#define UART_CLEAR_PEF                       USART_ICR_PECF            /*!< Parity Error Clear Flag           */
#define UART_CLEAR_FEF                       USART_ICR_FECF            /*!< Framing Error Clear Flag          */
#define UART_CLEAR_NEF                       USART_ICR_NECF            /*!< Noise Error detected Clear Flag   */
#define UART_CLEAR_OREF                      USART_ICR_ORECF           /*!< Overrun Error Clear Flag          */

#define __HAL_UART_CLEAR_FLAG(__HANDLE__, __FLAG__) ((__HANDLE__)->Instance->ICR = (__FLAG__))


__HAL_UART_CLEAR_FLAG(&huart[BLE_UART], UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF);

你可能感兴趣的:(STM32,stm32,单片机,串口通信)