STM32U599 移植H753 ADC+DMA代码后数据传输异常,DMA中断未触发求助
STM32U599 移植H753 ADC+DMA代码后数据传输异常,DMA中断未触发求助
兄弟,我之前移植STM32U5的时候也踩过不少ADC+DMA的坑,结合你描述的现象和代码细节,我帮你梳理几个核心排查方向,应该能快速定位问题:
一、先抓最可能的根因:DMA数据宽度与目标数组不匹配
你提到看到论坛说U5的DMA要求32位目标数组,但我看你当前代码里的reg_scan_data还是uint16_t类型!这绝对是高危点:
- U5的GPDMA对传输数据宽度和地址对齐要求很严格,如果ADC配置的是32位数据输出(哪怕是12位有效数据,U5的ADC_DR也是32位寄存器),DMA传输宽度设为32位时,目标数组必须是
uint32_t,否则会出现地址对齐错误或者传输逻辑不匹配,直接导致DMA不触发传输/中断。
立刻修正的代码点:
// 把adc.c里的adc_scan结构体中的数组类型改成uint32_t struct adc_scan { ADC_HandleTypeDef *hadc; uint32_t reg_scan_data[ADC_SCAN_ARRAY_SIZE]; // 替换原uint16_t int8_t reg_scan_data_size; int8_t is_scan_idle; int8_t is_scan_done; adc_scan_callback update_analog_measurements; uint32_t scan_counter; }; // 同时修改start_adc_regular_conversion_sequence里的HAL_ADC_Start_DMA调用,去掉强制转换 static void start_adc_regular_conversion_sequence(struct adc_scan * const scan) { scan->is_scan_done = 0; scan->is_scan_idle = 0; HAL_ADC_Start_DMA( scan->hadc, scan->reg_scan_data, // 直接传uint32_t*,无需强制转换 scan->reg_scan_data_size ); }
同时在CubeMX的IOC配置里,把ADC对应的DMA通道的外设数据宽度和内存数据宽度都设为Word(32bits),保持和数组类型一致。
二、ADC与DMA的请求映射是否正确
U5的GPDMA请求映射和H7完全不同,这是移植最容易忽略的点:
- 查STM32U599参考手册的DMA请求映射表,确认ADC1的规则通道DMA请求对应GPDMA1的哪个请求线(比如ADC1 Regular请求是GPDMA1 Request 0)。
- 检查CubeMX生成的DMA通道配置,确保通道的
Request参数选择了ADC1(而不是其他外设)。如果是手动写代码,要确认GPDMA通道的请求映射寄存器配置正确,比如GPDMA1_C0SCR的REQ字段要设为对应ADC1的请求编号。
你提到“切换DMA通道到port0/port1”,这里的port就是GPDMA的请求端口,必须和ADC的请求线严格匹配,否则DMA收不到ADC的触发信号,自然不会传输。
三、DMA中断触发的必要条件检查
你的DMA中断完全没触发,大概率是中断掩码没开或者状态位没满足:
- 检查DMA的Transfer Complete Interrupt(TCIE)是否开启:
HAL_ADC_Start_DMA理论上会自动开启这个位,但可以手动验证GPDMA_C0CR寄存器的TCIE位是否为1。如果没开,DMA传输完成后不会触发中断,GPDMA1_Channel0_IRQHandler自然不会执行。 - 确认ADC的DMA请求使能位是否置位:
检查ADC_CR寄存器的DMAEN位,如果这个位没开,ADC不会向DMA发送请求信号,DMA根本不会启动传输。HAL_ADC_Init应该会自动配置,但可以手动补一句:__HAL_ADC_ENABLE_DMA(hadc1, ADC_DMA_REGULAR);
四、简化配置,单步验证(快速定位问题)
你已经试过单通道转换,建议继续保持极简配置,用调试器一步步验证:
- 保留ADC1仅扫描VREFINT,关闭过采样,DMA传输次数设为1。
- 启动转换后,先看ADC_DR寄存器是否有正确的VREFINT数据(确认ADC本身在工作)。
- 看GPDMA_C0NDTR寄存器:如果数值从1递减到0,说明DMA已经收到请求并完成传输;如果一直是1,说明DMA没收到ADC的触发信号(请求映射错误)。
- 如果NDTR到0了,看GPDMA_C0ISR寄存器的
TCIF位(传输完成中断标志):- 若TCIF置1但没进中断:NVIC配置有问题,检查中断优先级和使能状态。
- 若TCIF没置1:DMA传输异常,大概率是数据宽度/地址对齐错误。
五、其他需要注意的细节
- 不要手动操作ADC_CR的
ADEN位和DMA的EN位:HAL库有自己的状态机,手动修改容易导致状态冲突,让HAL_ADC_Start_DMA自动处理即可。 - 你的U5 ADC过采样Ratio设为15,而H7是16:这个差异不大,但如果要保持一致可以改成16,避免不必要的变量干扰。
- U5的ADC校准函数参数是对的:
HAL_ADCEx_Calibration_Start(hadc1, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED),和H7的校准逻辑不同,这个配置没问题。
按照这个顺序排查,大概率在第一步或第二步就能解决问题,U5的DMA和ADC的适配坑基本就集中在这几个点上!如果还有问题,随时补充调试过程中的寄存器状态,我再帮你分析。




