最近在调试GD32F4xx,想使用串口的闲时中断,发现与STM32有些区别。在此做个记录,备忘,防止重复踩坑。

串口使能中断相关代码:

1
2
3
nvic_irq_enable(USART0_IRQn,0,1);
usart_interrupt_enable(USART0, USART_INT_RBNE);         /* 使能USART0读区非空中断 */  
usart_interrupt_enable(USART0, USART_INT_IDLE);         /* 使能USART0空闲中断 */

串口中断处理函数:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
void USART0_IRQHandler(void)
{
    if ((RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE)) &&
        (RESET != usart_flag_get(USART0, USART_FLAG_RBNE))) {
        unsigned char value = usart_data_receive(USART0);
        RingBufWrite(g_debugRingBuf, value);		//将接收到的数据写入ringbuf中
        usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE); //清中断标志

    }
    else if (RESET != usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE)) {
        usart_interrupt_flag_clear(USART0, USART_INT_FLAG_IDLE);
        usart_data_receive(USART0); /* 清除接收完成标志位 */
        (void)LOS_EventWrite(&g_shellInputEvent, 0x1); //事件通知接收完成
    }
}

特别要注意的是:与STM32F4不同的是,在进入闲时中断后,需要调用usart_data_receive函数,用于清除接收完成标志位,否则闲时中断会存在被触发多次或不触发的情况。

在STM32f4xx中,清除闲时中断标志宏定义如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
/** @brief  Clears the UART IDLE pending flag.
  * @param  __HANDLE__ specifies the UART Handle.
  *         UART Handle selects the USARTx or UARTy peripheral
  *         (USART,UART availability and x,y values depending on device).
  * @retval None
  */
#define __HAL_UART_CLEAR_IDLEFLAG(__HANDLE__) __HAL_UART_CLEAR_PEFLAG(__HANDLE__)

/** @brief  Clears the UART PE pending flag.
  * @param  __HANDLE__ specifies the UART Handle.
  *         UART Handle selects the USARTx or UARTy peripheral
  *         (USART,UART availability and x,y values depending on device).
  * @retval None
  */
#define __HAL_UART_CLEAR_PEFLAG(__HANDLE__)     \
  do{                                           \
    __IO uint32_t tmpreg = 0x00U;               \
    tmpreg = (__HANDLE__)->Instance->SR;        \
    tmpreg = (__HANDLE__)->Instance->DR;        \
    UNUSED(tmpreg);                             \
  } while(0U)

可以看到有读取操作对DR寄存器进行读取操作,相当于GD32标准库中usart_data_receive函数的作用。