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

本文参考了STM32论坛应用笔记,由于原笔记修改了底层HAL库,Cube更新代码时会导致修改被覆盖,因此,在原笔记基础上做了修改。
理论上本笔记适用于所有带IDLE中断的MCU。
这里以STM32L051为例

首先配置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中断

原文中启用IDLE中断代码位于HAL_UART_Receive_DMA函数内,这里移出来,避免修改底层程序,就不怕Cube更新工程时代码覆盖了

在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("\n\r[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);
 }

至此,修改完成。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值