资讯动态

STM32L4与PCA9422 PMIC协同的电池供电低功耗电源管理设计实践

发布时间:2026/10/24 4:57:50 来源:尧图企业网站定制
我用一块电池容量只有400mAh的小板子塞了主控、彩屏和低功耗蓝牙模块主控选了STM32L4S5ZI电源部分一开始想省事直接用MCU内部的LDO。结果一测待机电流和动态功耗问题接踵而至——这才把PCA9422这颗专用PMIC加进来。做完之后我的体会是完整电源管理这件事得把PMIC和MCU当成一个整体来设计PCA9422管充电、多路输出和监测STM32L4S5ZI管业务逻辑和低功耗策略两边的I2C、中断和复位信号配合得当整块板子的电源才能真正“闭合”。这篇文章就按我实际调板子的顺序讲从为什么不用MCU内部稳压器到硬件连接、寄存器配置、充电与ADC采集再到低功耗配合和调试踩坑。适合正在做电池供电便携设备、可穿戴原型或者想把手上的STM32低功耗项目与独立PMIC结合起来的开发者。1. 为什么不是仅用MCU内部稳压器整机供电设计的分工逻辑很多人在低功耗项目里第一个念头是用MCU自带LDO觉得能省一颗芯片。但把系统当成一个整体看MCU内部稳压器只能解决“内核逻辑电源”的转换问题解决不了电池充电、外设多轨供电、动态关断和实时监测。PCA9422和STM32L4S5ZI的关系更像“电站调度中心”电站负责把电池和USB输入变成多路稳定电压并承担充电保护调度中心负责决定哪一路输出需要开启、什么时候降功率、出异常时怎么处理。1.1 PMIC存在的意义多路电源轨的集中调度STM32L4S5ZI本身可以在一定电压范围内工作但它不会凭空变出传感器需要的1.8V模拟电源、无线模组需要的2.5V/3.0V也不会在你插入USB时自动切换供电路径并给锂电池充电。如果全部用分立元件搭需要单独选充电管理芯片、负载开关、LDO、电压监控复位电路PCB面积和故障点都会增加。PCA9422这一类小型PMIC把“充电功率路径多路输出ADC监测保护”集成在一起。实际项目中电源管理不再是我要在PCB上摆一堆芯片而是通过I2C寄存器去控制它让某一轨输出开启、关闭或者改变电压。整机功耗的可控性主要来自这些轨道的独立开关。1.2 PCA9422在系统中的前后端关系电池、USB、负载三个方向从系统的角度去看PCA9422处于三个方向的交汇点输入方向电池VBAT和USB VBUS输入芯片内部完成充电路径和系统功率路径选择。输出方向为MCU、传感器、显示模组等提供多路低压轨不同的轨可以独立使能。控制方向MCU通过I2C配置输出、读取状态、响应中断PMIC回传电池电压、充电状态、温度告警等信息。这样设计最大的好处是MCU在进入深度睡眠前可以通过I2C显式关闭非必要的外设轨而不是靠外设自己在睡眠模式下继续从电源轨偷电流。独立轨道的关断比让MCU内部的低功耗外设模块逐一切断要干净得多。1.3 什么情况下该用外置PMIC什么情况下不必不是所有项目都需要加入专用PMIC。固定5V适配器供电、没有电池、没有多电压域的设备MCU内部LDO做一个简单系统就够。但以下场景外置PMIC几乎绕不开电池供电且需要充电管理有多个电压域需要独立开关要求动态调整输出电压比如在MCU和外设状态变化时切换电压等级需要实时监测电池电压和充电电流而不是用MCU的ADC加一堆电阻分压。我建议做一个简单评估把系统里每一个电源域的电压、最大电流、是否需要在睡眠时关断列成一张表如果超过一路固定输入PMIC方案通常比分立方案省心。2. 最小系统与硬件连接五类信号线的设计细节从硬件上把STM32L4S5ZI和PCA9422连起来不只是“I2C两根线连上就能用”。我会把连接分成五类电源轨、I2C、中断、复位、检测与使能每一类都有自己的设计要点。2.1 电源树和地平面先别急着画PCB先把电源树画清楚。我的验证板上采用三路输出分配电源轨典型电压负载对象说明核心轨3.3VMCU主电源、数字逻辑常开低功耗时也要保持模拟轨1.8V传感器、模拟前端可关断进入STOP2前关闭外设轨2.5V~3.0V无线模组、屏幕驱动可关断仅在需要时开启PCB布局上需要注意开关节点和电感走线。PMIC的开关节点通常是高频方波尽量短而宽远离I2C和模拟信号线。地平面要完整不要把电池负极直接用一个细走线绕半圈连接到PMIC地这样充电和瞬时大电流会产生地弹影响ADC采样精度和复位信号。输入和输出电容不能省具体容值按数据手册给的范围取中间值偏大的那一端。电池输入侧我习惯并上10µF陶瓷电容加一个小的100nF高频电容输出侧每路至少4.7µF动态切换电压时不容易出毛刺。2.2 I2C与中断信号总线地址、上拉电阻和nINT接线PCA9422通过I2C与STM32L4S5ZI通信这是控制平面。接线本身很简单SCL、SDA、GND三根加上VDDIO电平匹配。STM32L4S5ZI的I2C引脚可以配置为开漏上拉电阻接到PMIC对应IO电平域而不是直接接到3.3V就算完。总线上拉电阻的选择不要照抄参考设计。I2C速度在400kbps以下时常见上拉在2.2k到4.7k之间具体要看总线上设备数量和走线长度。如果上拉太弱上升沿会很缓PMIC在高频通讯下可能出现偶发的NACK上拉太强总线驱动能力不够也会拉不下去。最好的验证方法是示波器看上升沿通常要求上升时间不超过时钟周期的30%。我这边用4.7k上拉400kbps下工作稳定如果总线上再加其他设备可能要考虑改成2.2k。中断信号nINT要单独说。PMIC的nINT通常低电平有效把它接到STM32L4S5ZI一个支持外部中断的GPIO上比如PA0配置为下降沿触发。不要把它和其他中断输出直接并联不同芯片的中断输出极性、脉冲宽度可能不同并联容易互相干扰。即便PMIC的中断引脚标称开漏也建议单独给一个合适上拉避免使用内部弱上拉。2.3 复位、使能与检测引脚容易被忽略的时序点复位引脚是很多人的坑。PMIC产生的上电复位信号如果直接接到STM32L4S5ZI的NRST要确认复位电压阈值和时序是否满足MCU要求。特别是在USB热插拔、电池低压瞬间复位信号可能因为电源毛刺产生多次抖动导致MCU反复重启。我的建议是采用专门的复位方案例如用外部复位IC或者至少增加RC滤波让复位信号在电源稳定后再解除。PMIC的软复位命令也可以用于调试阶段但不要依赖它来解决硬件复位毛刺。检测引脚比如NTC、VBUS检测要根据实际结构设计。NTC热敏电阻通常接在电池Pack里走线要尽量短避免引入太多接触电阻。VBUS检测如果由PMIC完成MCU只需要读它的状态寄存器就行不需要再自己加VBUS分压电路。3. I2C寄存器配置上电时序与输出轨电压的落地写法硬件连好后最先要做的是让PMIC在I2C总线上“听招呼”。我一般先把寄存器规划分成四组控制类、输出设置类、状态类、中断类。实际芯片的寄存器命名可能和下面写的不同开发时以官方手册和驱动头文件为准。3.1 从手册里先圈出四组寄存器控制、电压、状态、中断控制类寄存器负责软件复位、使能、工作模式切换。输出设置类负责每路输出电压和限流。状态类包括电源路径状态、充电状态、NTC温度状态。中断类用来屏蔽和读取事件标志比如VBUS插入、充电完成、电压跌路。拿到数据手册后我的做法是先画一张寄存器地图把每个寄存器的默认值抄下来特别注意默认是关断还是开启。很多PMIC出厂输出默认是禁用的直接上电不会输出必须通过I2C“点一把火”才工作。这和MCU的默认状态配合起来如果一开始没配置好可能表现为“板子上了电MCU却没程序跑”容易误判为硬件问题。3.2 初始化顺序先充电使能还是先输出电压初始化顺序比寄存器数值更容易忽略。我使用的顺序是确认I2C通信读取PMIC芯片ID或版本寄存器如果读不到检查供电和地址。软复位把PMIC恢复到默认状态避免上一次配置残留。延时等待内部电源稳定至少几毫秒。配置输出轨先使能核心轨并设置到目标电压等待电压稳定。配置充电参数设置充电电流、终止电流、NTC阈值。清除所有中断标志然后使能需要用到的中断。顺序背后的逻辑是MCU需要先有稳定的主电源才能跑后续代码所以核心轨必须先上充电参数放到最后是因为充电时大电流变化可能影响整机电源波动最好在系统基本稳定后再启动。如果MCU一上电就要从PMIC读取电池电压输出轨的稳定时间要格外留够。3.3 动态改电压的现实问题斜坡时间与被供电系统的稳定性动态调压的逻辑很简单改寄存器里的目标电压值就行但现实中有两个考虑点。一个是斜坡时间PMIC内部的DAC切换输出电压需要时间如果被供电的外设对电压上升速度敏感比如有些传感器在供电瞬间会有一个浪涌电流就要在软件里控制“写寄存器后延时等待”而不是连续写好几个寄存器。另一个是被供电系统在电压切换过程中的中间态比如某外设允许2.7V到3.6V从2.8V往3.3V切中间短暂停留在2.9V、3.0V此时如果外设正在执行写Flash操作会有风险。所以动态调压之前要通知业务层等外设进入空闲态再切换。/* 伪代码示意动态调整某输出轨电压的流程 */ static void pmic_set_vout_channel(uint8_t ch, uint16_t mv) { pmic_write_vset(ch, mv); // 写入目标电压 HAL_Delay(5); // 等待DAC斜坡完成 pmic_read_status(ch); // 读回输出状态确认稳定 }每次读完状态寄存器确认输出达到目标后再继续执行下一步。这个“确认”步骤看起来多余但能避免进入低功耗后发现某个外设轨电压还没建立。4. 充电管理与ADC数据采集从电池电压到电量估算电源管理不只是供电还有一个大头是电池充电和电量计算。这一部分如果只是在MCU的ADC引脚上挂个分压电阻会同时遇到功耗、精度和响应速度三个问题PMIC内置ADC可以更干净地解决。4.1 充电过程的四个阶段和状态判断锂电池充电通常分为预充、恒流充电、恒压充电和终止判断。电池电压很低时PMIC会用小电流预充上升到安全电压后再切换到设定的恒流充电电流电压接近满充电压后进入恒压阶段电流逐渐下降下降到终止电流阈值后停止充电。这个过程中MCU需要读PMIC充电状态来更新UI或记录日志。不要根据“充电电流是不是0”来判断充满很多PMIC在恒压阶段尾部电流已经很微弱ADC本身有噪声阈值判断会有偏差。用PMIC的充电状态位判断更可靠如果只有电流寄存器做迟滞比较终止电流阈值设成比手册建议高一点避免反复进入和退出充饱状态。充电电流的设置我按电池容量0.5C左右来配置。比如300mAh电池设150mA充电电流如果设备在高温环境使用还要看NTC阈值是否在允许充电的温度窗口内。小型PMIC的充电电流上限受封装热阻限制不要为了“充满快点”把电流往上限顶发热会让电池加速老化温度过高时PMIC会主动降流甚至停止充电。4.2 ADC转换与平均滤波不要直接把寄存器原始值当电压PMIC内部ADC会把电池电压、输入电压、充电电流等转换成一个数字值。直接拿原始值除以满量程再乘以基准电压通常会得到“有偏差但对得上大概”的结果但不够好。原因内部基准存在器件间偏差电池分压网络本身有误差ADC采样瞬间可能叠加电源纹波。我的做法是每次连续采8个值去掉最大最小剩下6个取平均。然后做一点校准在电池电压已知且系统静止时比如万用表读数为3.60V用ADC读数反推偏移量写入驱动的偏移参数。简单的一阶校准整个电压读数就能稳定到0.05V内的误差对绝大多数穿戴设备足够用了。读取时机也有讲究。不要在充电大电流期间读取电池电压用于SOC估算这时候电池内阻上的压降会让电压读数偏高或偏低。如果PMIC支持同时读取电流可以算实时的近似内阻再做动态补偿没有的话至少等充电进入恒压阶段再更新SOC表。4.3 电量估算没有库仑计时的电压查表法如果硬件上没有库仑计最简单的估算方法是“静止电压查表法”。充电结束或长时间待机后电池电压趋于稳定这时查OCV-SOC曲线能得到一个比较可信的电量。运行状态下电压会有负载波动查表结果参考价值有限。我会在低功耗设备里这样处理系统保持运行时电量通过充放电电流积分估算每次从深度睡眠醒来的头两个ADC读数专门用来校正OCV查表值。这样不会出现“跑着跑着电量从70%跳到40%”的突兀变化也不会在带电状态下因为负载变化频繁跳变。NTC温度数据除了用于充电保护也可以用来修正SOC查表结果。低温环境下锂电池放电平台会偏移同一个电压对应的实际电量更低查表前如果发现温度低于10度要给SOC加一个负偏移修正具体修正系数需要自己实测拟合。5. 低功耗协同PMIC动态输出与STM32睡眠模式的配合STM32L4S5ZI在低功耗方面本身能力很强有多个STOP模式甚至Standby模式但真正把系统功耗做下来需要MCU和PMIC一起协同。很多项目的问题是MCU睡得很好外设却被电源轨一直供电整体功耗降不下去。5.1 STM32L4S5ZI的内部调压器模式SMPS模式与前级电源的关系首先得区分清楚STM32L4S5ZI内部可以选择两种调压方案一种是普通LDO模式一种是SMPS模式开关电源模式。SMPS模式需要外加一颗电感好处是整体转换效率更高尤其当VDD电压较低时对电池供电设备很有价值。SMPS模式节省的电流主要体现在运行态MCU长时间处于Active状态时能看到明显收益。但代价是电感会带来开关噪声和一点点PCB面积同时布局要求更高。我自己的选择是如果系统大部分时间在睡眠运行时间很短LDO模式就够如果系统要经常处理传感器数据和刷新屏幕比如30%以上时间在运行SMPS模式值得用。PMIC为MCU VDD供电时要确保电压稳定在MCU允许范围内。动态改变PMIC为MCU供电的那一路电压需要非常谨慎因为MCU的IO电平、复位阈值、内部Flash操作都与VDD相关我通常让这一路电压固定把动态控制留给外设轨。5.2 PMIC与MCU的低功耗握手进入睡眠前先降压和关轨进入低功耗的正确顺序不是直接执行WFI指令而是先让PMIC知道系统要睡了。我会在进STOP2之前做这几件事通知业务层停止对外设寄存器的访问通过I2C关闭模拟轨和外设轨保留核心轨延时几毫秒等待输出电容放电到低电平避免外设掉电瞬间产生不可预期的状态配置唤醒源EXTI、RTC等执行WFI。唤醒后的顺序反过来先恢复核心工作状态再使能外设轨每使能一路都等待电压稳定并读回状态全部稳了之后才恢复外设初始化。不要小看关轨之后的延时有些传感器在电源跌落时会输出一个异常中断如果不等待电容放完电MCU刚进睡眠就被异常中断唤醒形成“电流黑洞”。伪代码示意static void system_enter_stop(void) { sensor_power_off(); pmic_disable_channel(CH_SENSOR); pmic_disable_channel(CH_RF); HAL_Delay(10); // 等待电容放电 exti_enable_wakeup(); HAL_PWR_EnterSTOPMode(...); }实测中这种“先关轨再睡”的方式能让睡眠电流少一个量级而如果直接把PMIC外设轨留在常开状态MCU睡得多沉都没用。5.3 中断唤醒链路nINT作为外部事件的触发通道低功耗模式下MCU不可能一直通过I2C轮询PMIC状态轮询本身就会耗电和增加唤醒次数。正确做法是让PMIC在真正有事件的时候去主动唤起MCU。比如VBUS插入事件PMIC检测到USB接入后nINT拉低STM32的EXTI检测到下降沿唤醒MCU再去读取PMIC中断状态寄存器判断是什么事件做相应处理。这个链路的好处是MCU绝大部分时间保持在STOP只有在充电器插入、拔除、充电完成、温度异常等“有必要处理”的时候才醒来。中断处理的一条经验唤醒后先读状态寄存器再清中断标志。不要在中断回调里直接进行耗时的I2C读写和业务处理把事件记录下来回到主循环慢慢处理。PMIC中断标志如果不清除nINT会一直保持低电平即使MCU再睡也会立刻被唤醒。清标志后确认总线通信正常再重新进入睡眠。6. 调试中的三起典型故障复位毛刺、I2C挂死与NTC偏差这部分内容是我实际调板踩过的坑不一定每个项目都一样但排查思路可以复用。如果你也在做PMCMCU系统建议把示波器探头同时放在PMIC输入、核心输出和复位脚上很多问题一眼就能定位。6.1 复位脚毛刺与MCU重启循环现象是MCU在USB热插拔瞬间重启程序跑到一半就跳回复位向量。示波器抓复位脚会发现VBUS插入的几十毫秒内NRST上出现一串抖动。原因是PMIC的系统功率路径切换时输入电压先跌落又恢复复位引脚正好在上拉和滤波电容的临界点上把电源毛刺变成了复位脉冲。解决方法是把复位信号和电源路径解耦。我在NRST上增加RC滤波同时用延时器件的复位IC替换直接连接确保复位解除时间晚于电源稳定时间。这类问题不会每次都出现但一旦出现在量产设备中非常难查建议早早在设计阶段就重视复位链路的滤波和阈值。6.2 I2C总线挂死PMIC瞬间掉电时把SDA拉低另一种现象是I2C总线在某个错误时序后死锁SDA长时间为低MCU的程序卡在I2C等待寄存器标志上。原因是PMIC在输入电压跌落到阈值以下时内部逻辑状态不确定恰好把SDA输出为低电平而I2C总线上没有设备能主动释放总线进入死亡状态。处理方法分两级。第一级是软件恢复I2C从机状态用GPIO模拟SCL连续发送9个以上时钟脉冲让总线上的从机状态机复位然后再初始化I2C外设。第二级是从根源避免当检测到PMIC中断出现过压或输入跌落事件时先读取PMIC状态必要时执行PMIC软复位而不是直接访问I2C总线避免在PMIC“半清醒”时通信。/* I2C总线恢复用GPIO模拟SCL发送9个脉冲 */ static void i2c_bus_recovery(void) { gpio_scl_output(); for (int i 0; i 9; i) { gpio_scl_set(0); delay_us(5); gpio_scl_set(1); delay_us(5); } i2c_reinit(); }6.3 NTC温度读数偏移分压电阻、接触电阻与两点标定充电时NTC温度读数比实际偏高导致PMIC在夏天接近充电截止温度时频繁降流。一开始怀疑PMIC坏了后来测量才发现问题出在两个地方一是NTC引线接插座的接触电阻有0.2到0.5欧姆分压被抬高二是NTC旁边还有一颗大电流走线PCB热传导把热量带给了热敏电阻。解决方法是调整PCB布局把NTC远离充电功率管和高频电感同时用两端不同的温度点比如冰水混合0度和50度温水做两点标定。标定后把偏移量补偿进MCU读取的温度换算公式里。如果你的系统有电池仓不要把NTC贴在电池中部贴在靠近电池负极的位置更能反映电池实际温度因为负极不易被充电电流加热的局部热点干扰。这三点故障都有一个共同特征问题不是出在“某个功能不好用”而是出在“不同功能交接的边界上”。电源管理系统的复杂处也正在于此单看PMIC手册和单看MCU手册都足够清楚把两者结合在一起之后边界上的时序、电平、中断配合才决定最终能否稳定工作。如果你的验证板也出现类似“偶发重启”“I2C卡死”“充电电流异常”的问题优先怀疑这些边界信号方向大概率没错。

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

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

免费获取报价 →
↑