☰
PMIC+I2C:便携设备电源管理与低功耗调压设计实践
2026/10/9 10:57:05 网站建设 项目流程

之前做便携式小盒子时,最困扰我的不是算法怎么写,而是电源管理方案太碎:充电一颗、升压一颗、LDO 两颗,各管各的,互相之间还要用逻辑引脚去协调,整板 BOM 快赶上主板了。后来在某个模拟项目 X 里把主控换成 PIC18F86J16,电源部分换到 PCA9422 上,整套系统瞬间清爽了很多。这块 PMIC 把充电管理、多路输出、I2C 配置和中断上报都收到一颗芯片里,MCU 只需要通过 I2C 去规划电压、使能通道、切换工作模式,整机的电源树就有了统一的控制入口。

这篇内容适合正在做电池供电便携设备、智能穿戴或 IoT 节点电源管理的朋友。如果你也打算把分散的电源模块整合进 PMIC,或者想让 MCU 对电源有更强的控制力,可以直接参考我这次的完整实现:从硬件选型、外围电路到 I2C 配置、动态调压、低功耗切换,再到调试过程里踩过的坑,一次讲清楚。

1. 项目整体思路:为什么把电源管理交给 PMIC 和 MCU 的组合

1.1 从分立电源到集成 PMIC,省的不只是 BOM

先算一笔账。原来分立方案里,锂电池进来要先分两路:一路给充放电管理芯片,一路经过一个升压或降压给系统供电,然后再挂两片 LDO 分别给 MCU 和外设。充电芯片要 MCU 用 GPIO 去模拟握手时序,升压芯片要外加使能控制和软启动电容,LDO 的输入输出电容还得按手册严格来。关键问题是,这些芯片之间的上电时序、欠压保护、短路保护都是割裂的,出了问题很难定位。

换到 PCA9422 之后,输入输出轨、充电回路、保护逻辑都在同一颗芯片内部管理。它有多路输出通道,每一路都可以通过 I2C 独立配置电压、开关、放电顺序,还集成了针对单节锂电池的充电管理。MCU 这边只保留一个任务:通过 I2C 下发配置,并在关键节点读取状态、响应中断。整个电源控制从"分散的逻辑电平控制"变成了"统一的寄存器管理",调试时看寄存器状态就能知道每个通道在干什么,效率完全不一样。

1.2 两颗芯片的分工

PCA9422 管的是"电能怎么进来、怎么存、怎么送出去"。它负责电池充电、系统供电、各路输出的通断和电压设定,也负责把过压、欠压、充电完成等事件通过中断脚上报给 MCU。

PIC18F86J16 管的是"什么时候用多少电"。它本身是一颗 8 位 MCU,Flash 和 RAM 对这个场景足够用,I2C 外设也够稳定,关键是功耗低、启动快。系统在工作状态时,MCU 正常运行;进入待机时,MCU 把不用的输出通道关掉、把电压调低,最后自己也进入低功耗模式;需要充电时,MCU 通过 I2C 读取充电状态并上报。

我按功能画了一下这套系统的工作流,大致是:上电时 PMIC 按默认配置输出,MCU 先跑起来,再去修改 PMIC 配置;运行过程中 MCU 根据负载状态调压或关断外设电源;电池电量低时 PMIC 上报中断,MCU 进入低功耗并等待唤醒。这个模型下,MCU 虽然不做功率变换,但它是整个电源策略的决策者。

2. 硬件设计细节:外围电路选型与板级注意点

2.1 PCA9422 外围电路的设计要点

PCA9422 这种 PMIC 虽然集成度高,但外围也不是零器件。我拿到这颗料之后先跟原厂手册对齐了引脚功能,再按系统需求把输入、输出和充电三部分分别规划。

输入侧是最需要注意的。如果系统同时支持 USB 和电池输入,那么 USB 的 5V 路径上要加过压保护和防倒灌,电池正极到 PMIC 的路径要尽量短,而且靠近芯片引脚要放一个 10uF 左右的陶瓷电容,再加上一颗 0.1uF 高频退耦。这组电容不能省,我实测过,输入路径长了之后,负载切换瞬间 PMIC 容易触发输入欠压保护。

输出侧的电感要根据每路负载电流选。一般 PMIC 手册里会给一个推荐电感量范围和饱和电流要求,我的原则是选择饱和电流至少是最大负载电流 1.5 倍的电感,不然大电流瞬间电感饱和,输出电压直接掉下去。另外输出电容决定了纹波和动态响应,我通常先在手册推荐值基础上用,然后实测纹波再微调。

充电回路的重点是电流设定电阻和电池温度检测。PCA9422 的充电电流可以通过外部电阻设定,也可以通过 I2C 修改,我推荐硬件先按最大充电电流定好一个保守值,比如 500mA,再在软件里根据电池容量往下调,这样即使初始化代码没跑,硬件也在安全范围。

