STM32 开启接收空闲中断后再开DMA,DMA不能接收到数据问题

一 问题描述

使用STM32F091CBT6时使用空闲中断加DMA方式实现接收不定长度的数据时,发现DMA不能正常接收数据,但接收到串口数据后能进入串口中断,但出现OVERRUN错误。

二 问题原因

1. 使用Cubemx生成的代码中初始化DMA是在初始化串口后面进行

/* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();
  MX_USART1_UART_Init();
  MX_USART4_UART_Init();
  MX_TIM1_Init();
  MX_ADC_Init();
  MX_DMA_Init();	

2. 开启空闲中断后,系统一上电就会产生一次串口中断,在串口中断处理函数HAL_UART_IRQHandler中检测到OVERRUN错误,将DMA接收功能关闭

 /* If Error is to be considered as blocking :
          - Receiver Timeout error in Reception
          - Overrun error in Reception
          - any error occurs in DMA mode reception
      */
      errorcode = huart->ErrorCode;
      if ((HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) ||
          ((errorcode & (HAL_UART_ERROR_RTO | HAL_UART_ERROR_ORE)) != 0U))
      {
        /* Blocking error : transfer is aborted
           Set the UART state ready to be able to start again the process,
           Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
        UART_EndRxTransfer(huart);

        /* Disable the UART DMA Rx request if enabled */
        if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
        {
          CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);

          /* Abort the UART DMA Rx channel */
          if (huart->hdmarx != NULL)
          {
            /* Set the UART DMA Abort callback :
               will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
            huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;

            /* Abort DMA RX */
            if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
            {
              /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */
              huart->hdmarx->XferAbortCallback(huart->hdmarx);
            }
          }

三解决方法

将DMA初始化调整到串口初始之前进行,问题解决

/* USER CODE BEGIN SysInit */
	MX_DMA_Init();					//一定要在串口初始化之前
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  
  MX_GPIO_Init();
  MX_CAN_Init();
  MX_USART1_UART_Init();
  MX_USART4_UART_Init();
  MX_TIM1_Init();
  MX_ADC_Init();

你可能感兴趣的:(STM32)