STM32 串口UART DMA Idel 接收调试记录

STM32 串口UART DMA Idol 接收调试记录

背景

在使用STM32CubeMX配置串口DMA+IDLE中断接收不定长度数据时,发现只有在main函数调用HAL_UARTEx_ReceiveToIdle_DMA()时执行一次,在中断回调函数中再次开启DMA时,发现huart- rxstate = 0x22 (HAL_UART_STATE_BUSY_RX),RX一直处于Busy状态,无法再次开启DMA接收。

最开始代码如下:

  1. 在main函数中启动DMA接收
c 复制代码
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  printf("Motor ready.\r\n");

  HAL_UARTEx_ReceiveToIdle_DMA(&huart2, (uint8_t *)rcv_buff, sizeof(rcv_buff));


  delay_ms(500);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
      HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
//      HAL_UART_Transmit_DMA(&huart2, s_buff, sizeof (s_buff));
//      HAL_Delay(500);

      delay_ms(500);
      commander_run();
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
  1. 接收到IDEL信号后,在中断回调函数中重新启动DMA接收
c 复制代码
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(DEBUG_UART == 2)
	{
		HAL_UARTEx_ReceiveToIdle_DMA(huart, (uint8_t *)rcv_buff, sizeof(rcv_buff));
		rcv_flag = 1;
	}
}

解决

代码单步调试发现,中断回调函数中调用HAL_UARTEx_ReceiveToIdle_DMA()再次启动DMA时,

串口接收寄存器状态huart- rxstate = 0x22 (HAL_UART_STATE_BUSY_RX) ,一直处于busy状态。

必须先调用HAL_UART_DMAStop()关闭DMA后,huart- rxstate = 0x20(HAL_UART_STATE_READY),才能调用HAL_UARTEx_ReceiveToIdle_DMA()再次启动DMA

代码如下:

c 复制代码
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
		// 必须关闭DMA,否则huart- rxstate = 0x22 (HAL_UART_STATE_BUSY_RX),
		// 调用HAL_UARTEx_ReceiveToIdle_DMA()时,无法正常开启,还是继续上次开启的Idle DMA
		HAL_UART_DMAStop(huart);
		HAL_UARTEx_ReceiveToIdle_DMA(huart, (uint8_t *)rcv_buff, sizeof(rcv_buff));
}

参考:

  1. STM32-HAL库串口DMA空闲中断的正确使用方式+解析SBUS信号
  2. STM32CubeMX HAL库串口+DMA+IDLE空闲中断不定长度数据接收和发送
相关推荐
极客小张24 分钟前
基于STM32MP157与OpenCV的嵌入式Linux人脸识别系统开发设计流程
linux·stm32·单片机·opencv·物联网
OH五星上将1 小时前
OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【扩展组件】上
linux·嵌入式硬件·harmonyos·openharmony·鸿蒙开发·liteos-a·鸿蒙内核
浅陌pa1 小时前
24:RTC实时时钟
c语言·stm32·单片机·嵌入式硬件
敲上瘾2 小时前
多态的使用和原理(c++详解)
开发语言·数据结构·c++·单片机·aigc·多态·模拟
小熊在忙fpga2 小时前
STM32如何修改外部晶振频率和主频
stm32·单片机·嵌入式硬件
我命由我123452 小时前
GPIO 理解(基本功能、模拟案例)
linux·运维·服务器·c语言·c++·嵌入式硬件·c#
学习日记hhh3 小时前
STM32G431RBT6(蓝桥杯)串口(发送)
stm32·单片机·嵌入式硬件
老李的森林3 小时前
嵌入式开发--STM32延时函数重构
stm32·单片机·嵌入式硬件·重构·延时
OH五星上将5 小时前
OpenHarmony(鸿蒙南向开发)——小型系统内核(LiteOS-A)【内核通信机制】上
linux·嵌入式硬件·harmonyos·openharmony·鸿蒙开发·liteos-a·鸿蒙内核
爱桥代码的程序媛5 小时前
鸿蒙OpenHarmony【轻量系统内核通信机制(互斥锁)】子系统开发
嵌入式硬件·harmonyos·鸿蒙·openharmony··鸿蒙开发·子系统开发