×
单片机 > 单片机程序设计 > 详情

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

发布时间:2020-08-24 发布时间:
|

前言:

最近在调试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=0;//清除接收的计数,下次接收重新计数

    }

}

以上修改,便可接收结尾为0x0a的任意长度的数据。但修改HAL库并不是一个好的解决方法;若别人要移植你的程序,会给别人移植程序带来困难。

关键字:STM32  USART  HAL库 


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
51单片机中断源的扩展方法