You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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完全不同,这是移植最容易忽略的点:

  1. 查STM32U599参考手册的DMA请求映射表,确认ADC1的规则通道DMA请求对应GPDMA1的哪个请求线(比如ADC1 Regular请求是GPDMA1 Request 0)。
  2. 检查CubeMX生成的DMA通道配置,确保通道的Request参数选择了ADC1(而不是其他外设)。如果是手动写代码,要确认GPDMA通道的请求映射寄存器配置正确,比如GPDMA1_C0SCR的REQ字段要设为对应ADC1的请求编号。

你提到“切换DMA通道到port0/port1”,这里的port就是GPDMA的请求端口,必须和ADC的请求线严格匹配,否则DMA收不到ADC的触发信号,自然不会传输。

三、DMA中断触发的必要条件检查

你的DMA中断完全没触发,大概率是中断掩码没开或者状态位没满足:

  1. 检查DMA的Transfer Complete Interrupt(TCIE)是否开启
    HAL_ADC_Start_DMA理论上会自动开启这个位,但可以手动验证GPDMA_C0CR寄存器的TCIE位是否为1。如果没开,DMA传输完成后不会触发中断,GPDMA1_Channel0_IRQHandler自然不会执行。
  2. 确认ADC的DMA请求使能位是否置位
    检查ADC_CR寄存器的DMAEN位,如果这个位没开,ADC不会向DMA发送请求信号,DMA根本不会启动传输。HAL_ADC_Init应该会自动配置,但可以手动补一句:
    __HAL_ADC_ENABLE_DMA(hadc1, ADC_DMA_REGULAR);
    

四、简化配置,单步验证(快速定位问题)

你已经试过单通道转换,建议继续保持极简配置,用调试器一步步验证:

  1. 保留ADC1仅扫描VREFINT,关闭过采样,DMA传输次数设为1。
  2. 启动转换后,先看ADC_DR寄存器是否有正确的VREFINT数据(确认ADC本身在工作)。
  3. GPDMA_C0NDTR寄存器:如果数值从1递减到0,说明DMA已经收到请求并完成传输;如果一直是1,说明DMA没收到ADC的触发信号(请求映射错误)。
  4. 如果NDTR到0了,看GPDMA_C0ISR寄存器TCIF位(传输完成中断标志):
    • 若TCIF置1但没进中断:NVIC配置有问题,检查中断优先级和使能状态。
    • 若TCIF没置1:DMA传输异常,大概率是数据宽度/地址对齐错误。

五、其他需要注意的细节

  1. 不要手动操作ADC_CR的ADEN位和DMA的EN位:HAL库有自己的状态机,手动修改容易导致状态冲突,让HAL_ADC_Start_DMA自动处理即可。
  2. 你的U5 ADC过采样Ratio设为15,而H7是16:这个差异不大,但如果要保持一致可以改成16,避免不必要的变量干扰。
  3. U5的ADC校准函数参数是对的:HAL_ADCEx_Calibration_Start(hadc1, ADC_CALIB_OFFSET_LINEARITY, ADC_SINGLE_ENDED),和H7的校准逻辑不同,这个配置没问题。

按照这个顺序排查,大概率在第一步或第二步就能解决问题,U5的DMA和ADC的适配坑基本就集中在这几个点上!如果还有问题,随时补充调试过程中的寄存器状态,我再帮你分析。

火山引擎 最新活动