STM32
直播中

王银喜

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

如何接收STM32串口不定长字符?

如何接收STM32串口不定长字符?

回帖(1)

王莉

2021-12-7 10:23:37
本文参考了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("nr[IDLE]Received %d Bytes:",__Rev_Size);
  for(uint16_t i = 0; i < __Rev_Size; i++)
  {
    printf(" 0x%02X", __UART_RX_Buf);
  }  
  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);
}


至此,修改完成。
举报

更多回帖

×
20
完善资料,
赚取积分