注意:我第一次画板时把电池负端直接大面积铺铜接到 PMIC 的 GND,结果充电电流采样不准。原因是 PMIC 的充电电流采样需要独立的采样路径,电池负极到芯片之间不该有大电流 GND 平面共享,后来单独走线才正常。

2.2 PIC18F86J16 侧的连接与 I2C 上拉计算

PIC18F86J16 的供电我直接取 PCA9422 的一路 LDO 输出,这样 MCU 的电源可以被 PMIC 控制,待机时可以把 MCU 电源轨也关掉,实现整板低功耗。I2C 的两条线 SCL、SDA 接到 PMIC 的对应引脚,中断输出 INT 接到 PIC 的外部中断输入,用于事件唤醒。

I2C 上拉电阻是很多人容易忽略的点。PCA9422 支持最高 400kHz 的 I2C 速率,PIC18F86J16 的 MSSP 外设也能跑到 400kHz,但总线上的上拉电阻得配合总线电容来选。我当时的 SCL/SDA 走线不长,板级电容估算在 100pF 左右,3.3V 供电下选了 4.7kΩ 上拉,实测 400kHz 波形上升沿稍微有点缓,但通信正常。走线超过 5cm 的话,建议把上拉降到 2.2kΩ 或者降速到 100kHz,稳定性优先。

布局上要注意模拟地和数字地。PCA9422 的充电电流采样属于模拟信号,PIC18F86J16 的数字噪声比较大,两块区域最好单点连接,PMIC 的开关节点 L受机远离 MCU 的晶振引脚,我第一版就是开关节点绕到了晶振下面,干扰导致 MCU 偶发复位。

3. 软件设计与初始化流程

3.1 PIC18F86J16 的 I2C 主模式配置

PIC18F86J16 的 MSSP 模块配置成 I2C 主模式并不复杂,但有几个细节必须处理好。首先是时钟,MSSP 工作在 Fosc/4 的时钟源下,波特率通过 SSPADD 寄存器设置。以 400kHz 目标速率、16MHz Fosc 为例,时钟分频后需要配置的 SSPADD 大致是 (Fosc / (4 * Fosc_derived)) - 1 这一类计算,实际值我会在初始化时结合示波器波形微调。

I2C 通信我用的是轮询加超时。没有操作系统,不用担心任务切换问题,但必须防止从机拉死总线导致程序卡死。每次发送起始条件、写地址、写寄存器地址、写数据、停止条件的每一步,都要加一个超时变量,超时就把总线复位。

这里贴一下我当时写的核心代码框架,XC8 环境下编译:

// I2C 初始化,目标 400kbps void i2c_init(void) { SSPCON1 = 0x28; // I2C 主模式,使能 SSP SSPCON2 = 0x01; // ACK 状态 SSPADD = I2C_BRG; // 根据实际时钟计算 SSPSTAT = 0x80; // Slew rate control } // 写 PMIC 寄存器 unsigned char i2c_write_reg(unsigned char addr, unsigned char reg, unsigned char val) { unsigned int timeout = I2C_TIMEOUT; SSPCON2 = 0x01; // 发起开始条件 while (!PIR1bits.SSPIF && timeout--); PIR1bits.SSPIF = 0; // 地址 + 写位 SSPBUF = (addr << 1) | 0; // 后续逐字节发送 reg 和 val,并检查 ACK // ... SSPCON2 = 0x03; // 结束条件 return 0; }

实际工程里我会把起始、结束、发送、接收都封装成底层函数,上层再去拼寄存器读写。不建议在应用层直接操作 SSPBUF,那样逻辑会乱。

3.2 PMIC 寄存器初始化顺序

PCA9422 的寄存器不少,但初始化顺序可以归纳成一套固定流程。我每次做新板子都会按这个顺序来,能少踩很多坑。

第一步,先读 ID 和版本寄存器,确认 I2C 地址正确、通信正常。如果这一步读数不对,后面所有配置都白搭。第二步,配置每路输出的目标电压和限流值,这个阶段不要使能输出,先把参数写好。第三步,使能需要开启的输出通道,观察电流和电压是否正常。第四步,配置充电相关的参数,包括充电电压、充电电流、截止电流、预充电流。第五步,配置中断掩码,把充电完成、电池欠压、过温等关键事件打开,接到 PIC 的中断脚。

顺序里最关键的一条:先写电压配置,再使能输出。我第一次调试时图省事,把电压和使能写成一个复合操作,先写了使能位,结果输出通道在电压寄存器还没更新时启动了,处于一个不确定的电压状态,后端负载直接进入欠压保护。后来的代码里我严格规定:每次修改某个通道的电压,都要先读当前使能状态,如果是使能状态,就先清使能位,再写电压,再恢复使能,避免中间状态。

