☰
PY32F002B低功耗ADC采样:VREFINT参考电压补偿与误差校准实战
2026/9/30 3:41:24 网站建设 项目流程

去年做一款电池供电的低成本传感器节点,成本压力压得很死,主控从某一颗进口MCU换到了普冉PY32F002B,BOM一下子降了不少,心里还挺美。结果样机一上电池,ADC采出来的数据就开始“表演”了,同一个温度点,上午测和下午测读数能差出一大截。一开始我以为是热敏电阻分压电路的问题,排查了一圈才发现,根子出在ADC的参考电压上——VDD一路从3.3V掉到2.7V,而ADC参考电压直接就是VDD,参考都在漂,采样值怎么可能稳得住。这就逼着我把内部参考电压VREFINT真正用起来,顺手把误差补偿和低功耗采样这块一起做透了。这篇文章就把整个思考和实操过程记录下来,给正在这颗芯片上折腾ADC的朋友一个参考。

1. 先把问题定性:便宜芯片配便宜参考电压

1.1 PY32F002B的ADC到底优势在哪

PY32F002B这颗料,Cortex-M0+内核,主频最高能到24MHz,Flash和RAM虽然不大,但在传感器节点、小家电、玩具、电源管理等场景完全够用。关键是它的价格太有杀伤力,一颗料比很多进口MCU便宜一大截,所以这两年很多成本敏感的项目都在往它身上迁移,我周边做灯控、做温湿度传感器、做电子烟方案的同行也都在用。

这颗芯片内部集成了一路12位SAR型ADC,支持多路外部通道,还带一个内部参考电压通道VREFINT。12位分辨率在消费级产品里属于中规中矩的水平,但它ADC的转换速度不算慢,配合DMA和定时器触发也可以实现连续采样。不过最让我看重的是它带了VREFINT,这就意味着我们可以摆脱对外部基准电压芯片的依赖,也可以修正VDD参考电压漂移带来的测量误差,这个价值在实际项目中非常大。

1.2 参考电压漂移才是ADC不准的头号元凶

很多工程师在用ADC的时候,默认把VDD当成一个稳定的参考电压,实际上VDD从来都不是稳定的,尤其是电池供电的场合,随着电量消耗,VDD会逐步下降。ADC转换的本质是“比例测量”,转换结果 = Vin / Vref × 满量程,这里Vref就是参考电压。如果Vref在变,而代码里还按固定公式换算电压,结果必定飘。

我用一个具体场景说明:假设被测电压是1.25V,VDD从3.3V掉到2.4V,未做补偿时按固定公式算出来的“电压值”能偏出5%以上。这个误差在12位ADC里已经属于灾难级别了,对温度、压力、气体浓度这些模拟量传感器来说,直接会导致最终测量值不可用。所以做电池供电产品,参考电压问题不能回避。

1.3 VREFINT的价值:一个挂在芯片内部的“稳定标尺”

VREFINT是芯片内部一个带隙基准电压源,它输出一个大约1.2V的稳定电压,理论上不受VDD变化影响。芯片出厂时在内部把VREFINT接到了ADC的某一个固定输入通道上,我们不需要任何外部器件,直接读ADC就能知道当前VREFINT的转换码值。

它的核心用途不是直接测量外部信号,而是作为一个“已知量”去反推当前ADC实际的参考电压。也就是说,任何时候我读一下VREFINT通道的ADC码值,就等于在问芯片:“你现在内部的参考电压实际值是多少?”拿到了这个实际参考电压,再去修正其他通道的测量结果,误差就被吃掉了。这个思路在STM32、GD32等系列里也很常见,可以用一套方法通吃。

2. 误差到底从哪来:VREFINT不是万能神药

2.1 带隙基准也有制造离散度

VREFINT最基础的问题是它有一个“绝对准确度极限”。数据手册上会给出典型值,比如1.2V,但不同芯片之间,因为晶圆制造工艺的偏差,实际值可能在1.18V到1.22V之间浮动。这个误差属于系统性的固定偏差,每个芯片不一样,但如果代码里统一按1.2V去算,就会引入最大的那部分误差。

