手把手STM32串口不定长字符接收教程——基于HAL

首先配置Cube工程如下:

启用串口接收DMA

启用串口中断

接下来时代码部分:

首先在main函数初始化后插入:

HAL_UART_Receive_DMA(&huart1, __UART_RX_Buf, __BUFFER_SIZE);
      /* Enable the UART IDLE Interrupt*/
  SET_BIT(huart1.Instance->CR1, USART_CR1_IDLEIE);//启用IDLE中断

在uart.c开头插入:

uint8_t __UART_RX_Buf[__BUFFER_SIZE] = {
          
   0};
uint32_t __Rev_Size = 0;

为了方便跨文件调用,在uart.h插入

#define __BUFFER_SIZE 50 //可根据情况设置,要大于可能最长的一帧
extern uint8_t __UART_RX_Buf[__BUFFER_SIZE];
extern uint32_t __Rev_Size;

在stm32l0xx_it.c文件中的USART1_IRQHandler函数专门为用户预留了插入代码空间,刚好可以把我们需要的功能插入:

/**
  * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
  */
void USART1_IRQHandler(void)
{
          
   
  /* USER CODE BEGIN USART1_IRQn 0 */

  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
  UART_HandleTypeDef *huart = &huart1;
  uint32_t isrflags   = READ_REG(huart->Instance->ISR);
  uint32_t cr1its     = READ_REG(huart->Instance->CR1);

    //Modification 2
 if(((isrflags & USART_ISR_IDLE) != RESET) && ((cr1its & USART_CR1_IDLEIE) != RESET))
 {
          
   
    //Record the received bytes number
    __Rev_Size = huart->RxXferSize - huart->hdmarx->Instance->CNDTR;
    //clear the IDLE flag
    __HAL_UART_CLEAR_IDLEFLAG(huart);
    //Abord the received process
    CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE| USART_CR1_IDLEIE));
    HAL_UART_AbortReceive_IT(huart);
    // return;
 }

  /* USER CODE END USART1_IRQn 1 */
}

注意原笔记基于F4,与L0有区别: 串口寄存器 F4

USART_SR_IDLE

STM32L051为

USART_ISR_IDLE

DMA中寄存器,F4为

huart->hdmarx->Instance->NDTR

STM32L051为

huart->hdmarx->Instance->CNDTR

接下来定义回调函数,这里会在一帧数据成功接收后被调用

void HAL_UART_AbortReceiveCpltCallback (UART_HandleTypeDef *huart)
{
          
   
   //Print received Bytes
  printf("

[IDLE]Received %d Bytes:",__Rev_Size);
  for(uint16_t i = 0; i < __Rev_Size; i++)
  {
          
   
    printf(" 0x%02X", __UART_RX_Buf[i]);
  }  
  HAL_UART_Transmit(huart, __UART_RX_Buf, __Rev_Size, 100);
  //Re-start receiving
  HAL_UART_Receive_DMA(huart, __UART_RX_Buf, __BUFFER_SIZE);
      /* Enable the UART IDLE Interrupt*/
  SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
 }

至此,修改完成。

经验分享 程序员 微信小程序 职场和发展