【嵌入式外设精学】Day16|ADC:分辨率、采样时间、平均滤波
今天解决:读数抖、通道串扰、静态值偏,分别怎么处理?
目录
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. 自测
6. 答案
作者:shuifanyu 标签:ADC 采样 滤波