我最初就是直接按数据手册标称值1.2V参与计算,结果测一个1.000V的基准电压,读出来1.01V多,误差已经超过1%了。对12位ADC来说,1%的误差意味着大概40个LSB的偏差,这在很多应用里已经不可接受。所以VREFINT可以用,但必须经过校准,不能直接拿标称值当真值用。

2.2 ADC本身的失调与增益误差

除了参考电压的离散,ADC转换链路本身也不是完美无缺的。SAR型ADC内部有比较器失调、电容阵列失配等问题,最终表现为转换结果的“零点偏移”和“增益误差”。也就是说,哪怕参考电压是完全准确的,ADC读出来的码值也可能整体偏大或偏小,或者斜率不完全对。

这个误差同样可以通过校准来修正,只不过它和VREFINT校准是两码事。VREFINT校准解决的是“参考电压是多少”的问题,ADC校准解决的是“转换器本身有多偏”的问题。在低成本芯片上,厂家一般不会给每个ADC通道都做芯片级出厂校准,所以我们要靠自己设计校准流程去修正这两层误差。

2.3 温度漂移导致的缓慢漂移

还有一个容易忽视的因素是温度。带隙基准虽然比齐纳二极管温漂小很多,但仍然不是零温度系数。数据手册通常会给出VREFINT的温度系数典型值,比如±20ppm/℃甚至更高。如果产品在不同季节、不同地区使用,环境温度变化可能让VREFINT电压值发生几十到上百ppm的漂移,最终反映到ADC结果上就是低温或高温环境下测量值偏差变大。

温度漂移的处理比固定偏差棘手一些,因为它是动态的。但好在VREFINT是一个可以实时读取的通道,我们每次采样时同步读一次VREFINT的当前码值,相当于拿到了“当前温度下VREFINT现在的实际状态”,这就能补偿掉大部分温漂。真正难处理的是VREFINT本身随温度的非线性漂移,这需要更高精度的两点或者多点标定才能解决。

2.4 采样时间不足引发的“隐性误差”

采样保持电路电容充电不足导致转换结果偏低,这个问题和上面三样叠加在一起,会让人觉得ADC“烂得没法用”。但很多时候芯片挺好,纯粹是配置没到位。SAR ADC转换前需要一段时间让内部采样电容充电到输入电压,如果采样周期太短,电容充不满,转换结果自然偏小。这属于使用层面的误差,不是芯片本身的问题,但它的影响非常明显,必须单独拎出来注意。

3. 误差补偿实操:从单点到实时跟踪

3.1 单点标定:用一把好表,求出你这颗芯片的VREFINT真值

既然每颗芯片的VREFINT实际值不确定,那我们就在生产或者调试阶段做一次标定,把这个真值测出来,然后存到Flash里,以后每次开机直接读取使用。

具体做法是这样:用一台高精度稳压电源给板子供电,同时用四位半以上的万用表实测VDD引脚电压,记为VDD_measured。然后让芯片去读VREFINT通道的ADC码值,记为vrefint_adc。这时候我们其实知道一个等式:

VREFINT_true × 4096 / vrefint_adc = VDD_measured

这是“比例法”的核心思路。整理一下,就得到了这颗芯片VREFINT的真实电压:

VREFINT_true = VDD_measured × vrefint_adc / 4096

我这边实测一个样片:VDD实测3.2989V,VREFINT通道ADC码值平均在1490左右,那么这颗芯片的VREFINT_true就是 3.2989 × 1490 / 4096,算出来约1.1999V。很接近标称1.2V,但如果你直接按1.2V算,又差了一点点,日积月累在高压输出场景就会被放大。把算出来的这个值写到Flash的某个参数区,标定完成。

3.2 运行时补偿:每次采样都问一次“参考电压现在是多少”

单点标定只在生产时做一次,运行时我们要做的是“实时补偿”。思路是每次要测外部通道之前,先读一次VREFINT通道的ADC码值,然后用标定的VREFINT_true去算出当前实际的参考电压VREF_actual:

VREF_actual = VREFINT_true × 4096 / vrefint_adc_now

拿到当前参考电压后,再测目标通道的码值,就能算出外部电压的真实值:

V_channel = adc_channel_raw × VREF_actual / 4096

