【问题标题】:HAL_UART_Receive_DMA works only once. How can I fix it?HAL_UART_Receive_DMA 只工作一次。我该如何解决?
【发布时间】:2022-12-10 14:34:27
【问题描述】:

我正在使用 STM32F103RB 板,我想简单地将我通过串行端口从计算机收到的所有内容回显到该端口。我必须使用 UART 和 DMA 来完成。我已经在正常模式下使用 CubeMX 在 USART2_RX 上设置了 DMA。我的问题是 HAL_UART_RxCpltCallback 只被调用一次。有趣的是,我在 PC 端得到了响应,但有额外的 0xFC 字节。之后,控制器停止对通过串口发送的新数据做出反应,直到我用 usb 拔下并重新插入控制器时才会这样做。这是回调和主要功能的代码:

#define BUF_SIZE 16

uint8_t RX_BUF[BUF_SIZE] = {0};
uint8_t TX_BUF[BUF_SIZE] = {0};

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
  HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
  HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
}

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 */
  HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

编辑:我正在尝试通过 USB-C 加密狗在 Mac 上执行此操作。这可能是问题所在吗?

【问题讨论】:

    标签: stm32 uart dma stm32f1 stm32cubemx


    【解决方案1】:

    在 ISR 中调用复杂函数不是一个好主意。许多 HAL 函数使用系统节拍来测量超时,并且根据您的中断优先级,节拍可能会在您的 ISR 运行时被阻止。

    最好将任何复杂的处理从你的 ISR 移到 main 函数中。只需在 ISR 中设置一个标志以指示接收何时完成。就像是:

    static volatile bool uart_rx_done = false;
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        uart_rx_done = true;
    }
    
    int main()
    {
        // Initialisation stuff
    
        for (;;)
        {
            uart_rx_done = false;
            HAL_UART_Receive_DMA(&huart2, RX_BUF, BUF_SIZE);
            while (!uart_rx_done)
                ;
    
            HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
        }
    }
    

    【讨论】:

    • 不幸的是,这并没有解决我的问题。我尝试了这个解决方案和使用 DMA 在 ISR 中传输,但没有效果。
    • 您可以在帖子中添加 RX_BUF 和 BUF_SIZE 的定义吗?
    • 我更新了代码。它们分别是一个固定大小的 uint8_t 数组和一个宏。
    【解决方案2】:

    首先,检查您是否正确配置了uartdma中断。 在 stm21f1xx_it.c 文件中你应该看到这些函数

    void DMA1_Channel6_IRQHandler(void)
    {
      /* USER CODE BEGIN DMA1_Channel6_IRQn 0 */
    
      /* USER CODE END DMA1_Channel6_IRQn 0 */
      HAL_DMA_IRQHandler(&hdma_usart2_rx);
      /* USER CODE BEGIN DMA1_Channel6_IRQn 1 */
    
      /* USER CODE END DMA1_Channel6_IRQn 1 */
    }
    
    
    void USART2_IRQHandler(void)
    {
      /* USER CODE BEGIN USART2_IRQn 0 */
    
      /* USER CODE END USART2_IRQn 0 */
      HAL_UART_IRQHandler(&huart2);
      /* USER CODE BEGIN USART2_IRQn 1 */
    
      /* USER CODE END USART2_IRQn 1 */
    }
    
    

    以及 main.c 文件中 MX_NVIC_Init() 函数中的 uart2 配置。

    但是你的主要错误是你根本没有激活uart接收中断。我建议暂时不要使用dma,试试看uart中断是否被激活:

    #define BUF_SIZE 16
    bool uart_received = false;
    
    uint8_t RX_BUF[BUF_SIZE] = {0};
    uint8_t TX_BUF[BUF_SIZE] = {0};
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
      // HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
      uart_received = true;
      HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
    }
    
    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 */
      //HAL_UART_Receive_DMA(&huart2, RX_BUF, sizeof (RX_BUF));
      HAL_UART_Receive_IT(&huart2, RX_BUF, BUF_SIZE);
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
          if (uart_received) {
              HAL_UART_Transmit(&huart2, RX_BUF, BUF_SIZE, 1000);
              uart_received = false;
          }
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
      }
      /* USER CODE END 3 */
    }
    

    如果这有效,那么您可以使用HAL_UARTEx_ReceiveToIdle_DMA激活uart-dma中断和HAL_UARTEx_RxEventCallback回调函数(假设配置了dam中断)。

    【讨论】:

      猜你喜欢
      • 2019-10-31
      • 2015-04-02
      • 1970-01-01
      • 2017-01-27
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 2022-10-17
      • 1970-01-01
      相关资源
      最近更新 更多