欢迎光临
我们一直在努力

【嵌入式外设精学】Day16|ADC:分辨率、采样时间、平均滤波

【嵌入式外设精学】Day16|ADC:分辨率、采样时间、平均滤波

今天解决:读数抖、通道串扰、静态值偏,分别怎么处理?


目录

  • 问题 2. 原理 3. 代码 4. 误区 5. 自测 6. 答案

  • 1. 问题

    • 同一电压码字乱跳
    • 多通道轮流读时互相影响

    2. 原理

    2.1 分辨率

    12bit 表示把参考电压分成约 4096 档。 档数不等于“一点不抖”:噪声、参考电压不稳都会让码字跳。

    2.2 采样时间

    ADC 内部先给一个采样电容充电再转换。 信号源内阻大、采样时间太短 → 电容没充够 → 读数偏、通道之间“残留”上一通道的电压。

    多通道轮流扫时,更要把采样时间留够。

    2.3 平均滤波

    多次采样求平均,能压噪声,但会变“钝”(有滞后)。 现场常用“连续 N 次平均”或“滑动平均”。

    2.4 电压换算

    12bit、参考 3.3V 时,一码约 3.3/4095 ≈ 0.8mV。 以实际参考电压和校准为准。


    3. 代码示例

    #include "stm32f4xx.h"
    #include <stdint.h>

    uint16_t adc_read_once(uint8_t channel)
    {
    ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_84Cycles);
    ADC_SoftwareStartConv(ADC1);
    while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET) {
    }
    return ADC_GetConversionValue(ADC1);
    }

    uint16_t adc_read_avg(uint8_t channel, int n)
    {
    uint32_t s = 0;
    int i;
    for (i = 0; i < n; i++) {
    s += adc_read_once(channel);
    }
    return (uint16_t)(s / (uint32_t)n);
    }

    float adc_to_volt(uint16_t x, float vref)
    {
    return (float)x * vref / 4095.0f;
    }

    滑动平均(1ms 调一次,窗口 8):

    static uint16_t hist[8];
    static uint8_t idx;
    static uint32_t sum;

    uint16_t adc_slide_push(uint16_t x)
    {
    sum = sum – hist[idx] + x;
    hist[idx] = x;
    idx = (uint8_t)((idx + 1u) & 7u);
    return (uint16_t)(sum >> 3);
    }


    4. 常见误区

    误区正解
    12bit 就是绝对准 有噪声和误差,看有效位
    采样时间越短越好 源阻抗大时会测不准
    平均点数无限大 滞后变大,动态信号失真
    不必看参考电压 换算必须用真实 Vref

    5. 自测

  • 12bit,码 2048,Vref=3.0V,电压约?
  • 多通道串扰,优先改什么?

  • 6. 答案

  • 约 1.5V。
  • 加长该通道采样时间,或通道间加缓冲/延时,硬件上降低源阻抗。

  • 作者:shuifanyu 标签:ADC 采样 滤波

    赞(0)
    未经允许不得转载:171主机测评 » 【嵌入式外设精学】Day16|ADC:分辨率、采样时间、平均滤波
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址