实测下来,这套方案在VDD从3.3V掉到2.4V的过程中,同一被测电压的换算结果误差能控制在0.2%以内,效果非常明显。关键在于“每次采样都同步读一次VREFINT”,不要偷懒只在开机时读一次,因为电池放电过程是持续变化的,只有实时跟踪才能保证精度。

3.3 两步走:ADC校准位和软件补偿组合

除了VREFINT的电压值标定,ADC本身还需要做一次校准。很多Cortex-M0+系列的ADC模块里有一个校准机制,启动ADC后需要执行一次自动校准流程,在校准完成之前尽量不要去触发转换,否则精度会受影响。这个动作虽然叫“校准”,但它修的是ADC内部的失调误差,和VREFINT的外部标定不是一个概念,两个都要做。

我的初始化顺序是:打开ADC时钟,等待VREFINT建立稳定,执行ADC自动校准,等待校准完成,然后开始正常转换。如果跳过自动校准这一步,最典型的表现是零点附近读数不为0,或者所有采样值整体偏移十几个LSB。加了这个步骤之后,表现会好很多。

3.4 滤波:最后一公里的稳定剂

实时补偿解决了参考电压漂移,ADC校准解决了卡脖子系统误差,采样时间配置解决了充电不足,但ADC采集出来的数据还是会有一个LSB到几个LSB的随机跳动,这是由芯片底噪、电源纹波、输入信号阻抗等共同决定的。这时候就需要在软件层面滤波。

我实测在PY32F002B上最好用的组合是“中值滤波+滑动平均”。每轮采集5个值,排序取中间值,然后和最近4轮的中值再做一次平均。这样既能抑制毛刺尖峰,又能让输出曲线平滑,响应速度也不会拖沓。滤波放在补偿计算之后做,先算出真实电压值再滤波,或者先对码值滤波再算电压,结果上差异不大,但建议对最终物理量滤波,更直观。

4. 低功耗优化:让ADC既能干活又少费电

4.1 低功耗不只是“采完就睡”

多数人接触低功耗MCU之后,都会知道一个粗略的原则:没事别跑时钟,没事别开外设,没事就睡觉。但落在ADC采样这件事上,细节更多。ADC本身在转换时会消耗不小的动态功耗,特别是在高频时钟驱动下,所以低功耗ADC采样的核心思路是“尽快采完、采完就关、尽量少采”。

每个采样周期的能耗 = 唤醒时间 × 唤醒功耗 + 转换时间 × 转换功耗 + 睡眠时间 × 睡眠功耗。实际项目中,唤醒和转换时间通常占整个采样周期的比例很小,大头都在放电电流只有微安级的睡眠期。你要做的就是把唤醒时间压缩到最短,把转换时间也压缩,尽早回到睡眠状态,而不是让芯片在醒来之后磨磨蹭蹭。

4.2 时钟选择:先降频,再采样

PY32F002B的ADC时钟一般是从系统时钟分频得到的。分频系数越大,ADC时钟越低,转换速度越慢,但功耗相对更低。在电池供电产品里,我们不需要追求极高的采样率,所以选择合适的分频系数,把ADC时钟压到几百kHz级别,既能保证采样精度,又能显著降低转换功耗。

我实测过,采样周期固定情况下,ADC时钟从高主频降到分频后的一两百kHz,整机功耗虽然没有数量级变化,但也有肉眼可见的降低。代价是单次转换时间变长了一些,不过对于状态监控类应用,几百微秒和几十微秒差别不大,省电优先。

4.3 外围电路功耗:分压电阻是隐形电老虎

一个经常被忽略的低功耗细节是ADC输入采样电路自身。很多传感器信号是通过电阻分压后送到ADC引脚的,如果分压电阻选得太小,比如两个10kΩ电阻,那么在电池供电系统里,这条分压链路本身就会持续消耗电流。对于一节纽扣电池来说,几微安的漏电已经非常可观了。

