ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

嵌入式ADC从入门到实战:采样原理、外设配置与滤波去噪指南

嵌入式ADC从入门到实战:采样原理、外设配置与滤波去噪指南 搞嵌入式开发跟ADC打交道几乎是绕不开的一关。无论是做电池电量检测、环境温湿度采集还是电机电流环采样、音频信号分析最终都要靠ADC把物理世界那个连续的模拟量翻译成CPU能认识的数字。很多刚入行的朋友看到“模拟信号”“数字信号”“外设工作原理”这些词就头大其实ADC这门技术没有想象中那么玄关键是先把概念理清楚再结合具体芯片把流程跑通。我当年也是从“读寄存器读到一堆乱码”一路踩坑过来的这篇就把我自己从零入门ADC时总结的思路、原理和外设配置经验完整写出来希望能帮你少走弯路。1. 先搞懂ADC在嵌入式系统里到底扮演什么角色1.1 模拟信号与数字信号一个是连续的河一个是离散的台阶先打个比方。模拟信号就像一条河水位是连续变化的你任何时候去量它都有一个对应的值而数字信号就像台阶只能一格一格地跳每个台阶代表一个离散的二进制编码。自然界里的温度、压力、光照、声音本质上都是连续变化的物理量传感器把它们转变成连续变化的电压或电流这就是模拟信号。而我们的MCU内核只能处理0和1也就是数字信号。这里有个最核心的矛盾MCU不认识“3.3V的一半”这种模糊概念它只认寄存器里是0还是1。ADCAnalog-to-Digital Converter模数转换器就是专门架在模拟世界和数字世界之间的一座桥它的任务是把连续电压离散成若干个等级再用二进制编码表示出来。比如一个12位的ADC能把0到参考电压之间的范围切成4096份每一份对应一个数字码。我见过不少初学者把ADC当成一个“电压表”来用觉得只要把引脚接上去就能读到电压这个理解方向没问题但忽略了ADC内部其实有一整套采样、保持、比较、编码的逻辑。只有把这些内部环节搞明白你才能真正理解“为什么我读到的数据会跳”“为什么采样时间不够会导致结果不准”这类问题。1.2 为什么非要“模拟转数字”这一步有朋友会问外部信号本来就是连续的直接分析不行吗不行。因为数字系统有存储和计算的能力但只能针对离散数据进行。换句话说我们要把连续世界里无穷多个可能的取值用有限个数字码去近似表示。这个过程叫量化量化必然带来误差——这是ADC的固有属性你无法消除它只能通过增加位数、优化参考电压、合理配置采样时间来减小它。举个例子一个10位ADC参考电压3.3V那么它的量化单位即1个LSB对应的电压是3.3V/1024约等于3.22mV。也就是说不管真实电压是多少ADC输出的数字码只能反映“它落在这1024个区间中的哪一个”落在同一个区间内的不同电压在数字层面是无法区分的。这就是为什么有些高精度测量场景要用16位、24位的ADC位数越高切得越细越能分辨微小的电压变化。这部分概念虽然基础但特别重要。如果你后面要处理传感器信号、做数据滤波、设计硬件电路脑子里始终要绷着一根弦ADC测到的永远是一个近似值而不是物理量的真值。1.3 嵌入式里最常见的ADC应用场景ADC在嵌入式项目中的存在感极强列几个我实际做过的场景你感受一下电池电量检测锂电池电压通过电阻分压后送入ADCMCU根据电压值估算剩余电量百分比。这个看似简单实际上要做滤波和分段校准否则电量显示会跳来跳去。电位器/旋钮输入像音量旋钮、调光旋钮本质上就是一个可变电阻分压电路ADC读出不同的电压值对应不同的档位。这类场景对采样速率要求不高但对稳定性有要求。NTC热敏电阻测温NTC阻值随温度变化配合一个固定电阻分压ADC读取分压点电压再通过查表或公式换算成温度。因为NTC曲线是非线性的往往还要做软件上的线性化处理。电机相电流采样通过采样电阻把电流转换成电压再用ADC高速采集配合FOC算法做电机控制。这里对ADC的采样速率和同步性要求就很高了。这些场景的共性是传感器输出的物理量最终都要变成电压再由ADC转成数字交给MCU做运算和控制。理解了这一点你对“为什么嵌入式开发必须要学ADC”应该就有直观感受了。2. 三种主流ADC架构与深入采样原理2.1 逐次逼近型SARADC是如何一步步逼近真相的MCU内置ADC绝大多数是逐次逼近型也就是SAR ADCSuccessive Approximation Register。SAR这个词你搜索频率很高值得彻底搞懂。SAR ADC的工作原理可以类比成一个“天平称重”的过程或者更贴近程序员思维一点——它本质上就是硬件版的二分查找。内部结构大致包含采样保持电路、比较器、数模转换器DAC、逐次逼近寄存器SAR和控制逻辑。工作流程是这样的采样保持电路先抓住输入电压把这一刻的电压“冻结”住保证转换过程中电压不变化。控制逻辑让DAC先输出参考电压的一半也就是最高位为1与输入电压比较。如果输入电压大于这个值说明最高位应该为1保留否则为0DAC输出回到原来的低位状态。接着设置下一位为1再次比较逐步缩小范围直到最低位比较完成。这个流程从最高位到最低位逐位确定有多少位就需要多少个时钟周期来完成。所以对于12位SAR ADC来说一次转换至少需要12个比较周期再加上采样时间、内部逻辑开销最终形成“采样周期 转换周期”的总时间。理解SAR的工作原理后有两个关键点自然就清楚了第一为什么SAR ADC比较耗电流因为它内部那个DAC电容阵列每次转换都在不停地充放电频率越高功耗越大。第二为什么输入信号要加RC滤波采样保持电路在采样瞬间相当于一个电容突然接到输入源上如果信号源内阻太高采样电容充不满转换出来的结果就会偏小或者抖动。这是嵌入式ADC采集最容易踩的坑之一。2.2 Σ-ΔSigma-DeltaADC的高精度思路SAR ADC的内部结构决定它很难做到极高的分辨率因为每一位比较都要精确的DAC和比较器位数上去之后成本和复杂度飙升。高精度场景比如称重传感器、音频采集、精密仪器一般用的就是Σ-Δ型ADC。Σ-Δ ADC的思路跟SAR完全不同它不用逐次逼近而是用“过采样 噪声整形 数字滤波”来换取分辨率。具体说它用很低的位数比如1位以极高的采样率去采样输入信号但每次只判断“当前输入比我参考高还是低”然后把这个高低结果反馈给调制器让调制器尽量跟踪输入的平均值。由于过采样率很高量化噪声被分散到很宽的频带内再通过数字滤波器把带外噪声滤掉相当于用时间换精度。看起来复杂其实核心理解一句话SAR是“一次精测量”Σ-Δ是“多次快测然后取平均/滤波”。前者响应快适合电机控制、实时监测后者精度高适合缓慢变化的高精度信号。我用过不少外部Σ-Δ ADC做工业变送器采集精度能到24位但单次转换时间动辄几十毫秒实时性完全没法跟SAR比选型时必须结合场景权衡。另外跟Σ-Δ ADC配套的是前端RC滤波设计。因为Σ-Δ调制器对抗混叠的要求较高而且它对外部时钟抖动敏感所以很多人会在ADC前端加一级RC低通滤波把高频干扰提前拒之门外。这个“前端RC滤波”不是随便焊两个元件电阻电容的取值需要结合传感器输出阻抗、ADC输入阻抗和期望带宽来算后续我会在PCB布局那节详细说。2.3 采样周期、分辨率、参考电压、信噪比这些参数怎么理解搜索词里“adc采样周期”出现频率很高这是实际配置里最容易困惑的地方。采样周期Sampling Time指的是采样保持电路把输入电压充到采样电容上的时间。如果信号源内阻大需要的采样周期就长采样周期太短电容充不满转换结果偏小。STM32的ADC采样周期是可以配置的比如1.5周期、7.5周期、13.5周期、28.5周期、41.5周期、71.5周期、239.5周期等选多少取决于输入阻抗和你要不要追求速度。分辨率ResolutionADC输出的位数常见8位、10位、12位、16位。每增加1位量化等级翻倍精度提升。参考电压VrefADC转换的满量程电压输入电压超过参考电压ADC直接输出满量程。参考电压的稳定性直接影响测量精度——如果参考电压有噪声相当于尺子本身在抖测出来的数据自然不准。信噪比SNR理想情况下ADC的量化噪声对应的信噪比可以用公式SNR 6.02N 1.76dB来估算N是位数。比如12位ADC理想信噪比约74dB。但实际器件还有热噪声、时钟抖动、电源耦合等影响实际信噪比往往低于理想值。有效位数ENOB才是衡量ADC实际精度的关键参数它把各种非理想因素都折算进去了。还有奈奎斯特采样定理要无失真地还原一个模拟信号采样频率必须大于信号最高频率的2倍。这句话看着简单实际工程里很多人都栽在“只知道采样率够高忽略了信号本身有高频噪声”这个问题上——模拟信号进ADC之前如果不做抗混叠滤波那些高于采样率一半的高频噪声会被“折叠”到低频段怎么滤都滤不干净。3. 从外设角度拆解ADC以STM32/GD32为例的工程实践3.1 ADC外设的工作链路通道、采样保持、转换器、结果寄存器看完理论再看外设就顺多了。以我常用的STM32和GD32为例ADC外设的典型工作链路可以拆成这样输入通道芯片引脚通过模拟开关连接到内部的采样保持电路。多个通道可以复用同一套ADC转换器所以ADC支持多通道采集但同一时刻只能转换一个通道。触发源转换可以由软件触发也可以由定时器、外部引脚、定时器比较事件等硬件触发。硬件触发的好处是精确控制采样时刻做电机控制或电网同步采样时几乎是必须的。采样保持电路按照配置的采样周期对接入的电压进行采样把电压“冻结”在采样电容上。逐次逼近转换器SAR逻辑逐位比较生成12位或10位、8位数字结果。结果寄存器转换完成后硬件把结果锁存到数据寄存器里同时置位EOCEnd of Conversion标志。如果开启了DMA转换完会自动触发DMA请求把结果搬走。多通道扫描如果配置了扫描模式ADC会自动按顺序把配置好的通道依次采样一遍结果依次更新到数据寄存器或通过DMA搬运。这里面有“上电后外设逻辑”的问题特别值得注意芯片上电复位后ADC外设默认是关闭的必须在程序里先打开外设时钟、配置GPIO为模拟输入、再配置ADC参数并启动。经常有初学者只配好了GPIO忘了开外设时钟结果读出来的寄存器全是0然后怀疑芯片坏了这其实是“上电后外设逻辑”没理清——外设不会无故自动工作每一步都需要你主动配置。3.2 单通道采集的完整配置步骤以STM32F4系列为例一个最基本的单通道ADC采集初始化流程是这样的开启GPIO和ADC时钟比如ADC1挂在APB2总线上先调用RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE)同时把对应GPIO的时钟打开。配置GPIO为模拟输入注意是模拟输入模式不是浮空输入也不是上拉输入否则引脚内部的上拉/下拉电阻会改变被测电压导致读数偏移。配置ADC参数包括分辨率、扫描模式开关、对齐方式、触发方式、转换通道数等。这里有一个容易忽略的点要先把ADC校准完成再开始转换。STM32内部有校准逻辑上电后最好调用校准函数否则可能出现ADC结果整体偏移——热搜词里“class 读取ADC结果寄存器时可能读到尚未应用ADCOFFTRIM的原始值”说的就是这类问题校准逻辑没跑完就去读寄存器读到的是没修正过的原始值自然不准。配置规则组通道指定用哪个通道、采样周期多少、转换顺序排第几。启动转换软件触发的话调用ADC_SoftwareStartConv然后轮询EOC标志或者等中断。读取结果等EOC置位后从ADC_GetConversionValue读回数据。注意12位结果默认右对齐存放在寄存器的低12位。很多芯片的ADC还有一个“连续转换模式”开启后ADC会不停循环采样数据寄存器持续更新。这个模式适合对实时性要求不高的持续监测场景但如果你要精确控制采样时刻建议改用单次转换加定时器触发的方式避免数据“跟不跟得上”说不清楚。3.3 多通道DMA采集与常见数据紊乱问题实际工程里很少只采一路电压多通道采集几乎必然用到DMA。以前我调试GD32E230的ADC多通道DMA采集时遇到过“数据紊乱”的问题典型现象是通道1的数据跑到通道2的位置或者采集几轮后数据错位。排查下来主要有几种原因DMA缓冲区大小和转换次数不匹配比如配置了3个通道的扫描但DMA缓冲区只设了2个搬运到最后就越界了。这种错误很隐蔽因为程序不一定崩溃但数据已经乱了。DMA循环模式和扫描模式的启动时机没同步扫描模式完成一轮后会自动从第一个通道重新开始但如果此时DMA还没就绪或者DMA配置在某些芯片上需要“先停止再重新配置”更新缓冲区地址就容易出现数据错位。缓存一致性问题如果MCU内核有数据缓存DMA把数据搬运到内存后CPU读到的可能是旧缓存数据需要做缓存失效或清理操作。这在Cotex-M7内核的芯片上特别明显M0/M3/M4大部分没这么严重。DMA中断里处理数据耗时太长如果每轮转换都进中断做大量处理下轮DMA搬运可能已经覆盖了正在读的缓冲区。正确做法是使用“乒乓缓冲”或双缓冲一轮采集在缓冲区A另一轮采集在缓冲区BCPU在处理A时DMA写B处理完再切换。我的习惯做法是多通道采集时DMA缓冲区大小设为“通道数 × 采样轮数”开启DMA循环模式并在DMA传输完成中断里用标志位通知主循环处理数据主循环里及时拷贝走结果。这样既保证了数据连续又不会因为处理太慢导致数据被覆盖。4. 让ADC数据站稳滤波、电源噪声与PCB布局4.1 数据漂移的来源和软件滤波方案ADC数据漂移是社区里最常见的求助帖主题。我踩过几次坑之后总结出漂移大致来自这几个方向参考电压不稳如果Vref直接用LDO输出且LDO本身纹波大ADC的满量程就会跟着抖。这种情况软件很难完全消除只能加滤波或换低噪声参考源。电路板地线噪声ADC采样回路里如果有大电流快速切换的器件比如LED驱动、电机驱动、开关电源地平面上的噪声会直接叠加到信号里。这就是“地弹”现象。外部干扰耦合长走线、靠近时钟线或PWM线的模拟信号线都会耦合高频噪声。信号源内阻偏大内阻大的信号源连接ADC时如果采样周期不够采样电容充不满读数会偏低且随机抖动。对应的软件滤波方法也很成熟我常用的有三种限幅滤波如果两次采样值的差值超过设定阈值认为有干扰丢弃本次值或用上次值代替。适合抑制偶发尖峰。滑动平均滤波维护一个长度为N的队列每次取队列内平均值。N越大越平滑但响应越慢。适合温湿度等缓变信号。中位值平均滤波连续采N次去掉最大值和最小值再取平均。相当于把“中位值滤波的抗脉冲能力”和“算术平均的平滑能力”结合起来。实测对付工业现场的随机干扰效果很好。一个项目里往往不是只用一种滤波而是按信号特征组合使用。比如电机电流采样先限幅去掉尖峰再滑动平均平滑波形电池电压检测直接滑动平均或者中位值平均就够。4.2 电源噪声与时钟抖动对采样的影响这个标题下的热搜词很专业adc/dac 电路设计:规避时钟抖动与电源噪声的3个pcb布局要点。ADC对时钟抖动和电源噪声的敏感程度超乎很多人的想象。先解释为什么时钟抖动会影响ADC。ADC的采样保持电路需要在一个精确的时刻把电压抓住采样时钟的边沿如果在时间上有微小波动实际捕捉到信号的时刻就会忽前忽后。如果被测信号本身变化很快那么即使是几百皮秒的抖动也会造成明显的电压测量误差。SAR ADC对时钟的要求相对宽松但Σ-Δ ADC因为内部是高频调制器对时钟质量很敏感外部时钟抖动会直接恶化信噪比。电源噪声的影响则更直观ADC内部有比较器、DAC、参考电路任何一个环节的供电被污染转换精度都会下降。特别是参考电压引脚如果参考源有纹波相当于量程在抖动测出来的数据自然不准。结合我自己的布板经验这几点非常关键模拟电源和数字电源之间要加磁珠或π型滤波ADC的AVDD引脚最好单独用一个低噪声LDO供电不要直接挂在数字3.3V上。数字电路开关时产生的毛刺会顺着电源线传过来磁珠能有效衰减高频噪声。参考电压走线要远离开关节点DC-DC的电感、MOSFET开关节点、PWM输出线都是强干扰源Vref走线要尽量短、尽量粗并且用地线或地平面包围起来。如果板子上有专门的REF引脚最好加一个高质量的旁路电容并确保电容靠近引脚放置。采样信号走线要短输入端加RC滤波ADC输入端串联一个小电阻如100Ω~1kΩ再并联一个电容到地组成低通滤波一方面抑制高频噪声另一方面给采样电容提供一个低阻抗的电荷源。这个RC的截止频率要结合被测信号的最高频率来定不能随意选。这三条是我每次画带ADC的板子必检查的项目。很多朋友仿真的信号很干净打样回来实测数据就是乱跳十有八九是PCB布局上的问题。4.3 实测中遇到的典型问题速查表最后放一张我在调试ADC时反复用到的排查速查表基本都是实际工作中遇到的直接抄作业没问题。现象可能原因解决方向读到的值始终为0GPIO没配成模拟输入ADC时钟没开启触发方式配置错误检查外设时钟使能、GPIO模式、触发源寄存器读到的值始终满量程输入引脚悬空或外部短路到VCC参考电压异常确认外部电路接线测量引脚实际电压数据随机跳变电源噪声大参考电压不稳采样周期太短外部干扰耦合加大采样周期检查电源滤波输入端加RC软件滤波多通道数据错位DMA缓冲区大小不匹配DMA循环模式配置错误扫描顺序配置错误核对DMA配置和ADC扫描顺序确认缓冲区长度 通道数 × 轮数首次采样值偏大或偏小采样电容尚未充到稳定校准未完成丢弃第一次转换结果或者启动后先执行一次“假转换”再取值长时间运行后数值缓慢漂移芯片温度变化导致参考电压漂移外部电路器件温漂检查参考源温漂考虑软件定期校准加了大滤波电容后读数反而变慢RC滤波截止频率过低重新计算RC参数避免把有效信号也滤掉5. 最后分享一点我自己的实操心得玩ADC这几年我最大的体会是ADC的坑七成在硬件上三成在配置上。很多时候你觉得是代码问题查了半天其实是被测信号本身就不干净。所以调试ADC的第一件事不是翻寄存器而是用示波器看ADC引脚的波形——如果引脚上的信号都是毛刺那软件怎么写都白搭。另外几乎所有MCU的ADC都内置了校准功能上电后一定记得执行这能解决相当一部分“数据整体偏移”的问题。最后建议备一个高精度万用表测量值和ADC读到的值做对比这是判断整个采集链路是否正常的快捷方式。做嵌入式耐心和细心比聪明重要得多ADC这关过了后面再学DAC、定时器、DMA这些外设你会觉得顺畅很多。
返回列表