STM32F103 STM32CUBE HAL库 串口DMA发送无法执行回调

STM32F103 STM32CUBE HAL库 串口DMA接收无法执行回调

一、STM32CubeMX 串口DMA配置

配置串口2波特率19200,启用DMA发送正常模式。配置DMA中断。

二、串口程序生成代码

串口初始化程序

c 复制代码
void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 19200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

DMA中断处理程序入口

c 复制代码
/**
  * @brief This function handles DMA1 channel6 global interrupt.
  */
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 */
}

/**
  * @brief This function handles DMA1 channel7 global interrupt.
  */
void DMA1_Channel7_IRQHandler(void)
{
  /* USER CODE BEGIN DMA1_Channel7_IRQn 0 */

  /* USER CODE END DMA1_Channel7_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_usart2_tx);
  /* USER CODE BEGIN DMA1_Channel7_IRQn 1 */

  /* USER CODE END DMA1_Channel7_IRQn 1 */
}

三、代码新增

3.1 自定义DMA回调函数

弱函数重定义

c 复制代码
/**
  * @brief  Tx Transfer completed callbacks.
  * @param  huart  Pointer to a UART_HandleTypeDef structure that contains
  *                the configuration information for the specified UART module.
  * @retval None
  */
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
  /* Prevent unused argument(s) compilation warning */
  UNUSED(huart);
  /* NOTE: This function should not be modified, when the callback is needed,
           the HAL_UART_TxCpltCallback could be implemented in the user file
   */
}

重定义回调函数

c 复制代码
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
   if (huart->Instance == USART1)
   {
		...
   }
}

四、DMA发送问题点

在实际测试中,发现第一次发送后进入中断后无法再次发送,且未执行回调函数。

调试发现。

当发送使用HAL_UART_Transmit_DMA发送数据时,状态呗置位了,再次发送不发进入if判断。

解决办法1

调用发送接口后将状态 huart->gState 复位。但是发送数据太长时,数据可能还未传输完成,可能会导致状态不一致。如果HAL_UART_Transmit_DMA调用的频率过快,可能出现冲突,数据错乱。

解决办法2

发送后在发送中断回调函数中复位状态。

新问题,回调函数无法执行,DMA正常模式下,未调用会点函数:


此时需要更改UART_DMATransmitCplt函数或者更改成循环模式。

c 复制代码
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
{
  UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
  /* DMA Normal mode*/
  if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
  {
    huart->TxXferCount = 0x00U;

    /* Disable the DMA transfer for transmit request by setting the DMAT bit
       in the UART CR3 register */
    ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);

    /* Enable the UART Transmit Complete Interrupt */
    ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
	  
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    /*Call registered Tx complete callback*/
    huart->TxCpltCallback(huart);
#else
    /*Call legacy weak Tx complete callback*/
    HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
  }
  /* DMA Circular mode */
  else
  {
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
    /*Call registered Tx complete callback*/
    huart->TxCpltCallback(huart);
#else
    /*Call legacy weak Tx complete callback*/
    HAL_UART_TxCpltCallback(huart);
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
  }
}

参考STM32F4

总结

STM32CUBE给开发提供了很多便利,但是HAL库还是有不少坑在里面,需要我们理解库函数的机制,遇到BUG后去调试优化。

相关推荐
一只川页1 小时前
arduino平台读取鼠标光电传感器
驱动开发·单片机·嵌入式硬件·计算机外设
qq_401700412 小时前
电容触摸按键PCB设计
stm32
爱学习的张哥4 小时前
UDP--DDR--SFP,FPGA实现之模块梳理及AXI读写DDR读写上板测试
单片机·fpga开发·udp·axi·ddr
LaoZhangGong1234 小时前
W5500使用ioLibrary库创建TCP客户端
网络·经验分享·stm32·网络协议·tcp/ip
一月千帆4 小时前
51单片机课设基于GM65模块的二维码加条形码识别
单片机·嵌入式硬件·51单片机
O。o.尊都假都5 小时前
STM32就业前景和下载KEIL软件(保姆级)
stm32·单片机·嵌入式硬件
「QT(C++)开发工程师」6 小时前
STM32 | FreeRTOS 消息队列
stm32·单片机·嵌入式硬件
sword devil9006 小时前
STM32烧录程序正常,但是运行异常
stm32·单片机·嵌入式硬件
YOYO--小天7 小时前
4G和5G模块的使用
linux·嵌入式硬件·5g
百里东风8 小时前
STM32IIC实战-OLED模板
stm32·单片机·嵌入式硬件