我的做法是:首先用大电阻分压,比如100kΩ级别甚至更高的电阻。其次,在不需要采样的时候,把分压网络的一端通过一个GPIO输出低电平关断,或者用MOS管把传感器供电单独切断,只留MCU本身在睡眠。第三,在ADC引脚和地之间正常放置一个0.1μF左右的采样电容,一方面减小采样瞬间对信号源的内阻要求,另一方面也能在采样时提供稳定的电荷源。这些细节叠加起来,整个待机电流才能压下来。

4.4 转换后外设时钟的关闭顺序

不要小看这个细节。ADC转换完成后,需要做的事是:禁止ADC模块、关闭ADC时钟、关闭对应GPIO的模拟功能时钟。有些人只做了ADC软件关闭,却忘了分频器时钟还开着,这一步偷懒可能导致待机电流凭空多出几百微安。

在PY32F002B上,我建议建立一个“采样完成后关闭所有采样相关时钟”的习惯。可以写成一个函数,里面统一把ADC时钟关掉、把对应外设复位、把GPIO切回低功耗模式,主循环里调用这个函数后再进入睡眠。顺序不要反:先关模块,再关时钟,最后再睡,中间不要穿插忘记的延时等待。

4.5 定时采样策略:用休眠时钟定时唤醒

既然低功耗的重点是尽快回到睡眠,那就需要一个可靠的唤醒源。PY32F002B通常内置低功耗定时器,可以在睡眠模式下继续跑,并周期性产生唤醒事件。我们的采样逻辑就可以这样组织:平常睡在最深的停止模式下,让低功耗定时器每1秒或者每10秒唤醒一次,醒来后快速打开时钟、稳定VREFINT、切换分频、触发ADC、做补偿和滤波、关外设时钟,然后再次进入停止模式。

这套流程跑顺之后,整个节点的平均功耗可以压到非常低的水平,几节纽扣电池撑几个月不是问题。需要注意的是,每次唤醒后代码要能正确判断“我是从低功耗模式回来的”,该重新配置的寄存器都要重新配,特别是一些掉电模式会丢失配置的外设。

5. 完整代码实现:可以直接抄的工程实践

5.1 初始化与ADC校准

下面这段是我在PY32F002B上实际跑通的初始化代码,用标准外设库风格编写,不同型号的库函数名可能会有细微差异,但逻辑完全一致。

void adc_init(void) { GPIO_InitTypeDef gpio_init; ADC_InitTypeDef adc_init; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* 配置ADC输入引脚为模拟输入 */ gpio_init.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; /* 外部采样通道 */ gpio_init.GPIO_Mode = GPIO_Mode_AN; GPIO_Init(GPIOA, &gpio_init); /* ADC分频,降低时钟频率,省电优先 */ RCC_ADCCLKConfig(RCC_PCLK2_Div8); adc_init.ADC_Mode = ADC_Mode_Independent; adc_init.ADC_ScanConvMode = DISABLE; adc_init.ADC_ContinuousConvMode = DISABLE; /* 单次转换模式 */ adc_init.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /* 软件触发 */ adc_init.ADC_DataAlign = ADC_DataAlign_Right; adc_init.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &adc_init); /* 启动ADC自动校准,务必等待校准完成 */ ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); ADC_Cmd(ADC1, ENABLE); }

5.2 读取VREFINT与外部通道核心函数

为了保持代码简洁,我把读VREFINT和读外部通道封装成两个函数,内部都包含采样次数取矩平均的逻辑。

#define ADC_CHANNEL_VREFINT ADC_Channel_17 /* 具体通道号以实际芯片为准 */ static uint16_t adc_read_channel(uint8_t channel) { uint32_t sum = 0; uint8_t i; ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5); for (i = 0; i < 5; i++) { ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET); sum += ADC_GetConversionValue(ADC1); } return (uint16_t)(sum / 5); } uint16_t adc_read_vrefint(void) { return adc_read_channel(ADC_CHANNEL_VREFINT); }

采样时间我选的是ADC_SampleTime_239Cycles5,这个时间比较长,对高内阻的输入信号更友好,采样电容能充分充电。如果你对采样速度敏感,可以缩短到几十个周期,但前提是输入源阻抗足够低。

5.3 补偿计算与电压换算核心代码

这里涉及VREFINT的真实电压标定值和实时码值。假设标定值已经存到了Flash里,读取函数如下:

