用PCA9422 PMIC接管多路供电:MK24低功耗电源设计实战记录

发布时间:2026/10/24 5:06:53
用PCA9422 PMIC接管多路供电:MK24低功耗电源设计实战记录

样机第一次整机点亮的时候,我最担心的不是MCU跑不跑得起来,而是电池电压从4.2V掉到3.0V的过程中,三路输出电压会不会出问题。这台便携记录仪的主控用了MK24FN1M0VDC12,电源管理部分则交给了PCA9422这颗PMIC。整套电源链路从选型、画板到低功耗验证,前后折腾了三个多月,踩过的坑比预想多不少。

这篇就把整个过程整理出来。核心是想说明一件事:如何用PCA9422接管多路供电、可调电压和上电时序,让MK24FN1M0VDC12专注于业务逻辑和低功耗策略。内容适合手上正在用Kinetis系列、或者正在评估PMIC方案的工程师;如果你完全没碰过PMIC,也能从硬件接线和初始化代码入手,把它当成一份带踩坑注解的工程记录来看。

1. 为什么最后选定"PMIC + 大容量M4"而不是分立电源方案

1.1 先把需求讲清楚:三个电压域加一个睡眠预算

这台设备是户外用的数据采集记录仪,锂电池供电,要求待机时间按月算。拆开需求之后发现电源侧其实有三个电压域要照顾:3.3V给MK24和传感器、存储卡供电;1.8V给模拟前端和ADC基准供电,这个域要求纹波和噪声都低一点;还有一路0.9V到1.3V可调的电源,专门给低功耗无线模组供电,这样在模组不发射的时候可以把电压压下来省电。

关键指标是整板深度睡眠电流要小于50µA。这个数字一旦写进需求说明书,电源架构就基本被锁死了——不能指望MCU自己靠内部LDO扛,也不能用一堆静态电流几百微安的分立LDO堆电压域。多电压域加上睡眠预算,这两条约束合在一起,就是我最后选择PMIC的直接原因。

1.2 分立方案差在哪里:静态功耗和上电时序两笔账

很多同行第一反应是用一颗DCDC出3.3V,再用一两颗低压差LDO出1.8V和1.0V,理由是BOM便宜、方案熟。这个思路在产品对功耗不敏感时完全成立,但放到这个项目里,问题就出来了。

首先是静态功耗。LDO在空载的时候也有不小的静态电流,一颗几十微安的LDO看着不多,三颗加在一起就把整机睡眠预算吃掉一大半。其次是效率。1.8V从3.7V电池降压,LDO的效率只有一半左右,而电池电压越低,这一路的效率越难看,本来就没多少电量的系统经不起这样浪费。

更麻烦的是上电时序。三路电压假如没有先后顺序,上电瞬间可能出现主控已经释放复位、外设供电还没到位的情况,尤其是有模组和存储卡这类对时序敏感的设备时,偶尔会出现启动失败。分立方案只能靠RC延时或者专门的时序芯片去凑,时序精度差,改起来也费劲。把这些账算完,我基本确定要换集成方案。

1.3 PCA9422与MK24FN1M0VDC12到底谁干谁的活

这颗PMIC的核心价值是功率变换和系统保护,它把电池电压转成多路稳定输出,内部带有过压、过流、欠压保护,输出状态可以通过I2C实时配置。MCU这边不负责具体的功率变换,只负责决策:根据当前业务状态决定各路电压目标、睡眠还是唤醒,然后通过I2C把指令发给PMIC。

MK24FN1M0VDC12作为主控,Cortex-M4F内核跑到120MHz,1MB Flash和256KB SRAM充足,把电源管理协议栈和应用逻辑放在一颗芯片里毫无压力。我尤其看中的是Kinetis的低功耗模式非常丰富,从STOP、VLPS一直到LLS都有,后面配PMIC的DVS动态电压调节时,能组合出很灵活的状态机。核心分工就一句话:PMIC管电,MCU管策略。

2. 硬件端的电源域规划与关键连接

2.1 一棵电源树

画原理图之前,我先把整个系统的电源树列成表,每一路接到哪个BUCK、目标电压多少、负载是谁都要写清楚。这样后面调低功耗时,每一路电流是哪来的,一眼就能查到。

