STM32
直播中

张浩

7年用户 1118经验值
私信 关注
[问答]

stm32f103 keil5 HAL库UART中断接收的知识点汇总,错过绝对后悔

STM32f103 keil5 HAL库UART中断接收的知识点汇总,错过绝对后悔

回帖(1)

秦玫

2021-12-14 11:44:54
1.根据选择的串口使能中断,由于需要,我将串口空闲(IDLE)中断时能,并使能串口接收中断


HAL_NVIC_EnableIRQ(USART3_IRQn);//使能USART3中断
HAL_NVIC_SetPriority(USART3_IRQn,3,3);//配置USART3的优先级               
HAL_UART_Receive_IT(&huart3,correction_Table, datalength);//correction_Table是申请的数组首地址
  __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE); //使能串口空闲(IDLE)中断
2.在中断函数中调用HAL_UART_IRQHandler(&huart3)函数,并判断是否有IDLE中断 ,IDLE中断的作用是用来接收可变的数据量,当发送的数据个数小于datalength时可以根据读取出(&huart3)->RxXferCount的值来判断接收到的数据个数
void USART3_IRQHandler(void)                       
{
        uint32_t  value_RxXferSize=0;
        uint32_t   value_RxXferCount=0;
                uint32_t temp_IDLE_flag=0;
       
        temp_IDLE_flag=__HAL_UART_GET_FLAG(&huart3,UART_FLAG_IDLE);//检测UART是否是空闲中断
        if(temp_IDLE_flag!=RESET)
        {
                __HAL_UART_CLEAR_IDLEFLAG(&huart3);//清除UART的空闲(IDLE)中断
           value_RxXferSize= (&huart3)->RxXferSize;       /*!< UART Rx Transfer size              */
           value_RxXferCount= (&huart3)->RxXferCount;      /*!< UART Rx Transfer Counter           */  
               
        }
        HAL_UART_IRQHandler(&huart3);//这个函数的功能包含了接收UART数据的功能  是调用了 UART_Receive_IT(huart)来实            现的
}       


3.UART_Receive_IT(UART_HandleTypeDef *huart)的实现如下,当接收到的数据个数 RxXferCount达到预定的值时,代码
if(--huart->RxXferCount == 0U) 会先关闭UART的接收中断__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);然后调用回调函数 HAL_UART_RxCpltCallback(huart);


static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint16_t* tmp;
  
  /* Check that a Rx process is ongoing */
  if(huart->RxState == HAL_UART_STATE_BUSY_RX)
  {
    if(huart->Init.WordLength == UART_WORDLENGTH_9B)
    {
      tmp = (uint16_t*) huart->pRxBuffPtr;
      if(huart->Init.Parity == UART_PARITY_NONE)
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
        huart->pRxBuffPtr += 2U;
      }
      else
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
        huart->pRxBuffPtr += 1U;
      }
    }
    else
    {
      if(huart->Init.Parity == UART_PARITY_NONE)
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
      }
      else
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
      }
    }

    if(--huart->RxXferCount == 0U)
    {
      /* Disable the IRDA Data Register not empty Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);//关闭UART的接收中断

      /* Disable the UART Parity Error Interrupt */
      __HAL_UART_DISABLE_IT(huart, UART_IT_PE);
        /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
        __HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

      /* Rx process is completed, restore huart->RxState to Ready */
      huart->RxState = HAL_UART_STATE_READY;

      HAL_UART_RxCpltCallback(huart);

      return HAL_OK;
    }
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY;
  }
}
4.系统自带的回调函数,我测试的时候不好用,所以将其注释掉,自己写了一个简单的功能 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)。功能如下,重新配置  HAL_UART_Receive_IT(huart,correction_Table, datalength);函数,由于在第3步关闭了UART的接收中断,所以要在此使能UART中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{

            if(huart==&huart3)
                        {
                           HAL_UART_Receive_IT(huart,correction_Table, datalength);//重新配置
         
                          __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);//使能UART中断
                         
                        }
         
            
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分