☰
ADC采样原理、取平均与精度:从噪声跳动到稳定采集的工程实践
2026/10/14 1:22:38 网站建设 项目流程

1. 从一个“读数总在跳”的现场说起

如果你玩过单片机、做过数据采集,或者调过任何一款传感器的驱动,大概率都遇到过这样的场景:明明输入电压是稳的,ADC读出来的值却在最后两三位上蹦来蹦去,像一只按不住的弹簧。你盯着串口助手上刷屏的数字,心里想的是“这玩意儿到底准不准”。更让人头疼的是,换一块板子、换一个通道、甚至只是把采样率调高一点,跳动幅度就变了。这时候如果有人说“取个平均就好了”,你试了之后发现——有时候确实稳了,有时候反而更糟,甚至引入了新的偏差。

ADC转换这件事,表面上看只是“把模拟量变成数字量”,但真正落到工程里,它牵扯到采样保持、量化误差、参考电压、输入阻抗、噪声抑制、数字滤波、校准补偿等一整套东西。标题里提到的“采样原理、取平均、精度”恰好是这条链路上最容易被忽视、又最影响最终结果的三块。采样原理决定了你能不能采到“真实”的瞬时值;取平均决定了你如何处理噪声和随机误差;精度则是一个从器件到系统、从硬件到算法的综合指标,而不是数据手册上那个孤零零的位数。

这篇内容适合谁看?如果你正在用ADC做电压、电流、温度、压力、称重等信号的采集,不管你是刚入门的新手,还是已经能写出驱动但总觉得“数据不够漂亮”的老手,这里面的思路和实操细节都能直接拿去用。我会从采样原理讲起,把取平均的几种做法拆开对比,再落到精度这个综合话题上,中间穿插参数计算、代码示例和踩坑记录。不堆公式,但关键的地方会把账算清楚。

2. 采样原理:ADC到底在什么时候“看一眼”

2.1 采样保持与孔径时间:为什么你采到的不是瞬时值

很多人以为ADC转换就是“此刻的电压被读走了”,但实际芯片内部有一个采样保持电路。在采样阶段,内部采样电容通过输入阻抗和开关电阻充电,跟踪输入电压;在保持阶段,开关断开,电容上的电压被送到比较器阵列去量化。这个“跟踪”需要时间,这个时间就是采样时间。如果采样时间不够,电容还没充到输入电压的真实值,转换结果就会偏低或偏高,而且这个误差和输入阻抗、源阻抗直接相关。

举个具体的账:假设某款ADC的采样电容是4pF,内部采样开关等效电阻是1kΩ,那么时间常数τ = R×C = 4ns。要充到0.5LSB以内,对于12位ADC,需要大约8.3个τ,也就是约33ns。这看起来很短,但如果你在输入端串了一个10kΩ的电阻做分压或限流,源阻抗直接变成11kΩ,τ就变成44ns,需要的采样时间就跳到约365ns。很多新手在分压电路上用大电阻,然后抱怨“ADC读数偏低”,根源就在这里。数据手册里的采样时间参数,通常是在源阻抗小于某个值(比如1kΩ或2.5kΩ)的条件下给出的,超过这个值必须自己重新计算。

注意:采样时间不足导致的误差是“系统性”的,不是随机噪声。它不会因为取平均而消失,反而会在不同通道间串扰时表现得更明显。

2.2 奈奎斯特与混叠:采样率不是随便定的

采样定理说采样率要大于信号最高频率的两倍,但工程里真正要关心的不是“能不能恢复”,而是“混叠进来的东西会不会毁掉你的测量”。假设你用一个1kHz的采样率去采一个50Hz的工频信号,看起来绰绰有余。但如果信号上叠加了1.2kHz的开关噪声,这个噪声会被混叠到200Hz的位置(1.2k - 1k = 200Hz),而你的有用信号在50Hz,200Hz的干扰就会落在你的通带里,取平均也去不掉,因为它已经变成了“低频信号”。

实际做法通常是在ADC前面加一个抗混叠滤波器,截止频率设在采样率的1/2以下,最好留出足够的过渡带。对于低速高精度的场景,比如称重传感器,信号带宽可能只有几Hz到几十Hz,这时候用一个简单的RC低通就能把高频噪声挡在外面。但RC的参数要算:截止频率fc = 1/(2πRC)。如果你用1kΩ和1μF,fc约159Hz,对于100Hz采样率来说,这个滤波器在50Hz处的衰减还不够,可能需要两级RC或者用有源滤波。