电源域目标电压主要负载来源
VIN_BAT2.8~4.2VPMIC输入锂电池加保护电路
3V3_MAIN3.3VMK24的VDD、传感器、存储卡BUCK1
1V8_ANA1.8V模拟前端、ADC基准BUCK2
1V0_RF0.9~1.3V可调无线模组BUCK3,支持DVS

这里有两个细节值得说。MK24本身工作电压范围是1.71V到3.6V,所以3.3V主域直接供电没有问题,不用再单独给内核做一路电源,省了不少事。另外模拟域的1.8V我特意和数字域分开,如果这颗PMIC某一路输出带LDO,我会把模拟域挂在LDO后面做二次稳压,效果比直接吃BUCK纹波好得多。

2.2 PCA9422与MK24之间的接线细节

PCA9422挂在MK24的I2C0接口上,SCL和SDA两个引脚各接一颗4.7kΩ上拉到3V3。为什么用4.7k而不是常见的10kΩ?因为我计划跑400kHz的I2C时钟,总线上的器件虽然只有两颗,但加上IC引脚电容和走线寄生电容,10kΩ上拉在400kHz下上升沿会很勉强,这点在第5节的实际调试里得到了验证。

除了I2C还有三根控制线要接:INT是PMIC的故障中断输出,低电平有效,我接到MK24的一个GPIO并配置成下降沿中断,这样PMIC一旦报过压、欠压或者过温,MCU能第一时间得到通知;EN是全局使能引脚,用另一个GPIO控制,可以在必要时强制PMIC关断;另外我预留了VSEL对应的GPIO引脚,用于快速切换DVS电压点。接线逻辑很简单:数据通路走I2C,紧急事件走INT,开关决策走EN和VSEL。

这里提醒一下,PMIC侧的I2C引脚供电决定逻辑电平阈值,接法和上拉网络必须和它的IO电源电压对齐,千万不要想当然全部拉到3.3V,先去手册里确认IO域供电范围再画网络。

2.3 PCB布局里被验证有效的几个措施

这部分经验是花了两版PCB换回来的。第一版我图省事,把PMIC摆得离MCU很远,I2C走了十几厘米的蛇形线,结果调试阶段问题不断,后面才把布局重新梳理。

归纳起来四条,直接照做就能少走弯路。第一,输入引脚位置的10µF和100nF电容必须紧贴芯片摆放,大电容负责储能,小电容负责滤高频;每路输出的陶瓷电容也要按数据手册要求的容值放到位,我后来踩的电压跌落坑就和这里偷懒直接相关。第二,I2C走线必须远离电感和开关节点,这两根线最容易被DC-DC的开关噪声耦合,哪怕只耦合出几百毫伏的毛刺,都可能造成通信错误。第三,整块板子底层尽量完整铺铜,电源回路的地要用过孔缝合起来,开关电源的环路面积越小,辐射和纹波越好。第四,如果打算测量整机电流,最好在原理图阶段就在主电源回路上预留串阻焊盘,别像我一样后面飞线改板。

3. 初始化配置:上电时序与寄存器操作

3.1 先解决"MCU怎么活过来"的问题

用I2C配置PMIC容易让人忽略一个前提:系统刚上电时PMIC还没被配置,它凭什么能先把MCU供起来?答案在于PMIC内部有默认上电状态,芯片出厂自带一套安全的初始电压,上电后各通道会按固定时序打开,MCU依靠这些默认电压先完成启动,再由固件通过I2C把电压逐步调整到目标值。

这个机制带来的教训是:第一次拿到板子,不要急着跑代码,先把PMIC每一路输出的默认电压用万用表量一遍,对照数据手册上的默认寄存器表记录下来。我身边就有同事默认电压和预期差了一大截,MCU上电后反复复位,折腾了半天才发现是PMIC还没被配置时输出的电压把系统卡住了。此外还要留意PMIC有没有可配置的地址引脚,如果I2C总线上还有其他器件,地址冲突的问题必须在画板前规避掉。

3.2 初始化代码骨架与寄存器映射

初始化流程我分成五步:读ID确认器件在线,配置各路输出电压,设定DVS电压点,使能对应输出通道,最后读回状态寄存器校验。下面是MK24侧I2C初始化的简化代码,Kinetis的I2C外设配置方式基本一致,引脚复用要对着你用的封装查表确认。

