资讯动态

深入理解SAR ADC:从二分查找原理到STM32工程实践

发布时间:2026/9/4 12:45:38 来源:尧图企业网站定制
咱们做嵌入式的每天都得跟传感器的模拟量打交道。电压、电流、温度、压力这些连续变化的物理量到了MCU里全得变成0和1。很多人会用ADC但真被问到它内部是怎么把连续的电压变成一串离散数字的能讲清楚的不多。这个标题说5分钟看明白我这篇争取让大家用喝杯水的功夫把ADC最核心的机制——也就是逐次逼近型SARADC的二分查找思想给吃透顺便把采样、保持、量化和编码这几个关键环节全部串起来。我尽量不讲太深的理论公式而是用工程思维拆解一个10位SAR ADC从启动到输出结果的完整过程。看完这篇你再去看STM32的ADC寄存器配置或者调试传感器读数跳变的问题心里会通透很多。1. 从连续到离散ADC到底在解决什么数学难题先搞清楚一个根本问题模拟信号和数字信号它们之间最本质的差别是什么模拟信号在时间上和幅值上都是连续的。一个随时间变化的电压它每一个瞬间都有一个确定的电压值而且这个值可以是任意小数。比如0V到3.3V之间可以有1.234567V这种精度。而数字信号在时间和幅值上都是离散的。MCU能处理的只有有限个离散的电压台阶每一个台阶对应一个二进制编码。ADC干的活就是在这两者之间架一座桥。它要做两件事第一把连续时间上的信号切成一个个瞬间的快照这就是采样第二把某个瞬间的电压值归入到离它最近的电压台阶上这就是量化。这里有一个反直觉的坑ADC的分辨率决定了台阶的个数但台阶是怎么切出来的才真正决定了ADC的性格。同样是12位逐次逼近型和Delta-Sigma型用起来完全是两个路子。后面我会详细讲这两种主流架构的取舍。很多人以为ADC就是拿电压除以分辨率得到一个整数。这个说法大方向对但忽略了最关键的一环参考电压。ADC内部所有的比较都是相对于参考电压Vref进行的。没有VrefADC连1V算大还是算小都不知道。这也是为什么高精度ADC的PCB布局对参考电压的干净程度要求那么苛刻。理解了这一层我们再来看ADC最核心的巧妙之处。2. 核心机制拆解二分查找思想在硬件里的完美复刻2.1 为什么说SAR ADC就是一场猜数字游戏SAR ADC的全称是Successive Approximation Register逐次逼近寄存器型。逐次逼近这四个字就是它的灵魂。想象一个猜数字游戏裁判心里想了一个0到1023之间的数对应10位ADC你每次猜一个数裁判只告诉你大了还是小了你怎么用最少的次数猜中学过算法的朋友会脱口而出二分查找。先猜512如果裁判说大了就猜256如果小了就猜768。每猜一次范围缩小一半。1024个数最多猜10次必然命中。SAR ADC内部干的正是这件事。它内部藏了一个DAC数字模拟转换器这个DAC能根据你给的数字码输出一个对应的模拟电压。整个转换过程是这样的SAR寄存器先给最高位置1其他位全置0也就是猜一个中间值1024的一半512。这个数字码被内部DAC转换成一个模拟电压Vdac。比较器把Vdac和输入电压Vin做比较。如果Vin大于Vdac说明猜小了最高位保留1如果Vin小于Vdac说明猜大了最高位清零。然后移到下一位重复同样的操作。从最高位到最低位每一位都这样猜一遍猜完最后一位SAR寄存器里的值就是最终转换结果。这个设计巧妙在哪它把测量一个连续电压这个模拟难题转化成了做10次数字判断这个数字逻辑问题。每一次判断只需要一个比较器整个ADC的核心模拟电路就是一个比较器加一个DAC。这就是为什么SAR ADC能做到低功耗、小面积、中等速度的原因。2.2 一个具体例子3位ADC转换过程的全流程推演光说理论不够直观咱们用一个简化的3位ADC来手算一遍。假设参考电压Vref 8V输入电压Vin 5.2V。3位ADC有8个量化台阶2的3次方每个台阶对应1V8V除以8。转换过程如下第一步猜最高位bit2。SAR寄存器设置为100也就是十进制4DAC输出Vdac 4V。比较器判断5.2V 4V猜小了bit2保留1。第二步猜次高位bit1。SAR寄存器变为110十进制6DAC输出Vdac 6V。比较器判断5.2V 6V猜大了bit1清零。第三步猜最低位bit0。SAR寄存器变为101十进制5DAC输出Vdac 5V。比较器判断5.2V 5V猜小了bit0保留1。最终结果101十进制5。代表输入电压落在了5V到6V之间ADC输出5。注意这里的量化误差5.2V最终被表示成了5V误差0.2V。这就是ADC与生俱来的量化误差分辨率越高量化台阶越细误差越小。这个例子完美解释了标题里说的巧妙设计——用最朴素的二分思想在数字世界里逼近同一个模拟值。2.3 比较器和内部DAC一对配合无间的黄金搭档比较器在整个SAR ADC里扮演的是天平角色。它的输入一端接Vin另一端接内部DAC的输出输出就是一位数字信号0或者1。因为它只需要判断谁大谁小不需要输出具体的差值所以可以做得非常快这也是SAR ADC能做到几Msps甚至几十Msps采样率的原因。内部DAC则负责翻译SAR寄存器里的数字码。有一种很经典的结构叫电荷重分布型DAC它用一组按二进制权重排列的电容阵列来实现。转换开始前所有电容并联采样输入电压相当于把Vin冻结在电容上这就完成了采样保持的功能。然后通过开关切换把电荷重新分配输出与数字码对应的电压。这种设计的好处是采样保持和DAC复用了一套电容既省面积又省功耗。这也是为什么说SAR ADC是中等速度、高精度、低功耗的均衡典型。在MCU内部集成的ADC绝大多数都是这个架构。3. 采样保持和孔径误差很多人忽略的关键环节3.1 为什么必须要有采样保持电路回到刚才说的3位ADC例子你可能注意到一个问题整个转换过程中输入电压必须保持稳定比较器才能做出正确判断。如果Vin在转换过程中一直在变前两步比较大一点后两步比较小一点结果就乱套了。所以在SAR ADC内部转换开始前必须先把输入电压冻结。这就是采样保持电路Track and Hold的职责。一个开关加一个电容就能实现最基本的采样保持开关闭合时电容充电到Vin跟踪状态开关断开时电容保存住当时的电压保持状态。然后ADC对电容上的电压进行逐次逼近。3.2 采样时间不够会怎样一个测试失败的案例这里有实战经验的朋友应该深有体会。我之前调试一个压力传感器采集板STM32的ADC配置的是12位分辨率采样时间设成了最短的1.5个ADC时钟周期。结果读数总是偏低而且误差随着信号源内阻变化而漂移莫名其妙。排查到最后才发现问题就是采样时间太短。传感器输出阻抗比较大加上PCB走线和滤波电容等效源阻抗有几十千欧。ADC采样瞬间内部采样电容要从这个高阻抗源抽取电荷RC充电时间常数太大1.5个周期根本充不满导致采样值系统性地偏低。这里给个实用的经验值ADC采样时间要满足采样电容充电需求一般要求源阻抗越小越好。如果源阻抗大要么加一级运放做缓冲要么把采样时间拉长。STM32的ADC采样时间通常建议配置在10.5周期以上除非信号源阻抗确实很低。3.3 孔径误差是怎么来的再往前推采样保持电路本身也有一个斜率为无穷大的理想假设。实际上开关断开需要时间从你发出保持命令到开关真正断开有一个短暂的延时叫孔径时间。在这段时间里输入信号还在变化电容上保存的值就已经不是你想要的那个点了。对于高频信号这个误差放大得特别明显。所以高精度采样高频信号真正要做的是把采样时钟设计得非常干净抖动要小。时钟抖动的本质就是孔径时间在变化每次采样的精确时刻不一样还原出来的波形就会有噪声底。做音频ADC的朋友应该有感受时钟抖动直接决定了你能达到的信噪比上限。4. 从原理到选型不同ADC架构的对比与工程取舍SAR ADC是MCU上最常见的内置ADC架构但它不是万能的。在工业仪表、音频、高精度测量这些场景你还会碰到Sigma-Delta ADC、Flash ADC甚至Pipeline ADC。选型本质上是速度、精度、功耗、成本的四方博弈。先来看Flash ADC。它用2的N次方减1个比较器把参考电压分成2的N次方个区间一次比较就能出结果。速度极快N位需要2^N个比较器10位就要1023个比较器面积和功耗大得离谱。一般只用在高速示波器、通信接收机这些需要GHz采样率的场景里。Sigma-Delta ADC的思路完全不同。它不做逐次逼近而是用极低分辨率常常是1位但极高采样率对信号进行过采样然后用数字滤波器把量化噪声整形到高频段并滤除。它能实现非常高的有效位数ENOB可以做到20位以上但延迟大、速度慢。适合称重传感器、精密温度测量这种信号变化慢但对精度极苛刻的场合。下表整理了几种主流ADC架构的典型对比架构类型典型分辨率典型采样率核心优势核心短板典型应用SAR8~18位100k~10M功耗低、面积小、易集成精度和速度中等MCU内置采集Sigma-Delta16~24位10~1000k精度极高、噪声整形延迟大、速度受限称重、音频Flash6~10位1G以上速度极快面积功耗巨大高速示波器Pipeline10~16位10M~1G速度精度均衡延迟较大视频采集、雷达从这张表能看出来做产品选型真的别一步到位追最好。实际项目里先界定好信号的带宽和需要的有效位数再去看架构多数情况下MCU自带的SAR ADC已经够用。我见过太多人一上来就上外挂24位ADC结果电源、布局、软件滤波全跟不上出来的有效位数还不如人家认真调过的16位。5. 工程落地以STM32为例的ADC采集全程实操光懂原理还不够得真刀真枪把数据采回来。我拿最常用的STM32F103或者F4系列举个例子把从初始化到拿到稳定数据的完整链路捋一遍。5.1 最小初始化配置用标准库旧版和HAL库都能做核心配置就三块时钟、GPIO、ADC参数。GPIO设置成模拟输入注意千万别把引脚配置成复用推挽否则要么烧引脚要么采出来的值是乱的。然后是ADC的时钟配置一般要求ADC时钟不超过14MHzF1系列F4可以到36MHz。时钟高了转换速度上去了但采样电容充电时间也相对变短所以采样周期要留足余量。一个比较稳的参数组合分辨率12位采样周期28.5周期或更高ADC时钟12MHz。算下来单次转换时间大约是12.5 28.5除以12MHz约等于3.4微秒对应采样率大约294kSPS。对绝大多数传感器来说这个速度已经完全够用。5.2 连续采样和DMA的正确姿势单次转换模式下CPU要被耗住好几次启动转换、等待EOC标志位置位、读数据寄存器。如果只是偶尔采一次无所谓。但要做连续数据流比如音频采样或者用一批数据做软件滤波必须让DMA出场。DMA的优势是让数据自己流到内存里CPU完全不用管。比如配置ADC扫描模式使能DMA循环模式把数据缓冲区长度设为N那么每次转换完成数据自动写入缓冲区。CPU只需要在缓冲区满的时候去做处理。这样采样率可以跑得比较高而且不会因为CPU中断响应延迟导致采样点丢失。这里有个常见的坑DMA配置的是半字half word还是字word。12位ADC结果存储在16位寄存器里所以DMA数据宽度用半字。如果用字模式数据会错位读出来的值奇怪得很。5.3 坐标转换从ADC值到真实物理量的映射采到ADC原始值比如0到4095并不是我们最终想要的东西。如果采集的是电压要还原成实际电压Voltage ADC_Value / 4096 * Vref。这里有个细节很多人没注意12位ADC除以的应该是40962的12次方而不是最大值4095。因为电压范围是0到Vref连续区间数字码0对应0V数字码4095对应Vref的4095/4096。差别虽然只有一个LSB但做高精度测量时这个误差是要较真的。采到的是传感器电压还要乘上传感器灵敏度系数才能得到最终的物理量。比如一个量程100kPa的压力传感器输出0.5V到4.5V对应0到100kPa。那么变量映射要考虑零点电压0.5V而不是直接按0V对应0kPa算。5.4 软件滤波的那些坑采集回来的数据必须滤波这句话没毛病。但用什么滤波怎么滤学问不小。最常见的做法是滑动平均。取最近N次采样取平均值。N越大平滑效果越好但对信号变化的响应越慢。我曾经在电机电流采样上用过64点滑动平均结果电流环的PI控制器反馈滞后明显导致系统振荡。后来换成16点问题就消失了。滤波器的延迟在控制回路里是巨大的隐患这点要特别警惕。中值滤波对付尖峰脉冲噪声效果好。比如工业现场电磁干扰强的场合偶发的大毛刺会把平均值拉偏用中值滤波可以干净地剔掉。我一般会做一个滑动中值滑动平均的组合滤波先取5个点中值再对连续的中值结果做16点平均。牺牲一点计算量换来的数据质量对得起这个成本。6. 实操中的两个高频疑难采样周期和抗混叠滤波器这一节说的是我在实际项目里反复踩过的两个坑全部是原理层面的理解偏差导致的。6.1 采样周期到底怎么设采样周期这个参数寄存器里能配的就是几个固定档位1.5周期、7.5周期、13.5周期、28.5周期、41.5周期等等。很多人不理解这数字怎么来的就直接全选最大的。这样做的后果是采样率被拖累而且对快速变化的信号反而会采到模糊的值。采样周期本质就是采样电容的充电时间。你需要估算信号源最大等效阻抗然后算RC时间常数确保在采样周期内电容电压充到误差小于0.5个LSB。公式不复杂充电误差 Vref * exp(-t / (R_source * C_sample))要让误差小于 0.5 * Vref / 2^N所以 t (R_source * C_sample) * ln(2^(N1))不同MCU的采样电容不一样STM32一般是几pF到十几pF你可以从数据手册查到精确值。工程上可以简化源阻抗小于1kΩ用1.5周期问题不大源阻抗几十kΩ至少用28.5周期以上源阻抗几百kΩ请放弃直接用ADC先加运放缓冲。6.2 抗混叠滤波器不是可有可无香农采样定理说采样率至少要是信号带宽的两倍。但如果输入信号里有高于奈奎斯特频率采样率一半的成分它会折叠回低频区域产生混叠。混叠是个挺隐蔽的问题因为你滤波都滤不掉——它已经长在数据里了。解决办法只有一个在ADC输入之前用一个硬件低通滤波器把超过采样率一半的信号能量全部滤掉。这就是抗混叠滤波器。我见过一个实际事故调试一个箱体振动检测项目采样率设为1kHz传感器输出有几个固定频率600Hz、900Hz的谐振峰。没有任何抗混叠滤波结果数据里出现了100Hz和400Hz的假信号频域分析一头雾水。后来才知道600Hz和900Hz折叠回来刚好落在100Hz和400Hz。加了一个二阶RC低通截止频率设在200Hz假信号全消失了。这里有个常见误区很多人觉得软件滤波能解决混叠。软件滤波只能处理已经进ADC的数据混叠是发生在ADC采样那个瞬间的软件根本无力回天。抗混叠滤波必须在模拟端完成。当然纯软件处理的低速直流信号可以不考虑这个问题但只要信号频率和采样率相对接近就得认真做硬件滤波。7. 一次真实的排障全流程温控板ADC读数跳变之谜理论说多了落地一个实际的排查过程。这块温控板用STM32的ADC采集一个NTC热敏电阻分压电压用来测水温。现象是温度稳定时ADC读数会在正负20个码之间来回跳对应的温度波动有半摄氏度。对恒温控制来说这个波动太大没法用。我当时的排查路径是这样的第一步先看电源纹波。用示波器量ADC的参考电压Vref引脚发现上面有大约30mV的纹波频率是开关电源的开关频率。30mV对于3.3V满量程来说约等于15个码的波动。这跟观察到的20个码的跳变基本吻合。问题定位到参考电压不干净。第二步看PCB布局。NTC分压电路的地和DC-DC的地在PCB上是直接连成一大片的没有做单点回流。开关电流经过地平面时在NTC分压的参考点之间产生了压差。这就导致Vref没问题但Vin的地参考点飘了读数同样会跳。第三步处理办法。硬件上做了两处修改NTC分压部分的地通过一个磁珠和星形单点方式回到主地Vref引脚用10uF钽电容加100nF陶瓷电容做双重去耦。软件上把采样速率从150kHz降到30kHz并把采样周期调到最大同时在软件里做16点滑动平均。三招一起下去ADC读数稳定下来跳变范围从20个码降到了两三个码。温度波动控制在0.1摄氏度以内。这个案子给我们的启示是ADC读数跳变很多时候不是ADC本身的问题而是它的供电、参考电压和地的质量在拖后腿。拿到跳变的读数先不要赖芯片先去量参考电压和地的噪声。真正的ADC问题其实比我们想的少得多。另外软件滤波能掩盖一部分硬件问题但它只是掩盖不是解决。该在硬件上花的功夫省不得。热设计、布局、去耦这些基本功在ADC采样质量里占比很大。8. 关于ADC精度有效位数和提升精度的几条实用路径最后聊一个被误解很深的概念有效位数ENOB。很多芯片标称16位ADC结构上是真的16位数据长度也是16位但不代表有效精度就是16位。由于噪声、非线性、温度漂移这些因素实际能保证的有效精度往往只有14位甚至12位。这就是为什么有些仪表产品用的ADC芯片并不高级但因为整体设计和校准做得好实际精度反而比那些堆硬件的产品高。提升实测精度我比较推荐这几条路径按性价比从高到低第一条多次采样取平均。这是最便宜、最简单、最有效的方法。过采样加求平均等效于把量化噪声随机化并降低。比如4次平均相当于多1位有效位16次平均相当于多2位。代价是采样率下降但对多数传感器应用来说完全可接受。第二条硬件上把参考电压做好。Vref是ADC衡量所有电压的标尺。标尺自己不稳其他全都白搭。用独立的低噪声LDO给Vref供电尽量远离数字电路和功率电路。有些MCU有内部参考电压但温度和电压稳定性一般对精度要求高还是外接专用基准芯片靠谱。第三条校准偏移和增益误差。MCU内部ADC往往有出厂校准值有的支持运行时校准。但校准概念可以推广到整个采样链路包括运放的失调电压和增益误差。在系统端做两点校准输入标准低电平记为偏移输入标准高电平记为增益然后做线性修正。这个办法能去掉系统误差的百分之八九十。第四条布局上隔离模拟和数字。ADC引脚是模拟引脚它旁边的Goio和电源别走太近。模拟地和数字地可以分区布局在ADC芯片附近单点连接。这条规则很多新手容易忽略布局随意了之后后端的滤波和校准会变得非常被动。我个人实际项目的体会是这四条路径里把参考电压做好和校准这两条带来的提升最明显而且是可测量、可复现的。采样平均多多少少有点用时间换精度的意思适合用在响应速度要求不高的场景。9. 最后分享一个小技巧真要判断一个ADC链路行不行别光看静态读数。把ADC输入短接到地读一组数据算均值再把输入接到Vref读一组数据算均值。这两个值之间基本就是你的ADC在全量程上的表现。然后扫描一个缓慢变化的斜坡信号比如几百Hz的正弦波看输出有没有明显的台阶失真或者跳码。这套自检流程做下来比看任何数据手册都更能帮你了解手里的系统到底有几斤几两。ADC这个领域概念理解清楚之后剩下的都是工程经验问题。最不能犯的错就是差不多得了——参考电压差一点布板随意一点采样时间省一点最后数据精度差了不止一点。反过来你把基础原理吃透每个环节按规律来出来的数据质量是很稳的。希望这篇能帮大家把ADC这块从会用推到用得明白。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价