注意:PCA9422 这类 PMIC 的寄存器有些是写入后立即生效,有些需要额外触发命令才生效。我遇到过一次写好电压但输出没变,排查后才发现忘了发"应用新配置"的命令。这个细节不同批次芯片可能不一样,最好看手册确认。

3.3 上电和掉电时序的软件实现

上电时序对多电源轨系统特别重要。我这次系统里有三路主要输出:VDD_MCU、VDD_SENSOR、VDD_RF。手册和负载要求是 MCU 先上电,等 MCU 初始化完成之后再打开传感器和射频电源。

软件实现的逻辑是,主控上电后先从 PMIC 读取当前状态,确认 VDD_MCU 已经稳定;然后再写寄存器打开 VDD_SENSOR,延时几毫秒等传感器电源稳定,再打开 VDD_RF。每一路使能之后我都会读一次电压状态寄存器,确认输出真的建立起来才进入下一步。如果某一步超时没稳定,就把系统切到安全状态:关所有输出、亮故障灯、记录错误寄存器。

掉电时序也是同样思路,先关射频、再关传感器、最后关 MCU 电源,顺序反了容易造成倒灌电流。我这次还遇到一个情况:MCU 已经写了掉电命令,但 PMIC 的输出放电时间很长,电压跌落太慢,导致负载在低电压下工作异常。后来我开启了输出放电功能,掉电瞬间快速泄放,问题才解决。

4. 动态调压与低功耗模式设计

4.1 为什么必须做动态电压调节

便携设备对功耗的要求往往比性能更敏感。我这个项目里有一个传感器数据采集的应用场景:CPU 全速跑的时候需要 3.3V 供电,电流约 80mA;传感器数据准备好之后进入浅度睡眠,只需要 1.8V 保持供电,电流不到 5mA。如果一直用 3.3V,浅睡眠时无用功耗就是 (3.3-1.8)x5mA=7.5mW,看似不多,但电池只有几百毫安时,累积下来损耗可观。

动态调压的作用就是让电压跟随负载状态调整。PCA9422 支持通过 I2C 修改输出电压,PIC18F86J16 在进入低功耗前,把 VDD_SENSOR 从 3.3V 降到 1.8V,唤醒后再升回 3.3V。这个操作看起来简单,但省下的功耗在低功耗场景里非常有意义。

4.2 运行中调整输出电压的实现

调节电压本身不复杂,但要注意时序。我的代码逻辑是:先读目标通道的当前电压寄存器,计算目标值对应的寄存器码;如果目标值比当前值低,就先写新电压、等待稳定、再降电流;如果目标值比当前值高,就先确保负载不会过流,然后写新电压、等待稳定。

这里有一个实操技巧:调压前后最好读一次实际电压输出。PCA9422 内部有电压反馈,但外部走线阻抗会导致实际负载端电压和芯片端读数有偏差。我这次就在 PCB 走线长的一路输出上遇到了 0.1V 的压差,调压目标值和实际负载电压对不上。后来我在调压后加了 ADC 回采,用 PIC 的 ADC 引脚直接量负载端电压,形成闭环。

软件之外,动态调压还受负载瞬态影响。我实测从 1.8V 调到 3.3V 时,如果负载电流同时从 5mA 跳到 80mA,PMIC 的输出会有一个比较明显的跌落,只要负载端电压不低于最低工作电压就可以接受。

4.3 低功耗模式的整体策略

完整的低功耗不只是调压,而是一整套状态切换流程。我按系统工作状态设计了四个模式:

正常运行模式:所有输出开启,电压设定为满载值,PMIC 和 MCU 都处于全速状态。

浅度睡眠模式:传感器等大功率外设电源关闭,主 MCU 电压降到最低保持电压,PMIC 充电功能保留,系统等待定时唤醒。

深度睡眠模式:除了 PMIC 自身维持和 MCU 的备份供电之外,所有输出通道都关闭,MCU 进入休眠,外部按键或 PMIC 的中断事件唤醒。

充电管理模式:系统不工作,充电器对电池充电,充电完成后 PMIC 进入低功耗充电维护状态。

模式切换的软件实现,本质上就是一组寄存器写操作。我封装了set_system_mode(uint8_t mode)函数,内部根据模式表依次配置各路输出通断和电压。整个切换必须按固定顺序执行,避免切换过程中出现多路同时开关,造成电池电流毛刺。

提示:深睡模式下 PMIC 自身功耗也要重点关注。我实测这套组合在深度睡眠时整板待机电流控制在 20uA 以内,关键是关闭了不用的输出通道、关闭了充电完成指示灯、MCU 选择了最低功耗的休眠模式,同时保持 I2C 总线上拉不产生额外漏电。

5. 调试实录:实测中踩过的几个坑

5.1 I2C 通信时好时坏,根因是上拉电阻和总线电容

