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空闲中断不定长度数据接收和发送
相关推荐
BreezeJuvenile1 小时前
外设模块学习(15)——MQ-2烟雾气体传感器(STM32)
stm32·单片机·学习·mq-2·烟雾气体传感器
Jie_jiejiayou3 小时前
定时器详解以及呼吸灯实现 — STM32(HAL库)
stm32·单片机·嵌入式硬件·定时器
逆小舟3 小时前
【STM32】定时器、PWM
stm32·单片机·嵌入式硬件
XH1.3 小时前
学习RT-thread(RT-thread定时器)
stm32·单片机·学习
QT 小鲜肉4 小时前
【个人成长笔记】在 Linux 系统下撰写老化测试脚本以实现自动压测效果(亲测有效)
linux·开发语言·笔记·单片机·压力测试
申克Lab4 小时前
STM32 串口概念 UART协议
stm32·单片机·嵌入式硬件
小莞尔4 小时前
【51单片机】【protues仿真】基于51单片机自动浇花系统
单片机·嵌入式硬件
沐欣工作室_lvyiyi5 小时前
基于51单片机的宠物喂食器的设计与实现(论文+源码)
单片机·嵌入式硬件·毕业设计·51单片机·宠物
hazy1k8 小时前
51单片机基础-最小系统设计
stm32·单片机·嵌入式硬件·mcu·51单片机·proteus
奋斗的牛马9 小时前
FPGA—ZYNQ学习spi(六)
单片机·嵌入式硬件·学习·fpga开发·信息与通信