You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32 ADC轮询模式读取值不稳定问题咨询

ADC采样读数持续下降问题排查与咨询

问题背景

采用轮询模式读取5个ADC通道,每个通道采集10个样本并计算平均值。发现样本数组存在重复性极强的不稳定现象:初始读数数值较高,之后逐渐降低至最后一个样本。

为调试,已将ADC通道连接的传感器替换为固定电阻以获取固定读数。ADC自校准在首次通道读取前执行,每30秒重复一次校准与5次读取操作。

原始采样数据

首次读数1855,末次读数1850

【原始输出值】
ui32_RawTemp[0]: 1855
ui32_RawTemp[1]: 1855
ui32_RawTemp[2]: 1854
ui32_RawTemp[3]: 1852
ui32_RawTemp[4]: 1852
ui32_RawTemp[5]: 1852
ui32_RawTemp[6]: 1851
ui32_RawTemp[7]: 1851
ui32_RawTemp[8]: 1850
ui32_RawTemp[9]: 1850

原始代码片段(单通道,已移除HAL错误处理)

#define AVG_NUMBER 10
sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
    sConfig.Offset = 0;

    // 读取通道5上的TEMP1_ADC
    sConfig.Channel = ADC_CHANNEL_5;

    ADC_HAL_ErrCode = HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    if(ADC_HAL_ErrCode != HAL_OK) {
        ......
    }

    ui32_Temp = 0;
    for(ui8_AVGCounter=0; ui8_AVGCounter < AVG_NUMBER; ui8_AVGCounter++) {
        HAL_ADC_Start(&hadc1);
        HAL_ADC_PollForConversion(&hadc1, 10);
        ui16_RawTemp[ui8_AVGCounter] = HAL_ADC_GetValue(&hadc1);  // 读取ADC寄存器
        ui32_Temp = ui32_Temp + (uint32_t)ui16_RawTemp[ui8_AVGCounter]; // 累加所有读取值

        ui16_avgADC[0] = (uint16_t)(ui32_Temp / AVG_NUMBER);    // 计算平均值

        HAL_ADC_Stop(&hadc1);
    }

优化后情况

在循环中添加vTaskDelay(1)后读数大幅稳定,但1ms延迟时长过大。

优化后代码片段

// 读取通道5上的TEMP1_ADC
    sConfig.Channel = ADC_CHANNEL_5;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
    sConfig.SingleDiff = ADC_SINGLE_ENDED;
    sConfig.OffsetNumber = ADC_OFFSET_NONE;
    sConfig.Offset = 0;

    ADC_HAL_ErrCode = HAL_ADC_ConfigChannel(&hadc1, &sConfig);
    if(ADC_HAL_ErrCode != HAL_OK) {
        .....
    }

    ui32_Temp = 0;
    for(ui8_AVGCounter=0; ui8_AVGCounter < AVG_NUMBER; ui8_AVGCounter++) {
        HAL_ADC_Start(&hadc1);
        HAL_ADC_PollForConversion(&hadc1, 10);
        ui32_RawTemp[ui8_AVGCounter] = HAL_ADC_GetValue(&hadc1);    // 读取ADC寄存器
        HAL_ADC_Stop(&hadc1);

        ui32_Temp = ui32_Temp + ui32_RawTemp[ui8_AVGCounter];   // 累加所有读取值

        vTaskDelay(1);
    }
    ui16_avgADC[0] = (uint16_t)((ui32_Temp + (0.5 * AVG_NUMBER)) / AVG_NUMBER); // 四舍五入并计算平均值

优化后采样数据

【新输出值】
ui32_RawTemp[0]: 1855
ui32_RawTemp[1]: 1855
ui32_RawTemp[2]: 1855
ui32_RawTemp[3]: 1855
ui32_RawTemp[4]: 1855
ui32_RawTemp[5]: 1855
ui32_RawTemp[6]: 1855
ui32_RawTemp[7]: 1855
ui32_RawTemp[8]: 1856
ui32_RawTemp[9]: 1855

咨询问题

  1. 该现象的原因是什么?
  2. 我的代码是否存在问题?
  3. 首次读数最不稳定,首次ADC转换前需执行什么操作?

解答

1. 现象原因

核心是ADC内部或外围采样电路的热漂移问题:

  • 刚启动ADC时,采样保持电容、内部放大器等器件处于冷态,连续采样产生的功耗会让器件升温,改变其电气特性(如电容值、放大器增益偏移),导致采样值逐渐漂移,直到器件温度稳定后读数才趋于一致。
  • 固定电阻测试仍有此现象,排除了传感器本身的问题,进一步指向ADC自身或外围采样电路的热稳定特性。延迟后稳定,是因为给了电路足够时间达到热平衡。

2. 代码存在的问题

  • 平均值计算时机错误:原始代码在循环内部每次累加后就计算平均值,属于无效操作,平均值应在所有样本采集完成后统一计算,既节省资源也避免逻辑混乱。
  • ADC启停逻辑冗余:每次采样都调用HAL_ADC_Start()和HAL_ADC_Stop(),频繁启停会导致ADC内部电路反复初始化,加剧热波动和不稳定。可改为一次启动ADC,完成所有采样后再停止。
  • 采样间隔无合理控制:原始代码采样间隔极短,电路没有足够恢复时间,连续采样的热积累会加速漂移。

3. 首次ADC转换前的必要操作

  • 执行预采样预热:正式采样前连续进行5-10次无效采样,让ADC内部电路达到热稳定,丢弃这些预热样本后再开始正式采样。
  • 校准后等待稳定:自校准完成后,不要立即采样,根据芯片手册推荐等待几十到几百微秒,让校准后的电路参数稳定。
  • 优化供电稳定性:确保外部采样电路的供电滤波电容足够,避免启动时的电压波动影响采样;必要时可在首次采样前给采样电路预上电一段时间。

内容的提问来源于stack exchange,提问作者IGtti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:35:26