另一个容易被忽略的点是:很多Σ-Δ型ADC内部有数字滤波器,它的采样率和输出速率不是一回事。你配置的输出速率是10SPS,但内部调制器可能跑在几十kHz,这时候抗混叠滤波器的要求就宽松很多,因为数字滤波器已经帮你做了大量抑制。所以选型时要看清楚ADC的类型,SAR型和Σ-Δ型在抗混叠策略上完全不同。

2.3 参考电压与输入范围:精度从源头就被决定了

ADC的输出码值本质上是输入电压与参考电压的比值。对于N位ADC,理想情况下:

码值 = round( Vin / Vref × 2^N )

这个公式里,Vref的精度和稳定性直接乘到结果上。如果你用MCU的电源电压作为参考,而电源本身有±5%的波动,那么你的测量精度不可能优于±5%,哪怕ADC是16位的。很多新手用USB供电的板子测电压,发现白天和晚上的读数不一样,原因就是电源电压在变。

正确的做法是:对于精度要求高于1%的场景,必须用独立基准源。常见的基准有2.5V、3.0V、4.096V、5.0V等,选哪个取决于你的信号范围。比如你的信号最大是2.0V,那就选2.5V基准,这样能用到80%的量程;如果选5.0V基准,只用到40%量程,相当于浪费了1位多的分辨率。基准源的初始精度、温漂、长期漂移都要看,普通齐纳基准温漂可能几十ppm/°C,而带隙基准能做到几个ppm/°C,价格差好几倍,但对你最终精度的影响是决定性的。

还有一个细节:基准源的输出阻抗和去耦。基准输出端必须就近放一个低ESR的电容,通常数据手册会推荐1μF到10μF,这个电容不是“可选”的,它负责在ADC转换瞬间提供电荷,否则基准电压会被拉低,导致转换结果偏高。我见过一个案例,某工程师把基准电容省了,结果ADC读数在转换时会跳几十个码值,加上电容后立刻稳定。

3. 取平均:不是所有平均都叫“滤波”

3.1 算术平均:最简单,但有两个前提

算术平均就是把N次采样值加起来除以N。它的效果是:如果噪声是零均值的随机噪声,平均后噪声标准差降到原来的1/√N。也就是说,采16次平均,噪声降到1/4;采256次平均,噪声降到1/16。这个关系在噪声确实是随机且不相关的时候成立。

但有两个前提经常被忽略。第一,信号在平均窗口内不能有变化。如果你在测一个缓慢变化的温度,采256次平均花了256ms,这期间温度变了0.1°C,那平均结果就滞后了,而且会把变化“抹平”。第二,噪声必须是零均值的。如果噪声里包含一个固定的偏移,比如50Hz工频干扰,而你的采样率恰好是50Hz的整数倍,那么每次采到的工频相位相同,平均后干扰不但不减小,反而会固定成一个直流偏移。这就是为什么很多人在工频环境下取平均,发现读数稳定地偏了某个值。

实操中,算术平均适合信号带宽远低于采样率、且噪声以白噪声为主的场景。比如你用一个1kSPS的ADC采一个称重传感器的信号,信号带宽只有10Hz,那取64次平均,等效输出速率约15.6SPS,噪声能降到1/8,效果很明显。

3.2 滑动平均与中值平均:什么时候该换方法

滑动平均(也叫移动平均)是每次新采样进来,丢掉最老的一个,保持窗口长度不变。它的好处是输出速率和采样率一样,但每个输出都是最近N个值的平均。代价是它对突变响应慢,而且计算量比块平均大。在嵌入式里,如果RAM够,用一个环形缓冲区就能实现,开销很小。

中值平均则是先取N个值,排序后取中间那个,或者去掉最大最小再平均。它对脉冲噪声特别有效。比如你的ADC偶尔因为外部继电器动作跳出一个离谱的值,算术平均会被这个值拉偏,但中值滤波能直接把它剔除。常见做法是“去极值平均”:采N个值,去掉最大和最小的各一个或两个,剩下的取平均。N通常取5、7、9这样的奇数,方便排序取中。

我个人的经验是:如果噪声是高斯白噪声,算术平均或滑动平均就够了;如果噪声里明显有尖峰,比如电机启停、继电器切换时出现的跳变,那就必须上中值或去极值。你可以先采一段原始数据,用串口画个波形,看看噪声的形态,再决定用哪种。盲目上中值滤波,在噪声本身很干净的时候反而会引入额外的计算延迟和轻微的偏差。

