[STM32F4] DMA 无法接收 USART3 数据

[复制链接]
778|97
Hitomi22 发表于 2026-6-2 18:15 | 显示全部楼层 |阅读模式
我为 USART 数据接收路径配置 DMA。我已经功实现了发送,正在在处理接收。
DMA 配置是在 HAL_UART_MspInit() 中完成的,代码完全复制自 CubeMX 自动生成的版本,在另一个启用 CubeMX 的工程中运行正常:
else if(huart->Instance==USART3)
{
/* Peripheral clock enable */
__HAL_RCC_USART3_CLK_ENABLE();

__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART3 GPIO Configuration
PD8 ------> USART3_TX
PD9 ------> USART3_RX
*/
GPIO_InitStruct.Pin = XZaber_TX_Pin|XZaber_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

/* USART3 DMA Init */
/* USART3_RX Init */
hdma_usart3_rx.Instance = DMA1_Stream1;
hdma_usart3_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart3_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK)
{
Error_Handler();
}

__HAL_LINKDMA(huart,hdmarx,hdma_usart3_rx);

/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
}
在我不使用 CubeMX 的工程中,初始化时已显式调用:
__HAL_RCC_DMA1_CLK_ENABLE()
同时也调用了以下启动接收函数:
rv = HAL_UART_Receive_DMA(&huart1, OMRxDat, OM20_MEAS_GET_RXLEN);
rv = HAL_UART_Receive_DMA(&huart3, ZabRxDat, sizeof(ZabRxDat));
我用示波器能看到数据确实发回来了,但所有回调函数都不触发。
我检查了 UART_DMAReceiveCplt()、UART_DMARxHalfCplt 和 UART_DMAError()。
如何才能让数据接收时触发回调函数void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)?

公羊子丹 发表于 2026-6-3 08:09 | 显示全部楼层
你配置的是DMA循环模式,满缓存才进完成回调,平时零星收数据只会进半满中断,想要收到就触发回调得改成普通正常模式。
周半梅 发表于 2026-6-3 08:10 | 显示全部楼层
之前踩过一模一样的坑,循环DMA死活不进RxCplt回调,查了大半天忘了两种模式中断规则不一样,白白对着代码反复核对配置。
帛灿灿 发表于 2026-6-3 08:11 | 显示全部楼层
楼主开启DMA1全局中断了吗?只开USART3中断没用,DMA流对应的NVIC中断没打开,就算数据存进内存也没法进入回调函数。
童雨竹 发表于 2026-6-3 08:12 | 显示全部楼层
先临时把DMA_MODE改成NORMAL单次模式测试,发满一整包数据,看能不能触发接收完成回调,以此判断是不是模式选型出错。
万图 发表于 2026-6-3 08:41 | 显示全部楼层
HAL库需要重写weak修饰的回调函数,要是函数名写错或者没放在正确文件里,中断触发后也跳转不到自定义回调代码。
Wordsworth 发表于 2026-6-3 08:43 | 显示全部楼层
F4串口DMA坑超多,USART3的DMA通道很容易记混,之前选错通道,波形有数据但DMA不搬运,排查花了整整一天。
Bblythe 发表于 2026-6-3 08:44 | 显示全部楼层
循环DMA想要实时取数不用等满缓存,可以在半满回调里处理一半数据,这也是HAL官方推荐的环形缓冲区处理方案。
Pulitzer 发表于 2026-6-3 08:45 | 显示全部楼层
你调用Receive_DMA之后,有没有打开USART的DMA接收使能位?部分非Cube工程手动移植容易漏掉寄存器使能步骤。
Uriah 发表于 2026-6-3 08:46 | 显示全部楼层
调试时断点卡在DMA错误回调里,大概率是地址或者位宽配置出错,先查看HAL_DMA_GetState读取DMA运行状态快速定位故障。
Clyde011 发表于 2026-6-3 08:47 | 显示全部楼层
PD8 PD9复用AF7没问题,但手动建工程记得开启GPIOD时钟,IO时钟漏开硬件收不到信号,DMA自然不会产生任何中断。
saservice 发表于 2026-6-3 21:46 | 显示全部楼层
HAL库中的 HAL_UART_RxCpltCallback 是弱定义(weak)函数,需在工程中自定义该函数以覆盖默认实现。
lihuami 发表于 2026-6-3 22:10 | 显示全部楼层
DMA控制器未配置传输完成中断,或NVIC未使能DMA中断。
zerorobert 发表于 2026-6-4 08:07 | 显示全部楼层
使用了 DMA,就需要开启 DMA 的中断来通知 单片机 接收完成。在 HAL 库中,这是完全错误的。
kkzz 发表于 2026-6-5 12:01 | 显示全部楼层
DMA 中断或 UART 中断没挂到 HAL 的中断链路上,或者 Circular DMA ***不会“完成”。
bartonalfred 发表于 2026-6-5 14:50 | 显示全部楼层
DMA 在搬数据 ≠ 会触发 UART 回调。
olivem55arlowe 发表于 2026-6-5 21:16 | 显示全部楼层
DMA 中断未配置或未使能。              
mollylawrence 发表于 2026-6-5 22:40 | 显示全部楼层
补上 DMA 的中断使能和中断服务函数
averyleigh 发表于 2026-6-6 11:23 | 显示全部楼层
接收数据后如何触发回调函数?              
plsbackup 发表于 2026-6-6 12:12 | 显示全部楼层
DMA传输完成中断需高于其他普通外设中断,避免因优先级过低导致延迟
您需要登录后才可以回帖 登录 | 注册

本版积分规则

203

主题

206

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部
0