# 引言:高阻抗信号源的ADC采样困境 在嵌入式系统中,ADC(模数转换器)是连接模拟世界与数字逻辑的桥梁。然而,当信号源内阻极高(例如>100kΩ)时,直接采样往往导致读数严重偏低且不稳定。以Arduino Uno的10位ADC为例,其内部采样保持电容(约14pF)在采样阶段会从信号源抽取电荷,若信号源无法快速补充,电容电压将无法达到真实信号值,产生所谓的“采样电荷注入误差”。 传统解决方案是添加电压跟随器(如运放),但会增加成本和PCB面积。本文提出一种利用ADC内部采样电容特性的软件技巧,在特定场景下可替代运放,实现低成本阻抗匹配。 # 原理剖析:采样保持电容的电荷再分配行为 ATmega328P的ADC采用逐次逼近(SAR)架构。其采样阶段(Sample and Hold)等效电路如下: ```c // 等效电路示意(非代码) // 信号源Vs -- Rs(内阻) -- S1(采样开关) -- Cs(14pF采样电容) -- GND // 采样时间t_sample = 1.5个ADC时钟周期(默认) ``` 采样时,S1闭合,Cs从0V充电至Vs。充电时间常数τ = Rs * Cs。若Rs = 1MΩ,则τ = 14μs,而默认采样时间仅约13μs(16MHz主频,ADC预分频128,采样周期1.5/125kHz ≈ 12μs),电容仅充至约63%的最终值,导致严重误差。 **关键洞察**:如果我们在采样前,先让Cs预充电至接近信号电压,那么正式采样时所需补充的电荷量将大幅减少,等效于降低了信号源的内阻要求。这类似于“电荷再分配”技术。 # 实现技巧:双阶段采样法 本技巧的核心是:利用ADC的“多次采样”特性,在正式采样前,通过软件快速进行若干次“预采样”,使Cs逐步逼近信号电压。具体步骤如下: 1. **配置ADC为手动触发模式**,关闭自动触发。 2. **执行N次“预采样”**:每次启动转换,但不读取结果(或丢弃),让Cs充电至当前信号电压。由于每次转换后Cs保持电压,下一次采样时,Cs初始电压接近上次值,充电时间缩短。 3. **执行最终采样**:读取ADC数据寄存器,获得准确值。 此方法等效于延长了采样时间,但无需修改ADC时钟(避免降低采样率)。 # 配置步骤(寄存器级) 以下代码基于Arduino IDE,但直接操作寄存器以精确控制。 ```c // 双阶段采样函数 uint16_t readHighZADC(uint8_t pin, uint8_t preSamples) { // 配置引脚为模拟输入 pinMode(pin, INPUT); // 选择ADC通道(假设pin对应模拟引脚0-5) ADMUX = (ADMUX & 0xF0) | (pin & 0x07); // 保留REFS位,设置MUX // 启用ADC,设置预分频为128(125kHz ADC时钟) ADCSRA = (1<