在 STM32H7 系列芯片开发中,ADC 配合 DMA 传输数据是高频场景,但不少工程师遇到棘手问题:查询模式读取 ADC 数据正常,启用 DMA 后数据完全不搬运,或调试窗口显示全 0、数据错乱。看似 DMA 配置无误,实则是 H7 总线架构、内存分区与缓存特性导致的典型坑点。本文基于意法半导体 LAT1650 官方案例,拆解异常根源,给出可直接复用的解决方案,帮开发者快速排查。
资料获取:经验分享 | LAT1650 STM32H7系列ADC DMA传输异常案例分析
1. 异常典型现象
STM32H743 等芯片使用 ADC+DMA 组合时,出现两类高频异常:
- DMA 完全失效:ADC 转换完成后,DMA 无数据搬运,缓存区始终为空;
- 调试显示异常:DMA 能搬运数据,但 KEIL 等 IDE 实时窗口显示全 0、数据错乱,仅查询模式正常。
排除 ADC 硬件、时钟配置问题后,异常集中在DMA 选型、内存分配、缓存一致性三大关键环节。
2. 三大核心异常根源
根源一:DMA 类型选错(BDMA 误用)
STM32H7 有DMA1/DMA2(通用 DMA)与BDMA(备份域 DMA)两类控制器,功能与访问范围差异极大:
- DMA1/DMA2:可访问 AXI SRAM、SRAM1/2/3 等常用内存,适配 ADC、SPI 等外设;
- BDMA:仅能访问 SRAM4、Backup RAM,无法访问 ADC 常用的 AXI SRAM。
很多开发者在 CubeMX 中误选 BDMA 作为 ADC 的 DMA 控制器,导致数据无法写入缓存,直接传输失败。
根源二:内存分区分配错误(误用 TCM)
STM32H7 内存分为TCM(ITCM/DTCM)、AXI SRAM、SRAM1-4,其中TCM 区域(0x20000000-0x2001FFFF)DMA1/2 无法访问。
若将 ADC 数据缓存定义在 DTCM/ITCM 中,DMA 无法完成数据搬运,这是新手高频踩坑点。
根源三:DCache 一致性冲突
AXI SRAM、SRAM1/2/3 默认开启数据缓存(DCache),采用回写策略:
导致调试窗口显示旧数据或全 0,实际 DMA 已正常搬运,仅缓存一致性异常。
3. 分步落地解决方案
3.1 修正 DMA 选型:禁用 BD,改用 DMA1/DMA
CubeMX 配置步骤:
- 进入 ADC→DMA Settings;
- 删除 BDMA 通道,重新选择DMA1 或 DMA2通道;
- 配置传输模式(Normal/Circular)、数据宽度,与 ADC 转换模式匹配;
- 重新生成代码,确保 DMA 控制器正确绑定。
3.2 正确分配 ADC 缓存内存
避开 TCM 区域,将缓存定义在AXI SRAM(0x24000000+)、SRAM1/2/3:
// 正确:AXI SRAM区域(可被DMA1/2访问)
uint16_t Adc_Buffer[9] __attribute__((section(".bss.axi_ram")));
// 错误:DTCM区域(DMA无法访问)
// uint16_t Adc_Buffer[9] __attribute__((section(".dtcm_ram")));
3.3 解决 DCache 一致性:DMA 完成后缓存失效
在 DMA 传输完成中断中,执行DCache 行失效,强制 CPU 读取最新物理内存数据:
// ADC DMA传输完成回调函数
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
// 缓存失效:地址+长度匹配ADC缓存
SCB_InvalidateDCache_by_Addr((uint32_t*)Adc_Buffer, sizeof(Adc_Buffer));
}
添加后,调试窗口可实时显示正确 ADC 数据,循环模式下也不会出现 0 值错乱。
4. 关键避坑要点
- DMA 选型必核对:ADC、SPI 等外设优先选 DMA1/DMA2,BDMA 仅用于备份域低速外设;
- 内存分区记牢:TCM(0x2000 开头)禁止分配 DMA 缓存,优先 AXI SRAM;
- 缓存维护不可少:开启 DCache 的内存区域,DMA 完成后必须执行失效操作;
- 循环模式适配:DMA 循环传输长度建议与 ADC 通道数匹配,避免末尾数据异常。
STM32H7 ADC DMA 传输异常,本质是总线架构差异、内存分区限制、缓存特性三大 H7 专属问题,而非硬件故障。开发者只需牢记:禁用 BDMA、避开 TCM、DMA 完成后维护缓存三大核心原则,按 CubeMX 配置 + 缓存失效代码复用,即可快速解决异常,让 ADC DMA 稳定传输。
221