void i2c0_init(void) { SIM->SCGC4 |= SIM_SCGC4_I2C0_MASK; // 打开I2C0时钟 PORTB->PCR[2] = PORT_PCR_MUX(2); // PB2 做 I2C0_SCL PORTB->PCR[3] = PORT_PCR_MUX(2); // PB3 做 I2C0_SDA I2C0->C1 = 0; // 先禁模块 I2C0->F = I2C_F_MULT(2) | I2C_F_ICR(0x12); // 初始 100kHz I2C0->C1 = I2C_C1_IICEN_MASK; // 使能模块 }

再写一个寄存器写操作。Kinetis的I2C是硬件主模式,发送过程就是往数据寄存器里填地址、寄存器号和值,每步等ACK标志位置位即可。

#define PCA9422_ADDR 0x32 // 示例地址,实际以手册为准 uint8_t pca9422_write_reg(uint8_t reg, uint8_t value) { while (I2C0->S & I2C_S_BUSY_MASK); // 等总线空闲 I2C0->C1 |= I2C_C1_TX_MASK; // 进入发送模式 I2C0->C1 |= I2C_C1_MST_MASK; // 产生起始位 I2C0->D = (PCA9422_ADDR << 1) | 0; // 器件地址+写 if (!wait_ack()) return 1; I2C0->D = reg; // 寄存器地址 if (!wait_ack()) return 1; I2C0->D = value; // 写入数据 if (!wait_ack()) return 1; I2C0->C1 &= ~I2C_C1_MST_MASK; // 产生停止位 return 0; }

寄存器映射我在工程笔记里整理了一张表,这里列出来供参考。必须说明的是,我笔记里的寄存器编号是按PMIC的数据手册对照着写出来的,不同子型号可能有差异,你拿到板子后第一件事就是对着最新版手册重新核对一遍,再按照我的顺序做初始化。

寄存器(示例)内容配置值
REG_DEVID芯片ID读回并核对
REG_BUCK1_VSELBUCK1输出电压3.3V对应值
REG_BUCK2_VSELBUCK2输出电压1.8V对应值
REG_BUCK3_VSEL_ADVS电压点A1.3V对应值
REG_BUCK3_VSEL_BDVS电压点B0.9V对应值
REG_EN各路使能控制使能BUCK1/2/3
REG_STATUS状态与故障信息上电后读回确认

3.3 读回校验与故障中断

很多I2C设备只写不读也能跑起来,但这颗PMIC我强烈建议你把读回做进初始化流程。写寄存器之后立刻读同一地址,值一致再往下走,不一致就报错重试。原因很简单:功率器件的引脚电平直接关系到硬件安全,一次静默的I2C写失败可能让某一路输出电压停在错误状态,而系统表面的现象可能只是"偶尔工作异常",极难排查。

INT引脚对应的中断处理也建议提前写好。PMIC检测到输入欠压、输出过流、过温这类故障后会把INT拉低,MCU在中断服务程序里读取状态寄存器、记录故障码,然后决定是恢复运行还是进入安全模式。我在实际调试中就靠这个中断抓到过一次摸不到的欠压问题,后面会具体讲。

4. 低功耗状态机:K24的模式切换与DVS联动

4.1 MK24的低功耗模式怎么选

Kinetis K24的电源模式从高到低排列大体是RUN、WAIT、STOP、VLPS、LLS、VLLS0这一串。选哪个模式不是越低越好,而是看唤醒方式和恢复速度能不能满足业务需求,下面是参考手册整理的对照表。

模式CPU外设时钟典型唤醒源参考电流
RUN运行全速无几十到一百mA级
WAIT停止系统时钟可关中断明显低于RUN
STOP停止可配置关断外部中断/RTC几十到几百µA
VLPS停止低功耗异步时钟LPTMR/外部引脚十µA级
LLS停止几乎全关RTC/引脚唤醒个位µA级
VLLS0复位状态全关RTC/特定引脚亚µA级

这里要特别提醒:STOP及以上的模式,SRAM内容和寄存器状态能保留;但到了VLLS0这种深度掉电模式,唤醒后整个芯片相当于重新复位,所有现场状态都要从外部存储恢复。我们这个项目需要定时唤醒采集数据,状态恢复又不想做得太复杂,最后选择VLPS作为深度睡眠点,满足整板电流目标的同时,唤醒后可以直接回到业务代码里往下跑。

4.2 状态机设计与DVS配合

低功耗设计最忌讳的是状态散落在业务代码里,想到哪里睡就哪里睡。我把电源状态固化成一个状态机,总共四个状态,每个状态定义了各路电压目标和MCU所处的模式。

BOOT阶段三路全开,MCU高频运行,初始化完成后进入ACTIVE;ACTIVE状态MCU正常采集,无线模组电压保持在1.3V;一旦进入IDLE,传感器电源关断,无线模组电压通过DVS降到0.9V,MCU进STOP等定时器唤醒;再往下一层是DEEP_SLEEP,无线模组断电,MCU进VLPS,只剩下RTC和按键能唤醒。每一层状态切换都有明确的电压和模式定义,调试时只要对着这个表核对状态就行。

进入睡眠的顺序也很关键,一定要先在DVS上降电压,等电压稳定以后,MCU再进入低功耗模式。唤醒过程反过来,MCU先从WFI出来,第一件事就是把电压抬回工作点,然后才继续跑业务。这个顺序颠倒的话,设备大概率会在睡眠和唤醒的边界反复欠压复位。下面这段是进入深度睡眠的代码骨架:

void pm_enter_deep_sleep(void) { pca9422_write_reg(REG_BUCK3_VSEL, BUCK3_0V9); // 先把1V0_RF从1.3V降到0.9V delay_us(500); // 等DVS斜坡稳定,留足余量 // 关闭外设时钟、复位GPIO方向 // ... SMC->PMCTRL = SMC_PMCTRL_STOPM(2); // 按手册配置进入VLPS __WFI(); // 等待唤醒 pca9422_write_reg(REG_BUCK3_VSEL, BUCK3_1V3); // 唤醒后立刻抬回1.3V }

4.3 切换时序的几个实测注意点

DVS的斜坡时间在数据手册里通常会给一个电压转换速率,按速率算出来的斜坡时间只是一个理论下限。实际必须留出至少两倍的余量,因为PMIC的输出电压从目标值到真正稳定还包含一段时间,尤其外围还有负载电容在充电。我第一次写代码时只按理论值延时,结果在低电量的样机上出现唤醒后死机,后来把延时从200µs加到500µs才稳定。

另外强烈建议把示波器探针同时挂在电压轨和GPIO上,实测一次完整的降电压、进睡眠、唤醒、抬电压波形。我这是调试完才补做的,但做完之后对这套机制的理解完全不同,很多莫名其妙的复位、死机都能在这个波形里看出端倪。

5. 调试过程中还原的三场硬仗

5.1 400kHz I2C偶发NACK:总线容抗和上拉电阻的账

这个问题的排查过程比较典型。样机正常运行时,I2C偶尔出现NACK,软件里做了重试,所以表面看起来功能都正常。但后来发现,电池电压降到3.6V以下、或者环境温度降低时,NACK频率明显上升。

我用逻辑分析仪挂上总线抓波形,第一眼就看出问题了:SCL和SDA的上升沿明显变缓,特别是温度低的时候,上升沿几乎成了一条斜线。原因有两层,第一层是上拉电阻初始选的10kΩ偏大,第二层是PCB上PMIC和MCU之间的I2C走线较长,再加上器件引脚电容,总线总容抗已经超过了400kHz正常工作能接受的范围。低温下PMIC内部IO驱动能力下降,问题就暴露得更明显。

处理办法是我把上拉电阻从10kΩ换到2.2kΩ,同时把初始化阶段的I2C时钟降到100kHz,等握手成功后再切到400kHz。换完之后同样的环境条件下,波形上升沿干净多了,NACK再也没出现过。这里总结出一条经验:I2C出问题先看波形、先查上拉和容抗,不要第一时间怀疑配置代码,我见过太多人在软件里反复试参数而忽略了这根物理链路。

5.2 无线模组突发电流导致电压跌落

第二个坑是在联调无线模组时踩的。模组之前单独供电一切正常,接进系统以后只要一发数据,设备就复位。示波器抓BUCK3的输出电压,能清楚看到模组发射脉冲瞬间电压跌落超过150mV,直接跌出了模组的最低工作电压。

根因有两方面。一是输出电容放得太小,偷懒只放了4.7µF,瞬态负载进来时电荷储备不够;二是PMIC处在PFM轻载模式,这个模式为了省电,开关频率会降下来,应对突发大电流的能力自然变差。解决办法是输出电容加到22µF,并把BUCK3配置成强制PWM模式,让它在模组工作时始终维持较高的开关频率。改完之后同样的发射场景,电压跌落控制在50mV左右,系统稳定了。

这里多说一句PFM和PWM的选择逻辑:PFM在轻载时效率高,适合睡眠期间的小电流场景;PWM动态响应好,适合电流突变频繁的场景。如果数据手册支持模式动态切换,最好也通过寄存器在两种模式间切换,而不是长期固定用PWM耗着睡眠电流。我们最后就是在睡眠时切回PFM,唤醒后切到PWM,兼顾了两头。

5.3 睡眠电流虚高:不是PMIC的锅

硬件和初始化代码都稳定以后,开始测整机睡眠电流。目标50µA,实测却高达1.6mA,差了三十多倍。我一开始怀疑PMIC空载电流高,逐路断开输出以后发现PMIC这边本身只有十几微安,问题反而集中在MCU侧。

排查过程是把GPIO逐组复位测量。最后定位到两件事:一是有几个GPIO在睡眠前还保留输入状态,芯片内部的上拉电阻被使能了,漏电路径一条接一条;二是I2C两根线的外部上拉电阻一直在工作,睡眠时总线是空闲高电平,但上拉电阻挂在电源和总线之间,这一路就白耗了。解决办法是进睡眠前把所有不用引脚的PCR清零,GPIO配置成模拟状态或输出低电平;I2C上拉电阻改成由一颗MOS管控制,睡眠时直接断开上拉。全部改完之后整板电流降到26µA,不仅达标,还比目标值低了一半。

测量方法这里也值得记一笔:睡眠这种微安级的电流,普通万用表的电流档分辨率不够而且会在回路里产生不小的压降,建议用支持微安分辨率的表或者直接串一个精密采样电阻配示波器看压降,数据才可信。

6. 实测数据与几条能直接抄走的经验

6.1 各状态电流实测

整个状态机调完之后,我给每个状态做了一组整板电流实测。测量时串接采样电阻并用示波器记录平均值,避免普通万用表在动态电流下的读数误差。

状态条件BUCK3电压整板电流
BOOT120MHz全速运行1.3V45mA
ACTIVE正常采集数据1.3V38mA
IDLE定时采样,MCU进STOP0.9V210µA
DEEP_SLEEPVLPS,无线模组断电0.9V26µA

这些数字本身没有普适性,因为每块板子外设数量和类型不同,但能看出一个趋势:DVS和MCU低功耗模式联动之后,整机电流从几十毫安级压到了几十微安级,降了整整三个数量级,这就是完整电源管理方案带来的实际收益。

6.2 这套组合带来的收益

我在迭代过程中保留了一版旧的分立电源方案做对比,把关键指标放在同一张表里,差距一目了然。

对比项旧分立方案PCA9422 + MK24方案
电源相关BOM12颗左右6颗左右
上电时序RC延时,精度差寄存器配置,可复现
睡眠电流180µA26µA
调整输出电压换物料改寄存器
动态电压调节不支持支持
故障上报无INT中断+状态寄存器

面积省的其实不算多,毕竟PMIC本身也占地方,真正值钱的是调试成本的下降。以前改一个电压要动BOM、重新画板,现在一条I2C命令就解决了;以前时序不稳要靠示波器抓碰运气,现在每次上电都是同样的配置序列。这种确定性在量产阶段价值很大。

6.3 几条建议,包括一个我最后才学会的测量方法

按优先级把经验整理成几条,给后来者直接参考。

第一,首次上电前把PMIC默认输出全部量一遍,确认和预期一致再写代码。第二,调低功耗时不要只盯MCU,把PMIC的空载电流和整机电流分开量,逐路断开输出就能快速定位电流花在哪个域。第三,测睡眠电流尽可能用微安表或采样电阻加示波器,普通万用表串进去不仅读数不准,自身压降还可能触发PMIC的欠压保护。第四,PMIC的INT引脚务必接进MCU中断,出故障时第一时间留下状态记录,比事后猜原因高效得多。第五,改DVS电压时避开大负载窗口,先切到轻载再操作寄存器,减少瞬态冲击。

如果让我重做一遍整个项目,我会在画原理图阶段就预留好EN和VSEL对应的GPIO,不会等到调DVS时才飞线补控制。电源管理这种基础链路,前期多花一天确认引脚和测量点,后期往往能省下一周。希望对正在做类似项目的你有点参考价值。