float vrefint_true_mv; /* 标定的VREFINT真实电压,单位mV */ float adc_get_vref_actual_mv(uint16_t vrefint_adc_now) { return (vrefint_true_mv * 4096.0f) / vrefint_adc_now; } float adc_convert_to_voltage(uint16_t adc_value, float vref_actual_mv) { return ((float)adc_value * vref_actual_mv) / 4096.0f; } float adc_get_voltage_with_compensation(uint8_t channel) { uint16_t vrefint_adc = adc_read_vrefint(); uint16_t ch_adc = adc_read_channel(channel); float vref_mv = adc_get_vref_actual_mv(vrefint_adc); return adc_convert_to_voltage(ch_adc, vref_mv); }

注意这里我使用浮点数只是为了代码清晰,实际工程里如果对性能有要求,可以全部改成整数定点运算,避免MCU在软浮点上的开销。但PY32F002B跑浮点也没太大压力,看具体场景取舍。

5.4 低功耗采样状态机主流程

下面这个状态机可以放进一个周期任务里,配合低功耗定时器唤醒,完成“睡醒-采样-处理-再睡”的完整循环。

typedef enum { ADC_STATE_IDLE, ADC_STATE_WAKE, ADC_STATE_SETTLE, ADC_STATE_SAMPLE, ADC_STATE_PROCESS, ADC_STATE_SLEEP } adc_state_t; volatile uint8_t g_adc_wake_flag = 0; void adc_lowpower_task(void) { static adc_state_t state = ADC_STATE_IDLE; uint16_t vrefint_adc; uint16_t ch_adc; float voltage_mv; switch (state) { case ADC_STATE_IDLE: if (g_adc_wake_flag) { g_adc_wake_flag = 0; /* 唤醒后重新开启时钟,无特殊情况需要重新初始化寄存器 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); state = ADC_STATE_SETTLE; } break; case ADC_STATE_SETTLE: /* 让VREFINT稳定,实测至少需要几十微秒 */ delay_us(100); state = ADC_STATE_SAMPLE; break; case ADC_STATE_SAMPLE: vrefint_adc = adc_read_vrefint(); ch_adc = adc_read_channel(ADC_CHANNEL_0); state = ADC_STATE_PROCESS; break; case ADC_STATE_PROCESS: /* 用上面补偿函数换算真实电压 */ voltage_mv = adc_convert_to_voltage(ch_adc, adc_get_vref_actual_mv(vrefint_adc)); /* 这里做滤波算法,然后更新全局变量保存结果 */ /* 关闭ADC和相关时钟 */ ADC_Cmd(ADC1, DISABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, DISABLE); /* 关闭采样通路GPIO时钟或切换IO状态 */ state = ADC_STATE_SLEEP; break; case ADC_STATE_SLEEP: PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI); /* 系统时钟需要重新配置,按芯片手册要求处理 */ state = ADC_STATE_IDLE; break; default: state = ADC_STATE_IDLE; break; } }

这套状态机的核心优点是把“稳定等待”“采样”“关闭外设”“睡眠”切成独立的阶段,方便你后续在中间插入超时保护或者状态检查,调试起来也直观。我把“100微秒稳定时间”放在采样之前,这个时间对VREFINT输出稳定非常关键,省掉之后首采的码值会偏低,后面再采又会跳。

5.5 生产阶段的自动标定流程

产线标定比实验室手动标定更讲究效率。做法是先把板子接到一个已知的高精度电源上,比如3.000V,然后上位机通过串口发一条命令,固件收到后先读VREFINT码值,再通过串口回复,上位机在电脑端计算VREFINT真实值,然后写回Flash。也可以直接在固件里做:预设VDD=3000mV,读取VREFINT码值,算完写Flash,上位机只负责触发。

需要注意,产线标定时供电电压必须非常准确,否则标定完误差会整体偏。如果供电电压偏差0.5%,那么标定出来的VREFINT真实值也会偏差0.5%,后面无论怎么补偿都是这个底子。所以产线上尽量用精度高一点的稳压源,或者用万用表实测后通过串口告诉固件,不要完全依赖焊盘上写的“3.3V”。