3.3 过采样与抽取:用速度换精度的经典操作

过采样是取平均的一个特例,但它的理论更漂亮。如果你对一个信号以远高于奈奎斯特的频率采样,然后做平均和抽取,每提高4倍采样率,等效分辨率提高1位。这是因为量化噪声在频域上被摊薄了,平均相当于一个低通滤波器,把带外噪声滤掉。

具体操作:假设你需要12位有效精度,但手头只有10位ADC,采样率可以跑到200kSPS,而你的信号带宽只有100Hz。那么你可以以200kSPS采样,每4096个点平均一次,输出速率约48.8SPS。理论上分辨率提升log4(4096) = 6位,也就是10+6=16位。当然实际受限于ADC的线性度和噪声底,不可能无限提升,但提升2到4位是可行的。

这里的关键是:过采样必须配合“抖动”或“噪声”才能打散量化误差。如果输入信号恰好落在两个码值中间,且没有噪声,那么每次转换结果都一样,平均也不会增加信息。实际ADC本身有热噪声,通常就够用了。如果不够,可以在输入端故意注入一点白噪声,幅度约1LSB,这叫“抖动注入”,能显著改善小信号的分辨率。

提示:过采样提升的是“分辨率”或“有效位数”,不是“精度”。如果ADC本身有增益误差或偏移误差,过采样不会修正这些,必须靠校准。

4. 精度:从器件到系统的完整账本

4.1 分辨率不等于精度:一个被用烂的误区

12位ADC的分辨率是1/4096,约0.024%满量程。但它的精度可能只有±2LSB,也就是±0.049%满量程,再加上偏移、增益、温漂,实际精度可能差一个数量级。分辨率是“能分辨的最小变化”,精度是“离真实值有多近”。一个12位ADC可以分辨0.024%的变化,但如果你不知道它的偏移是+5LSB,那这个分辨率对绝对测量没有意义。

算一笔完整的账:假设某12位ADC,Vref=4.096V,那么1LSB=1mV。数据手册给出:偏移误差±3LSB,增益误差±5LSB,INL±2LSB,温漂10ppm/°C。在25°C时,最坏情况误差约±10LSB=±10mV。如果你测一个1V的信号,相对误差1%;如果测100mV,相对误差10%。所以小信号测量必须做校准,否则精度惨不忍睹。

校准分两步:偏移校准和增益校准。偏移校准通常短接输入到地,读一组值取平均,得到偏移码值,后续测量减去这个值。增益校准需要加一个已知的精确参考电压,比如用基准源输出2.000V,读一组值,算出实际增益系数,后续测量乘以这个系数。这两步做完,精度能提升到接近INL的水平。

4.2 噪声、有效位数与信噪比:怎么读懂数据手册

数据手册里的ENOB(有效位数)和SNR(信噪比)是衡量ADC动态性能的核心指标。ENOB = (SNR - 1.76) / 6.02。比如SNR=72dB,ENOB≈11.7位。这意味着虽然ADC标称12位,但在交流信号下实际有效精度只有11.7位。对于直流测量,更关心的是“峰峰值噪声”或“RMS噪声”,通常用“无噪声码”来表示。比如某24位Σ-Δ ADC在10SPS时无噪声码是21.5位,意思是读数最后2.5位是跳动的,你可以稳定读到21位。

选型时不要只看位数。一个16位SAR ADC在1MSPS时的噪声可能比一个24位Σ-Δ在10SPS时大得多。关键是看你的信号带宽和所需分辨率。低速高精度选Σ-Δ,高速中精度选SAR,这是基本盘。

4.3 PCB布局与接地:精度的一半在板子上

即使你用了高精度基准和24位ADC,如果PCB布局不对,精度照样上不去。几个铁律:

  • 模拟地和数字地分开,单点连接。连接点通常选在ADC芯片下方或基准源下方。
  • 基准源的去耦电容必须紧贴基准输出引脚和地引脚,回路面积越小越好。
  • 模拟输入走线远离数字信号线,尤其是时钟线和PWM线。如果必须交叉,尽量垂直交叉。
  • 输入端的RC滤波器电阻不要太大,否则影响采样保持,但电容要选低泄漏的,比如C0G或薄膜电容,不要用X7R。
  • 电源去耦:每个电源引脚都要有100nF陶瓷电容,再并一个1μF到10μF的钽电容或陶瓷电容。

