
做低功耗设备好几年了电压检测电路这块我踩过的坑不算少。最开始做一款一年都未必充一次电的采集终端想着电池电压检测还不简单拿两颗10K电阻一分压直接送MCU的ADC引脚就完事了。结果实测待机电流让我头大整机睡眠电流2µA出头光这个分压电阻就吃掉一两百µA别说一年仨月就能把电池耗空。后来把思路换成了“MOS管门控分压网络”待机电流一下压回3µA以内这才算真正把低功耗电压检测做明白。这篇内容就是围绕这个方案来的用电阻分压先把电池电压降到ADC能接受的范围再用一颗MOS管做电源开关让它只在采样瞬间给分压网络通电其余时间彻底断开。我会把分压计算、器件选型、驱动方式、采样流程和调试中遇到的问题都摊开讲适合正在做电池供电产品、需要控制静态功耗的嵌入式工程师和硬件工程师参考也适合电子DIY玩家了解低功耗检测电路的完整设计套路。1. 整体方案设计先把功耗账算明白1.1 电压检测电路在低功耗设备里的“隐形消耗”很多人设计电池电量检测时第一反应就是“两颗电阻分压接ADC”。这个方案在开发板和普通功耗要求不高的设备里完全没问题但一旦放到需要长期待机、定期唤醒上报的产品里它就成了最大的漏电流来源。举个具体的例子一颗3.7V锂电池用常见的10K10K分压分压网络在整个电池寿命期间只要一直挂在电源上流过的电流就是 3.7V / (10K10K) 185µA。一天24小时算下来是4.44mAh一个月就是133mAh。对一颗1000mAh的电池来说光这个分压电路就把13%的电量白白耗掉了而它实际上只是在“待命”根本没有执行任何功能。就算把阻值提到100K100K只有18.5µA的静态电流一年也会有约162mAh的消耗对微安级待机系统来说依然是个不小的数字。可阻值再往大了加ADC采样误差就会冒出来这就引出下面要说的门控思路。1.2 门控思路把分压电路的“通电”时间压到采样窗口内既然问题出在“分压电路始终通电”自然就想到给它装一个开关需要采样的时候把电接通采样完立即断开。这个开关用普通三极管也能做但低功耗场景下MOS管优势明显——它的导通压降小、关断漏电流极低、驱动也简单。于是方案就变成电池电压通过一颗P-MOS管接到分压电路P-MOS管的开通与关断由MCU的GPIO控制分压输出接到ADC引脚。平时P-MOS完全关断整个分压网络处在断电状态理论上只有MOS管自身的漏电流通常在亚微安级别。每天哪怕采样20次每次通电20ms实际电流持续的时间也才400ms折算成平均功耗几乎可以忽略。这个思路本质上就是“让不必要的电路在不干活的时候彻底断电”比单纯堆高电阻阻值要踏实得多因为它从根源上砍掉了分压网络持续消耗的问题。1.3 两种门控拓扑怎么选P-MOS高端还是N-MOS低端门控开关在电路上有两种放置方式一种是把MOS管放在电池正极和分压电路之间叫高端开关最常用的是P-MOS管另一种是把MOS管放在分压电路下端和地之间叫低端开关最常用的是N-MOS管。低端开关的驱动更简单MCU的GPIO可以直接驱动N-MOS栅极。但有一个坑N-MOS关断时分压点会因为上分压电阻而浮空如果电池电压高于MCU模拟引脚的耐压上限比如电池4.2VMCU的VDDA只有3.3V这个浮空电压可能飘到接近VCC存在损伤ADC引脚的风险。我踩过这个坑表现是采样引脚偶尔读值异常查了半天才发现是关断时节点电压没归零导致的。高端开关就没这个问题。P-MOS管关断后分压网络的供电端被彻底断开分压点会通过下分压电阻自然拉到地电压稳定为0V对ADC引脚非常友好。需要付出的代价是驱动稍微麻烦一点因为P-MOS的导通条件要求栅极电压比源极低一个阈值不能直接用GPIO高电平驱动通常要加一颗小N-MOS做反相。两种拓扑对比如下对比项N-MOS低端开关P-MOS高端开关GPIO驱动复杂度低可直接驱动稍高需要N-MOS反相或特殊接法关断时分压点电压可能悬空若源压高于MCU耐压有风险经下分压电阻拉回0V安全导通阻抗低低应用建议适用于源压不超过模拟域电压的场景适合电池电压高于MCU电压的场景我的选择踩坑后放弃目前主推我做过的低压设备普遍是4.2V电池配3.3V MCU所以最终固定用P-MOS高端开关方案稳定、安全、逻辑清楚。2. 核心电路原理与关键器件选型2.1 电阻分压的计算与阻值选择分压电路的核心就是两个电阻R1上分压和R2下分压输出电压为 Vout VIN × R2 / (R1 R2)。选型时要先看MCU的ADC参考电压是多少再结合电池电压范围反推分压比。以我常用的STM32L151C8T6A为例它的12位ADC参考电压是VDDA我用LDO把VDDA稳定在3.3V所以ADC输入电压不能超过3.3V。电池标称3.7V满电4.2V为了留出余量分压比取0.5也就是 R1R2。这样满电时ADC输入是2.1V低于3.3V完全在安全范围内而ADC分辨率是 3.3V / 4096 ≈ 0.806mV经过0.5的分压比换算到电池端每个LSB对应约1.61mV检测精度足够日常电量判断。阻值怎么选是另一个关键。从功耗角度希望阻值尽量大电流就小但从ADC采样角度源阻抗越大采样建立时间越长误差也越大。不要一上来就选1M级别很多MCU的SAR型ADC对源阻抗非常敏感。STM32在12位精度下官方建议外部源阻抗不要超过十几千欧但我们这里用100K100K等效源阻抗是 R1//R2 50K显然超出建议值。解决手法是给分压节点加一颗采样保持电容。电容在采样瞬间给ADC内部采样电容提供足够电荷相当于一个低阻抗源。我通常加10nF到100nF的X7R电容放在分压节点和地之间。代价是打开P-MOS后需要等待RC充电稳定这个后面在软件流程里会说。2.2 MOS管的选型参数不是随便一颗MOS都行选MOS管做门控很多人只关心导通电阻实际在低功耗电路里更该关心的是关断漏电流和栅极阈值电压。先说关断漏电流。数据手册里一般给的是Idss即VGS0时的漏源电流。常温下好的小信号MOS管通常能到1µA以下有些甚至到几十nA。SOT-23封装的小管子里AO3401、SI2301都是常见选择。注意数据手册给的通常是常温典型值高温下漏电流会明显上升如果产品要过60甚至80度环境这一项要留够余量。再说栅极阈值电压Vgs(th)。做高端开关的P-MOS要保证在电池电压最低时仍然可靠导通。比如电池放电到3.0V如果选了一颗Vgs(th)高达-2.5V的P-MOSVgs实际只有-3.0V导通程度可能不够导致分压网络电压不准。我一般选Vgs(th)在-0.5V到-1.5V左右的型号辅以足够的负压驱动保证任何时候都能完全打开。至于MOS管的米勒效应在这个场景下基本可以忽略因为开关频率太低一天也就几次不涉及高频开关损耗。但如果哪天要把这套电路改造成高速采样那就要重新核算驱动能力了。2.3 驱动电路设计用一颗小N-MOS做反相器P-MOS的高端驱动不能直接把GPIO接上去。GPIO输出高电平3.3V时P-MOS的源极在电池端比如4.2VVgs3.3V-4.2V-0.9V这个电压处在临界区P-MOS可能关不彻底。所以要在中间加一颗N-MOS做反相电路结构是这样的电池正极进来后接P-MOS的源极P-MOS的漏极接分压网络的R1P-MOS的栅极接一个1MΩ上拉电阻上拉电阻另一端接电池正极同时P-MOS栅极接N-MOS2N7002的漏极2N7002的源极接地栅极串一个1KΩ电阻接到MCU的GPIO。这样控制逻辑就非常清晰了GPIO输出低电平时2N7002不导通P-MOS的栅极被1MΩ电阻拉到电池电压Vgs≈0P-MOS关断GPIO输出高电平时2N7002导通把P-MOS栅极拉到接近地Vgs-VBATP-MOS完全导通电池电压接入分压网络。上拉电阻选1MΩ而不是常见的10K是为了把平时流过这部分电路的分流降到最低。2N7002导通时流过1MΩ电阻的电流只有3.7µA而且只在采样期间存在完全可以接受。2.4 整机功耗预算门控电路到底能省多少用实际参数把账算清楚。假设电池3.7V分压电阻R1R2100KΩP-MOS选用AO3401关闭状态漏电流典型值按0.1µA算。功耗项参数平均电流MCU睡眠STOP模式约1.5µA1.5µAP-MOS关断漏电流典型0.1µA0.1µA分压网络非采样期关闭0µA每天采样12次每次20ms18.5µA × 240ms/天约0.05µA其他漏电与LDO静态约1µA1µA整机待机合计—2.7µA左右一年总消耗约 2.7µA × 24 × 365 ≈ 23.7mAh对一颗1000mAh电池来说只占约2.4%。而如果不做门控直接100K100K分压接ADC光分压网络一年就是162mAh占16%以上。门控电路省下来的电量非常可观。3. 电路实操与软件配合3.1 完整连接清单与实物布局这个电路的实物连接并不复杂我在项目里的接法如下电池正极接P-MOS管AO3401的源极。P-MOS管的漏极接R1100KΩ1%的一端。R1的另一端接R2100KΩ1%和采样电容C110nF这个节点就是ADC采样点V_SENSE。R2的另一端接地。C1并联在V_SENSE和地之间。P-MOS管的栅极接1MΩ上拉电阻到电池正极同时接2N7002的漏极。2N7002的源极接地。2N7002的栅极串一个1KΩ电阻接MCU的GPIO比如PA1。V_SENSE节点直接连到MCU的ADC输入引脚。PCB布局上有两点值得注意一是采样电容C1要尽量靠近MCU的ADC引脚避免走线太长被噪声干扰二是整个分压网络和MOS管所在区域下方要保证完整的参考地平面否则采样值容易跳动。如果做两层板至少保证这个区域的地不要被信号线打断。3.2 低功耗采样流程从唤醒到关闭的完整状态机硬件搭好只是第一步软件上的时序配合才是成败关键。低功耗设备通常是这样的流程RTC定时唤醒MCU进入电量检测完成后重新进入睡眠。采样流程的核心是打开P-MOS、等待稳定、采样、关闭P-MOS然后才允许MCU进入低功耗模式。千万不要把打开P-MOS的动作放在进入低功耗前一步那会让分压网络在睡眠期间继续耗电。我当时写的采样函数大致是这个结构#define VBAT_SAMPLE_GPIO_PIN GPIO_PIN_1 #define VBAT_SAMPLE_GPIO_PORT GPIOA #define VBAT_DIV_RATIO 0.5f #define ADC_VREF 3.3f #define ADC_RESOLUTION (4096.0f) float read_battery_voltage(void) { uint32_t sum 0; uint32_t avg_code; // 1. 打开P-MOSPA1输出高电平2N7002导通P-MOS栅极拉低分压网络通电 HAL_GPIO_WritePin(VBAT_SAMPLE_GPIO_PORT, VBAT_SAMPLE_GPIO_PIN, GPIO_PIN_SET); // 2. 等待分压网络和采样电容稳定10nF电容配50K等效源阻抗稳定时间约3.5ms delay_ms(20); // 3. 连续采样8次提高可靠性 for (uint8_t i 0; i 8; i) { HAL_ADC_Start(hadc); if (HAL_ADC_PollForConversion(hadc, 100) HAL_OK) { sum HAL_ADC_GetValue(hadc); } HAL_ADC_Stop(hadc); } avg_code sum / 8; // 4. 关闭P-MOSPA1输出低电平2N7002断开P-MOS栅极被上拉到电池电压分压网络断电 HAL_GPIO_WritePin(VBAT_SAMPLE_GPIO_PORT, VBAT_SAMPLE_GPIO_PIN, GPIO_PIN_RESET); // 5. 换算电池电压 float vbat (float)avg_code * ADC_VREF / ADC_RESOLUTION / VBAT_DIV_RATIO; return vbat; }注意第5步的计算用的是VDDA3.3V作为参考电压。这个前提是你把MCU的VDDA接到了稳定的LDO输出上。如果MCU直接用电池供电或者VDDA会随负载波动一定要加一步内部基准校准否则换算会不准。3.3 采样时机与延时设置等电压稳定再动手打开P-MOS之后不能马上读数这是新手最容易犯的错。为什么因为采样电容C1和分压电阻构成了RC充电网络等效源阻抗是R1//R2 50KΩC1是10nF时时间常数约0.5ms但要让电压稳定到0.1%以内需要大约7个时间常数也就是3.5ms。如果你把C1加到了100nF时间常数就是5ms稳定时间需要约35ms。所以延时20ms在10nF场景下够用但用100nF时就要加大延时。我一般根据C1大小动态调整原则是稳定时间 7 × (R1//R2) × C1再额外留20%余量。另外ADC自身的采样时间也要配置得当。源阻抗高的情况下ADC内部采样电容在极短时间完成充电如果采样时间太短采样值会偏小。在STM32的ADC配置里我把采样时间设到最大档如239.5周期配合外部的10nF电容读数才稳定下来。3.4 多通道与多次采样别让一次读数决定命运电池电压检测经常会受到瞬时负载影响比如系统刚发完无线数据瞬间拉低了电池电压这时的采样值不能反映真实电量。我的做法是在采样时先让系统进入相对稳定的状态关闭无关外设然后连续采样多组去掉最大值和最小值剩下的取平均。这样能滤掉偶发的毛刺。更稳妥的方案是把采样分散到几次唤醒周期里第一次唤醒采一组第二次唤醒再采一组连续几次后做一个滑动平均。尤其对电池内阻较大的设备负载瞬间产生的压降会让单次采样值偏低通过多次采样取平均可以有效缓解。另外还要注意MCU的ADC通道配置。分压点V_SENSE连到的GPIO要设置为模拟输入模式不要保留数字输入特性否则引脚内部的上拉或下拉电阻会和分压电阻形成额外分压导致读数系统性的偏差。这一点容易忽略但影响挺大。4. 常见问题与排查技巧实录4.1 分压点电压飘到VCC导致ADC异常开头提到过如果用N-MOS做低端开关MOS关断时分压节点会通过上分压电阻浮空。如果此时MCU的模拟输入引脚没有有效的下拉路径节点电压可能飘到接近电池电压一旦超出了VDDA0.3V轻则读数异常重则损伤模拟引脚。我在这里踩过坑MCU的VDDA是3.3V电池满电4.2V用N-MOS低端开关时某次上电后ADC引脚读值乱跳检测才发现是关断状态下节点电压接近4V。从那以后我统一改用P-MOS高端开关方案彻底规避这个问题。如果你项目里必须用低端开关至少要在分压节点和地之间加一个大阻值下拉电阻比如1MΩ把浮空电压拉低同时注意这个电阻会和下分压电阻并联影响分压比要提前计入计算。4.2 采样值偏大或偏小源阻抗过高导致的ADC丢码低功耗设计里有个惯性思维分压电阻越大越好。但电阻太大ADC输入端的高源阻抗会造成采样保持电容充不满典型表现是采样值系统性地比理论值偏低而且随着温度变化波动明显。排查这类问题可以先用万用表实测分压节点电压再对比MCU读回来的数值。如果实测是1.65VADC读回来只有1.55V大概率就是源阻抗问题。解决办法不是盲目降低电阻而是按前面说的增加采样保持电容并且延长ADC采样时间或者换用输入阻抗更高的ADC前端。我实测在100K100K分压、10nF电容、最大采样时间档位的组合下读数和实测值误差能控制在0.2%以内。4.3 待机电流没有想象中低排查漏电路径有朋友照着这个电路做了板子回来说待机电流还是偏高有30多µA。我让他按步骤排查最后发现问题出在两处一是P-MOS栅极的上拉电阻用了10K而这个上拉电阻并非常年有电流不对等等——上拉电阻只在2N7002导通时才会形成对地电流待机时2N7002关断上拉电阻不耗电。真正的元凶其实是分压节点没有断开干净他在PCB上把R1和R2之间的走线底下铺了一块铜但铺铜网络有问题导致漏电。PCB漏电在低功耗电路里是个隐形杀手。助焊剂残留、潮湿环境、走线间距过小都会产生微安级漏电。处理办法是打样回来后先用洗板水或酒精彻底清洗板面再涂一层三防漆。如果还能测到异样漏电可以把MOS管和分压电阻拆掉分段测电流很快就能定位是哪一段的问题。现象可能原因排查方向待机电流偏高数十µA分压网络未断电、PCB漏电测P-MOS漏极对地电流清洗板面采样值偏低ADC源阻抗过高增大采样时间、加采样电容采样值跳变采样节点悬空、地线空泡检查关断时节点电压、补强地线温度升高功耗剧增MOS管关断漏电流上升更换Idss更小的型号、降环境温度4.4 温度漂移普通电阻的误差累积分压电阻的精度直接决定检测准确性。普通贴片电阻的温度系数大约在±100ppm/°C如果R1和R2的温漂方向不一致分压比会随温度漂移。假设60°C温差下两颗电阻各漂移0.6%分压比可能偏移1%左右反映到4.2V的电池电压上是约42mV用于电量判断还能接受但要是用来做精准电压保护就不够了。要追求更高精度就用低温漂的薄膜电阻比如25ppm或更低同时尽量选同批次电阻让它们的温漂方向一致。如果产品的电压阈值判断比较苛刻还可以在生产时做一次分压比校准把每台设备的实际分压比写进Flash在软件里修正。我当时做的那台记录仪就留了这个校准点后面批量一致性省了不少心。另外一个细节采样电容的材质尽量选C0G或X7R别用高容量的Y5V那种电容随温度和直流偏置变化能掉一半容量虽然不会直接影响分压比但会改变RC稳定时间极端情况下采样还没稳定就读数了。写在最后做低功耗电压检测核心不是在某个环节做到极致而是把“耗电时间”尽可能压缩。MOS管门控分压网络这个方案我用在STM32L151和国产HC32L196的低功耗产品上实测效果稳定。经验是不要追求极端的超大分压电阻常规100K级别配合采样电容比盲目加到1M级更可靠如果ADC参考电压随电池波动一定要做内部基准校准否则检测结果没有意义还有就是养成习惯每次打样回来先测整机待机电流再逐段排查很多静态电流问题都是板面清洁和走线引起的。最后再分享一个小技巧调试时用带波形显示的低功耗电流分析仪去观察MCU从唤醒到采样的电流曲线能清楚看到采样期间的电流尖峰和关断后的回落。如果你看到某个时间段电流没有回落到基线说明你的门控电路没有真正关断这时候顺着电路往下查通常十分钟就能定位问题。