6. 实测数据与避坑指南

6.1 校准前后对比:数据会说话

我在板子上做了一组对比测试,VDD从3.3V降到2.4V,外部输入固定接1.250V,看ADC换算出来的电压值:

VDD (V)未补偿计算值 (V)未补偿误差补偿后计算值 (V)补偿后误差
3.301.268+1.44%1.251+0.08%
3.001.244-0.48%1.252+0.16%
2.701.209-3.28%1.248-0.16%
2.401.178-5.76%1.2500.00%

从这个表可以看得很清楚,未补偿时VDD越低误差越大,原因是拿固定的标称VREFINT去算参考电压,VDD已经掉到2.4V了,原始码值被拉高,换算结果自然离谱。补偿之后全电压范围内都跑在0.2%以内,这个精度在消费类产品里完全够用。

6.2 采样周期对码值的影响

我用一颗10kΩ内阻的信号源做测试,不断加大ADC采样周期,记录同一个输入信号的稳定码值。刚开始采样周期短,读出来的值明显偏低;随着采样周期逐渐加长,码值一路爬升,到后面开始不再变化,就说明采样电容充饱了。这个测试方法不需要专业仪器,用串口打印码值就能判断自己的采样周期配置是否合理。

实际配置的时候,我推荐先用本芯片最大的采样时间跑一遍,确认测量正确性和稳定性,然后再根据实际功耗需求逐步缩短采样时间,找到一个“两者兼顾”的平衡点。千万不要一开始就把采样时间调到最短,然后拿滤波去填坑,那是本末倒置。

6.3 常见问题排查小表

现象排查方向解决办法
首次采样值偏小唤醒后稳定时间不足增加100微秒以上的稳定延时,或丢弃首采
码值整体偏低且无法消除采样周期不够加大ADC采样时间,Pin脚加0.1μF采样电容
电池供电时读数时高时低参考电压未实时补偿每次采样同步读VREFINT,用真实VREF算电压
待机电流偏大分压电阻/ADC时钟未关用大电阻分压+采样后关闭ADC时钟/模块
零点偏移严重未做ADC校准执行ResetCalibration和StartCalibration流程
高温低温测量值偏移VREFINT温漂+采样链路温漂按温度区间做两点标定,或接受当前精度范围

6.4 关于4095和4096的执念

网上经常有人争论满量程到底用4095还是4096。其实对这个精度级别的应用来说,用4095还是4096理论上差异不到0.03%,你如果非要在意这个差距,说明你更应该关注的是PCB布板、电源纹波和VREFINT标定精度,而不是这个除数。工程上我统一用4096,因为ADS和代码实现里按2的12次方更自然,而且大部分厂家的校准算法也是按这个量纲做的,少一些纠结。

6.5 单独说一下“首采陷阱”

低功耗唤醒后的第一次转换是最容易踩坑的地方,因为ADC模块和VREFINT需要时间重新上电建立稳定工作状态。我实测过,刚唤醒就触发转换,VREFINT的码值可能比稳定后低几十个LSB,这直接导致补偿结果偏大。解决方式很简单:在状态机里插入稳定延时,或者直接对第一次转换结果做标记并丢弃。我两种方式都试过,最终选择了“稳定延时+丢首采”双保险,效率和可靠性兼顾。

最后的体会

回头来看,PY32F002B这颗芯片并不是不能做好ADC测量,问题是它把参考电压、校准、低功耗这些“高级功能”的决策空间都丢给了开发者。你如果只是照着demo把ADC打开、读到码值就以为测的是真实电压,那后面坑一定躲不掉。我在这颗芯片上跑通VREFINT补偿之后,最大的感受是:低成本的料,反而更需要你对“测量链路”有一个清醒的理解,把每一个误差源都补偿到位,它一样能输出很漂亮的数据。

如果你也在做类似项目,建议先把“每次采样同步读VREFINT”这条原则刻在脑子里。不要嫌多读一个通道麻烦,这一个动作就解决了电池供电最核心的参考电压漂移问题,性价比极高。接下来再去优化采样周期、滤波和睡眠流程,整个低功耗ADC采样系统才能真正做到既省电又准确。

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

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

立即咨询