STM32之HAL库—-使用STM32CubeMX配置串口DMA发送数据时不开启串口中断只发送一次数据。

问题

       最近在学习使用STM32CubeMX配置DMA时,使用UART作为示例来演示DMA的功能,遇到一个问题,使用串口和DMA传输数据时,在不开启串口中断时,程序只能发送一次数据,查阅了一些资料和博客,总算搞清楚了。

环境配置

        使用的是STMF103系列的板子。使用STM32CubeMX配置串口1工作在DMA模式下。

1、选择串口

2、开启串口中断

3、添加DMA

DMA参数保持默认即可

DMA通道的中断在这里会被强制开启。

这里主要并不是讲解如何使用STM32CubeMX配置DMA的,所以只展示了串口和DMA的配置。

例程

1、UART+DMA发送数据(开串口中断)

        打开生成的工程,新建一个变量

uint8_t sendBuff[] = "USART test by DMA\r\n";

         在 man.c 中的主循环添加以下代码:

  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    HAL_UART_Transmit_DMA(&huart1, (uint8_t *)sendBuff, sizeof(sendBuff));
    HAL_Delay(500);      
    /* USER CODE END WHILE */

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

通过串口助手可以看出不断有数据打印出来

2、UART+DMA发送数据(关串口中断)

关闭中断,重新生成代码。

重新烧录一边程序,按下复位键,串口打印如下:

代码分析,为什么不开启串口中断只打印一次

        重新打开串口中断,生成代码。

DMA发送数据的中断函数入口是:

void DMA1_Channel4_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel4_IRQn 0 */

  /* USER CODE END DMA1_Channel4_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart1_tx);
  /* USER CODE BEGIN DMA1_Channel4_IRQn 1 */

  /* USER CODE END DMA1_Channel4_IRQn 1 */
}

USART1的中端入口是:

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 */

  /* USER CODE END USART1_IRQn 1 */
}

DMA数据发送分析:

1、开启DMA数据传输

点击HAL_UART_Transmit_DMA(&huart1, (uint8_t *)sendBuff, sizeof(sendBuff));进入定义中。

①:判断USART外设当前状态,是否为准备使用

②:将USART外设状态设置为忙碌(记住目前的USART为忙碌)

③:UART_DMATransmitCplt为DAM中断回调函数,huart->hdmatx->XferCpltCallback是一个函数指针。

④:启用DMA传输请求。

记住这四点,后面都要用到。

2、当DMA数据传输完成后,进入中断。

点击HAL_DMA_IRQHandler(&hdma_usart1_tx);进入定义中。

红箭头所指的部分是DMA发送完成的回调函数,它是一个函数指针,也就是调用了函数UART_DMATransmitCplt。

3、调用DMA回调函数

⑤:清除串口到DMA的数据传输标志位。

⑥:使能了串口发送完成中断TCIE。

4、串口中断查看

        因为在DMA发送完成后,在回调函数中开启了串口数据发送完成中断,因此,当数据发送完成时,会进入串口中断中。

        

        找到串口发送模式,在进入UART_EndTransmit_IT(huart);函数定义中

如下所示:

⑧:关闭串口发送完成中断

⑨:USART外设当前的状态改为准备使用。(从忙碌态转为了空闲)

至此,一次数据发送完成了。下次发送数据再次调用HAL_UART_Transmit_DMA函数开始。

如果没有串口中断函数,在第一次发送数据时,第②步将USART设为忙碌后,数据传输完成后,没有串口中断函数则不会有第⑨步将USART变为可准备态,便不会在启动DMA到USART的数据传输。

参考博客:

(stm32之HAL库)UART工作在DMA模式要打开串口中断吗?_hal uart dma-CSDN博客

STM32CubeMX学习笔记(7)——DMA接口使用_cubemx dma-CSDN博客

作者:菜鸟_爱学习

物联沃分享整理
物联沃-IOTWORD物联网 » STM32之HAL库—-使用STM32CubeMX配置串口DMA发送数据时不开启串口中断只发送一次数据。

发表回复