我踩过的一个坑:某次用24位ADC测热电偶,读数一直有规律地跳动,频率约50Hz。查了半天发现是ADC的模拟输入走线从一颗DC-DC电感旁边经过,耦合了开关噪声。把走线绕开并加了一个简单的RC滤波后,跳动从几十个码值降到几个码值。所以布局不是玄学,是实打实的精度保障。

5. 实操:从零搭建一个稳定的ADC采集流程

5.1 硬件最小系统与参数计算

假设我们要用一款12位SAR ADC,Vref=4.096V,采样率10kSPS,测一个0到3.3V的信号。信号源内阻约100Ω,需要加抗混叠滤波。

第一步,确定采样时间。查数据手册,采样电容3pF,内部开关电阻800Ω。源阻抗100Ω,总阻抗900Ω,τ=2.7ns。12位需要8.3τ≈22.4ns。ADC的采样时间配置为1μs,远远足够。

第二步,抗混叠滤波。信号带宽假设1kHz,采样率10kSPS,奈奎斯特频率5kHz。为了在5kHz处有足够衰减,用一阶RC,截止频率设为2kHz。R取1kΩ,C=1/(2π×2000×1000)≈80nF,取标准值82nF。但注意,这个R会加到源阻抗上,总阻抗变成1.1kΩ,τ=3.3ns,采样时间仍然够。

第三步,基准去耦。基准输出加1μF陶瓷电容+100nF,紧贴引脚。

第四步,电源。模拟电源用LDO单独供电,数字电源用另一路,地在ADC下方单点连接。

5.2 固件中的采样与滤波代码

以下是一个基于环形缓冲区的滑动平均+去极值示例,用C语言写,适合嵌入式:

#define WINDOW_SIZE 9 static uint16_t adc_buf[WINDOW_SIZE]; static uint8_t idx = 0; static uint8_t count = 0; uint16_t adc_read_filtered(void) { uint16_t raw = adc_read_raw(); adc_buf[idx] = raw; idx = (idx + 1) % WINDOW_SIZE; if (count < WINDOW_SIZE) count++; // 复制到临时数组排序 uint16_t tmp[WINDOW_SIZE]; for (uint8_t i = 0; i < count; i++) { tmp[i] = adc_buf[i]; } // 简单冒泡排序 for (uint8_t i = 0; i < count - 1; i++) { for (uint8_t j = 0; j < count - 1 - i; j++) { if (tmp[j] > tmp[j+1]) { uint16_t t = tmp[j]; tmp[j] = tmp[j+1]; tmp[j+1] = t; } } } // 去掉最大最小各一个,剩下的取平均 uint32_t sum = 0; for (uint8_t i = 1; i < count - 1; i++) { sum += tmp[i]; } return (uint16_t)(sum / (count - 2)); }

这段代码在每次采样后更新缓冲区,然后排序去掉极值再平均。窗口大小9,去掉最大最小后平均7个值,对脉冲噪声有很好的抑制。如果你需要更快的响应,可以把窗口降到5,去掉最大最小后平均3个。注意排序在中断里做可能耗时,如果采样率很高,建议在主循环里做,或者用更高效的排序网络。

5.3 校准流程与数据记录

校准分两步,建议在系统上电后、传感器稳定时执行:

  1. 偏移校准:将输入短接到模拟地(或已知的零信号),采256次,用上面的滤波函数读平均值,记为offset。
  2. 增益校准:输入一个精确的参考电压,比如2.000V(用高精度基准源提供),采256次,读平均值,记为gain_raw。理论码值 = 2.000 / 4.096 × 4096 = 2000。实际增益系数 = 2000 / (gain_raw - offset)。

后续测量:实际电压 = (raw - offset) × gain_coeff × Vref / 4096。

把offset和gain_coeff存在EEPROM里,每次上电读取。如果环境温度变化大,可以加温度补偿,但那是另一个话题了。

数据记录时,建议同时记录原始值和滤波值,方便后期分析。如果发现滤波值仍然有规律跳动,先看原始值的频谱,确认干扰频率,再调整采样率或滤波器参数。

6. 常见问题与排查技巧实录

6.1 读数跳动、偏差、串扰的速查表

