HAL库学习——串口中断一些注意点

1、现象

       最近在使用HAL库串口中断做数据接收时遇到了中断接收标志位开启,但是却收不到数据的问题。作者的代码时是在主程序初始化时使用HAL_UART_Receive_IT函数开启中断每次接收一个字符,由于HAL库的底层机制每接收一个字符后都会关闭中断并且进入中断回调函数,所以在中断回调函数里需要再次调用HAL_UART_Receive_IT函数开启中断。但是结果是重复开关单片机电源,出现偶尔串口数据会进不来(串口数据来源:外部模块上电后一直往串口吐)。

2、开发环境

     IDE:KEIL5 

     MCU:stm32l071

     操作系统:win10

3、原因

      由于一上电串口数据就往单片机吐,当串口初始化后,数据开始进来放到移位寄存器内,这时如果开启接收中断不及时就会造成进入ORE溢出错误,而HAL_UART_Receive_IT函数在执行到SET_BIT(huart->Instance->CR3, USART_CR3_EIE);这一语句后即会给切去中断函数执行ORE错误一些操作,执行到UART_EndRxTransfer函数把自己的状态huart->RxState = HAL_UART_STATE_READY_RX,而这时候要进入接收数据的条件是HAL_UART_STATE_BUSY_RX,所以造成了一直死锁的状态一进入中断就去清RXNE,具体相关函数如下:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
  /* Check that a Rx process is not already ongoing */
  if (huart->RxState == HAL_UART_STATE_READY)
  {
    if ((pData == NULL) || (Size == 0U))
    {
      return HAL_ERROR;
    }

    /* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
       should be aligned on a u16 frontier, as data to be received from RDR will be
       handled through a u16 cast. */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      if ((((uint32_t)pData) & 1) != 0)
      {
        return  HAL_ERROR;
      }
    }

    /* Process Locked */
    __HAL_LOCK(huart);

    huart->pRxBuffPtr  = pData;
    huart->RxXferSize  = Size;
    huart->RxXferCount = Size;
    huart->RxISR       = NULL;

    /* Computation of UART mask to apply to RDR register */
    UART_MASK_COMPUTATION(huart);

    huart->ErrorCode = HAL_UART_ERROR_NONE;
    huart->RxState = HAL_UART_STATE_BUSY_RX;

    /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
    SET_BIT(huart->Instance->CR3, USART_CR3_EIE);

    /* Set the Rx ISR function pointer according to the data word length */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      huart->RxISR = UART_RxISR_16BIT;
    }
    else
    {
      huart->RxISR = UART_RxISR_8BIT;
    }

    /* Process Unlocked */
    __HAL_UNLOCK(huart);

    /* Enable the UART Parity Error interrupt and Data Register Not Empty interrupt */
    SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);

    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}
static void UART_EndRxTransfer(UART_HandleTypeDef *huart)
{
  /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
  CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
  CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);

  /* At end of Rx process, restore huart->RxState to Ready */
  huart->RxState = HAL_UART_STATE_READY;

  /* Reset RxIsr function pointer */
  huart->RxISR = NULL;
}

       如有疑议,评论留言,博主回复。

猜你喜欢

转载自blog.csdn.net/wanruiou/article/details/107565507