[STM32H7] STM32H7的HPDMA搭配ADC连续采样,为什么一开循环模式就卡死

[复制链接]
7|0
classroom 发表于 2026-9-2 20:05 | 显示全部楼层 |阅读模式
最近在Nucleo-H7S3L8开发板上调试HPDMA配合ADC采集,遇到一个让人挠头的问题。把ADC配成连续转换模式,DMA也选了循环模式,结果程序直接卡在HAL_ADC_Start_DMA这一行出不来了。更奇怪的是,关了循环模式就能正常工作,但采样跑一次就停,完全没法用。

翻了一堆资料才明白,STM32H7系列的HPDMA和传统GPDMA在循环模式的实现上根本不是一回事。有个关键信息藏在官方文档里,DMA的传统循环传输方式,已经被循环链表配置取代了。也就是说,你直接在DMA句柄里设个循环模式位就指望它无限跑,硬件根本不认这个配置。

先看一组典型的配置代码,很多人都是这么写的

c
DmaHandle.Init.Mode = DMA_CIRCULAR;  // 直接开循环模式
DmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
if (HAL_DMA_Init(&DmaHandle) != HAL_OK) {
    // 初始化可能成功,但跑起来就卡
}
这代码在GPDMA上可能没问题,但HPDMA需要额外配置链表才能实现循环。你想实现无限循环,得用HAL_DMAEx_List_SetCircularMode函数把链表头尾接起来,或者用HAL_DMAEx_List_SetCircularModeConfig指定从哪个节点开始循环。直接在Init结构体里开循环标志,底层根本识别不了,卡死是必然的。

ADC这边还有一个隐藏坑,ConversionDataManagement这个参数配错了也会导致卡死。ADC_CFGR寄存器里的DMNGT位控制数据管理模式,要使用DMA循环模式,必须把这项设成ADC_CONVERSIONDATA_DMA_CIRCULAR。如果设成了普通DMA模式或者DR寄存器模式,ADC的DMA请求生成逻辑和DMA的循环配置对不上,传输就卡住了。

另外一个容易忽略的问题是ADC溢出处理。H7的ADC在连续转换模式下,如果DMA没来得及把数据搬走,ADC的DR寄存器会被新数据覆盖,此时会置起OVR标志位。关键点是一旦OVR标志置位,DMA传输请求会被硬件直接阻塞,直到软件把OVR位清掉才能恢复。如果DMA中断处理不及时或者中断优先级太低,OVR标志一直挂着,DMA就***停在那里。

还有内存地址选择的问题。H7的DMA1和DMA2无法访问TCM内存区,把ADC缓存放在DTCM或者ITCM里,DMA根本搬不了数据,表面看就是卡住了。AXI SRAM(地址0x24000000开始)是通用DMA可以正常访问的区域,优先把缓冲区放在那里。

如果你用的是HPDMA而不是通用DMA,还得确认AHB端口选择是否正确。官方有明确提示,当HPDMA配合ADC1或ADC2使用时,外设侧的AHB端口必须选择端口1。端口配错了,总线握手***不成功,HAL_ADC_Start_DMA也就一直等在那里。

遇到卡死问题,第一步是查ADC状态寄存器里的OVR位,如果有溢出先处理溢出逻辑。第二步检查ConversionDataManagement是不是设成了循环模式,第三步确认DMA句柄是否通过__HAL_LINKDMA正确关联到了ADC句柄。这三项都对了,再考虑链表配置的问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

743

主题

5973

帖子

2

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