STM32-USART HAL库接收任意长度数据详细解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014470361/article/details/78708892

前言:

最近在调试STM32L152 HAL库串口接收任意长度数据程序,详细解析下接收任意长度数据的方法。

硬件平台:STM32L152

软件平台:keil v5+cubeMX

函数库:HAL库

STM32L152 —USART

STM32L152  USART 的HAL库中接收函数:

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);

该函数的参数Size固定,使用时很不方便,只能接收固定长度的数据。

本文详细解析HAL库UASRT接收函数并修改成接收任意长度。PS:仅适用于接收数据结尾为换行符0x0a,若接收数据为其他格式,可根据数据的特点进行修改。

1.HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer, 200);

开始接收终端,设定一个初始长度200,接收的任意字节数不大于200就行。

2.中断处理函数

void USART1_IRQHandler(void)
{
    HAL_UART_IRQHandler(&huart1); 
}

3.在HAL_UART_IRQHandler(&huart1)的定义找到接收终端函数  :UART_Receive_IT(huart);

void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
{
  uint32_t tmp_flag = 0, tmp_it_source = 0;


  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_PE);
  tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE);  
  /* UART parity error interrupt occurred ------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  { 
    huart->ErrorCode |= HAL_UART_ERROR_PE;
  }
  
  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_FE);
  tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR);
  /* UART frame error interrupt occurred -------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  {
    huart->ErrorCode |= HAL_UART_ERROR_FE;
  }
  
  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_NE);
  /* UART noise error interrupt occurred -------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  {
    huart->ErrorCode |= HAL_UART_ERROR_NE;
  }
  
  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_ORE);
  /* UART Over-Run interrupt occurred ----------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  {
    huart->ErrorCode |= HAL_UART_ERROR_ORE;
  }
  
  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE);
  tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE);
  /* UART in mode Receiver ---------------------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  { 
    UART_Receive_IT(huart);
  }
  
  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_TXE);
  tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE);
  /* UART in mode Transmitter ------------------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  {
    UART_Transmit_IT(huart);
  }


  tmp_flag = __HAL_UART_GET_FLAG(huart, UART_FLAG_TC);
  tmp_it_source = __HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC);
  /* UART in mode Transmitter end --------------------------------------------*/
  if((tmp_flag != RESET) && (tmp_it_source != RESET))
  {
    UART_EndTransmit_IT(huart);
  }  


  if(huart->ErrorCode != HAL_UART_ERROR_NONE)
  {
    /* Clear all the error flag at once */
    __HAL_UART_CLEAR_PEFLAG(huart);
    
    /* Set the UART state ready to be able to start again the process */
    huart->State = HAL_UART_STATE_READY;
    
    HAL_UART_ErrorCallback(huart);
  }  
}.

4.接下来是修改UART_Receive_IT(huart) 函数;

u8 flag,Rx_Size;
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
  uint16_t* tmp;
  uint32_t tmp_state = 0;

  tmp_state = huart->State; 
  if((tmp_state == HAL_UART_STATE_BUSY_RX) || (tmp_state == HAL_UART_STATE_BUSY_TX_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 += 2;
      }
      else
      {
        *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
        huart->pRxBuffPtr += 1;
      }
    }
    else
    {
      if(huart->Init.Parity == UART_PARITY_NONE)//本例串口为非奇偶校验
      {

        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
if(((uint8_t)(huart->Instance->DR & (uint8_t)0x00FF))==0x0a) flag++;   //当收到0x0A换行符时认为接收结束。
Rx_Size++;

      }
      else
      {
        *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
      }
    }





//   if(--huart->RxXferCount == 0)    //  原程序根据设定的接收缓存RxXferCount减为0时认为接收结束,注释掉,修改为if(flag== 1);

    if(flag== 1)
    {
      flag=0;
      __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);


      /* Check if a transmit process is ongoing or not */
      if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 
      {
        huart->State = HAL_UART_STATE_BUSY_TX;
      }
      else
      {
        /* 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);


        huart->State = HAL_UART_STATE_READY;
      }
      HAL_UART_RxCpltCallback(huart);


      return HAL_OK;
    }
    return HAL_OK;
  }
  else
  {
    return HAL_BUSY; 
  }
}

5.编写UART串口回调函数,重新开启接收中断并清标志;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    if(huart->Instance==USART1)
    { 
    HAL_UART_Transmit(&huart3 ,(uint8_t *)aRxBuffer,Rx_Size ,200);//用串口3打印出    来接收的数据,可忽略
    HAL_UART_Receive_IT(&huart1,(uint8_t *)aRxBuffer, 200);//重新开中断
    for(u8 i=0;i<Rx_Size;i++)aRxBuffer[i]=0; //清除接收缓存
    Rx_Size=0;//清除接收的计数,下次接收重新计数
    }
}

以上修改,便可接收结尾为0x0a的任意长度的数据。但修改HAL库并不是一个好的解决方法;若别人要移植你的程序,会给别人移植程序带来困难。使用DMA方式进行串口的接收是一个较优的方法,见:传送门

展开阅读全文

没有更多推荐了,返回首页