现象可能原因排查方法解决措施
读数最后几位跳动噪声、参考不稳、采样时间不足短接输入看跳动,换基准看是否改善增加平均次数、加RC滤波、用独立基准
读数整体偏高或偏低偏移误差、增益误差、基准偏差测零输入和满量程输入做偏移和增益校准
多通道之间串扰采样保持电容未充分放电、通道切换太快切换通道后丢弃第一次采样增加通道切换后的稳定时间,或采两次取第二次
读数随温度变化基准温漂、传感器温漂、ADC温漂加热或冷却看变化趋势选低温漂基准,加温度补偿
读数有规律工频干扰50Hz/60Hz耦合,采样率与工频同步改变采样率看跳动频率是否变化用采样率与工频非整数倍,加陷波滤波
高采样率时精度下降采样时间不足、基准电荷不足降低采样率看是否改善增加采样时间,基准加更大去耦电容

6.2 几个只有踩过才知道的细节

第一个,ADC输入端的ESD保护二极管会有漏电流。如果你用高阻分压电阻,比如1MΩ+1MΩ,漏电流在电阻上产生的压降可能达到几个mV,直接吃掉你的精度。解决办法是降低分压电阻,比如用10kΩ级别,或者用运放做缓冲。

第二个,多通道ADC在切换通道后,第一个采样值通常不可信。因为采样保持电容上还残留着上一个通道的电压,需要一次“牺牲采样”来放电。很多MCU的ADC手册会建议丢弃第一次转换结果,但新手往往不知道。我一般的做法是切换通道后连续采两次,用第二次的值。

第三个,取平均的窗口大小不是越大越好。窗口越大,噪声抑制越好,但响应越慢,而且如果噪声里有低频成分,比如1/f噪声,平均到一定程度后改善就饱和了。实测中,窗口从16增加到64,噪声可能只降了20%,但响应慢了一倍。找到那个拐点,通常是在噪声降到可接受范围的最小窗口。

第四个,如果你用DMA搬运ADC数据,注意DMA的传输完成中断和ADC的转换完成中断之间的时序。有时候DMA还没搬完,下一次转换就覆盖了数据,导致你读到的是新旧混合的值。解决办法是ADC转换完成后触发DMA,DMA搬完再启动下一次转换,或者用双缓冲。

6.3 一个真实的调试记录

某次做一个压力采集项目,用24位Σ-Δ ADC,输出速率10SPS,发现读数每隔几秒跳一次,幅度约50个码值。先查电源,纹波很小;查基准,稳定;查输入,传感器输出稳定。后来用示波器看ADC的DRDY引脚,发现跳变时DRDY的周期有轻微变化。再查MCU的时钟,发现用的是内部RC振荡器,温漂较大,导致ADC的采样时钟和内部数字滤波器不匹配。换成外部晶振后,跳变消失。这个问题的教训是:高精度ADC的时钟源必须稳定,内部RC振荡器省不得。

另一个案例是12位SAR ADC,测一个0到20mA的电流环,通过250Ω采样电阻变成0到5V。发现低端非线性,0.5mA以下读数偏差大。查电路发现采样电阻是普通厚膜电阻,温漂100ppm/°C,而且运放有输入失调。换成低温漂电阻和零漂运放后,低端线性度改善到0.1%以内。所以精度是一个系统问题,任何一个环节的短板都会暴露出来。

7. 最后分享几个实用技巧

如果你只想记住三件事:第一,采样时间要算,不要抄别人的电路;第二,取平均之前先看噪声形态,白噪声用算术平均,脉冲噪声用中值;第三,精度靠校准,不靠位数。

再补充一个我常用的快速评估方法:拿一块新板子,先短接ADC输入到地,采1000个点,算均值和标准差。均值就是偏移,标准差就是噪声。然后加一个已知电压,再采1000个点,算均值和标准差。这两个数据就能告诉你这块板子的实际精度和噪声水平,比看数据手册快得多。如果标准差大于1LSB,说明噪声没处理好;如果均值偏离理论值超过2LSB,说明需要校准。

还有一个关于过采样的技巧:如果你用过采样提升分辨率,记得在平均之前不要做任何截断或舍入,用32位累加器把N个采样值加起来,最后再除以N。如果中间就截断到16位,累加会溢出,或者精度损失。另外,过采样的抽取滤波器最好用“sinc”型,简单的算术平均其实就是一个sinc1滤波器,对带外噪声抑制有限,但实现最简单。如果要求更高,可以用两级平均或者FIR滤波。

这个内容后续还可以这样扩展:比如加入温度传感器的非线性校准、多通道轮询的时序优化、以及用FFT分析ADC输出噪声频谱的方法。但那是另一个话题了,先把采样、平均、精度这三块吃透,大部分数据采集问题都能找到方向。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询