这应该是我调试中最费劲的一个问题。现象是 PMIC 的寄存器读出来大部分正确,但偶尔会读错一个字节,有时候连续读写十几分钟又完全正常。一开始我怀疑 PMIC 芯片体质问题,换了芯片还有。后来用示波器抓 SCL/SDA 波形才发现,400kHz 模式下 SDA 的上升沿明显变缓,低电平时间正常,但高电平建立太慢,导致从机在采样边沿时电平还没稳定。

解决方案分两步。第一步把 I2C 速率降到 100kHz 临时验证,通信立即稳定;第二步重新计算上拉电阻,把原来的 4.7kΩ 改为 2.2kΩ,总线上拉能力增强后恢复 400kHz,波形干净了很多。现在我做这类板子,I2C 上拉阻值一定会根据总线电容实测来计算,不再直接抄参考设计。

5.2 使能顺序错乱导致输出打嗝

另一个印象深刻的坑是 PMIC 的输出在启动时"打嗝",电压起来又掉下去,反复几次才稳定。现象出现在一次修改初始化代码之后,我把通道使能放在中间位置执行,和电压配置顺序错开了一步。PMIC 检测到该通道输出电压建立太慢,以为发生过流,触发了保护,关断输出;电压掉下去之后保护条件消失,又重新尝试启动,形成打嗝。

解决方法是严格按照先配置电压、再使能通道的步骤,同时检查了该通道的过流阈值配置,确保阈值低于实际负载启动电流。我后来还加了一步启动后的状态读取,确认输出稳定再继续,彻底杜绝了这类问题。

5.3 充电管理判满不准,背后是采样路径问题

充电管理这块,我的板子在初期出现了充满电压判不准的现象。用电池测试仪确认电池电压只有 4.0V,但 PMIC 上报已经充满。排查之后发现是电池负极和 PMIC 充电采样点之间的走线压降问题。充电电流 500mA 时,一条不够宽的采样走线产生了比较大的压差,芯片内部看到的电池电压高于电池实际电压,于是提前判满。

解决方法是把电池负端采样线单独拉出来,走线加宽,直接连到 PMIC 的采样引脚,避免大电流路径和采样路径共用。修改后充电曲线恢复正常,判满电压和实测电池电压基本一致。

5.4 系统硬复位时 PMIC 状态错乱

还有一次,系统在异常复位后 PMIC 既不理睬 I2C 命令、输出也不正常,只有断电重启才恢复。排查后确认是 PIC 复位时 I2C 总线处于不确定状态,正好和 PMIC 的配置状态机发生了竞争,PMIC 收到了半截命令,进入了错误状态。

处理办法是软件复位序列:PIC 复位后先拉低 PMIC 的复位引脚(如果有),没有复位引脚的话,就用 I2C 先发软复位命令,确保 PMIC 回到默认状态,再执行常规初始化。我在项目里约定了一个规则:任何 RMII 复位或看门狗复位之后,第一步都是重新初始化 PMIC 到已知状态,不允许直接跑业务代码。

6. 常见问题排查速查表

现象可能原因排查与处理
I2C 读写不稳定上拉电阻太大、总线电容过大、速率过高示波器抓波形;减上拉电阻;降到 100kHz 验证
某路输出无电压通道未使能、电压值配错、硬件损坏读寄存器确认使能位;测电感两端;换通道对比
输出启动后反复重启电压配置和使能顺序错误、过流阈值设定偏低严格先配电压再使能;检查阈值和负载电流
充电判满过早采样路径压降、充电参数设置不当单独走采样线;核对截止电流和充电电压
整板待机功耗偏高输出通道未全关、I2C 上拉漏电、MCU 未进入低功耗逐项关断并实测电流;关 PMIC 指示功能
电压调整后负载工作异常调压后未回采实际电压、负载端压降大加 ADC 闭环回采;PCB 加宽供电走线

调试这类电源系统,我的建议是先打通通信、再玩配置、最后才做策略。通信不稳定的时候不要盲目调参数,先把波形和时序确认好。另外每次修改 PMIC 配置代码之后,一定要做完整的掉电重启测试,因为很多问题只在冷启动时暴露。

另外,配置代码建议做成表格驱动。把每一路输出、每一个通道的参数放到一个结构体数组里,初始化时统一遍历写入,后续修改电压和切换模式只改表项,不会牵动大段逻辑。我在这个项目里把运行参数、充电参数、低功耗参数都做成了独立表,调试时定位问题效率高很多。

最后分享一个小技巧:给所有 PMIC 寄存器读写函数加上日志输出,在调试时打印地址、数据、返回状态。这看起来不起眼,但电源问题排查时,能很快定位到底是写入被吞了,还是读取时序错了。等系统稳定了,再把日志关闭,不影响运行性能。

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

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

立即咨询