1. 方案定位:PCA9422 与 PIC18F87J50 是怎么分工的
这块采集板一开始的需求很朴素:无线模组、模拟前端和主控各要一路电源,但是三路不能同时随便上电。无线模组要等主控完成配置后才开,模拟前端的纹波要求比较高,主控那一路又要具备软复位能力。如果按老做法用线性稳压加 GPIO 使能,能实现基本开关,但故障保护太弱,电池过放、负载短路、过温这些场景只能靠硬件保险丝兜底,出了问题很难定位。后来我决定把方案整体改成"PMIC 执行 + MCU 调度",选型落在 PCA9422 和 PIC18F87J50 上。这篇内容就是完整记录这套电源管理方案的选型逻辑、电路接法、固件流程和实测排雷过程。
1.1 先算清需求:多电源域、时序、待机电流
选型不能先看芯片再倒推需求,而是要把需求列成硬指标,再拿芯片去对。当时我给这台便携采集设备列了这么一张表:
| 电源域 | 目标电压 | 最大电流 | 时序要求 |
|---|---|---|---|
| 主控内核 | 1.8V | 100mA | 最先上电,支持软复位 |
| 无线模组 | 3.3V | 300mA | 主控配置完成后才允许开启 |
| 模拟前端 | 3.3V | 50mA | 与主控同步启动,纹波要求高 |
| 整机待机 | - | 小于1mA | 休眠时关闭无线域和模拟域 |
在这个基础上还有两个隐藏需求:一是要支持 USB 和锂电池双输入,二是要能通过程序动态调整某路电压,而不是固定死。PCA9422 内部有两路降压转换器加两路 LDO,正好匹配无线、数字核、模拟前端这三路。更重要的是它的 I2C 接口能读回状态,包括中断源、欠压标志、输出状态,这给系统级诊断留了很大空间。PIC18F87J50 这颗 8 位 MCU 则负责所有"决策"动作:开机时写寄存器、运行时轮询状态、休眠时管理各电源域开关。它内置 I2C 外设、十几个 ADC 通道,还有足够大的程序闪存存运行日志,板子上连外部晶振都可以省掉,直接用内部振荡器跑,整体 BOM 很干净。
1.2 为什么是"PMIC 执行 + MCU 调度"而不是全硬件方案
有人会问,既然 PCA9422 本身支持硬件引脚配置,为什么还要多挂一颗 MCU 去控制它?答案是灵活性。纯硬件配置适合电源方案完全固定、不需要动态调压的场景;但一旦涉及电池电量变化、待机唤醒、异常重试策略,就需要软件介入了。PIC18F87J50 在这里只做三件事:通过 I2C 写配置、通过中断读取故障、执行上层策略。它不参与功率转换路径,所有电流路径都留在 PMIC 内部。这个分工的最大好处是调试时可以清楚区分问题出在哪一层——是策略层配置错了,还是执行层硬件坏了,不用两边互相猜。实际项目里,我曾把某一路输出误配置成过高电压,MCU 侧读回输出状态时立刻就能察觉到不一致,第一时间做关断保护,这个"可读、可查、可回滚"的能力是纯硬件方案给不了的。
2. 硬件连接细节:接口一对一该怎么做
硬件连接看着简单,实际上决定了后面固件能不能顺利调通。这一节把 I2C 总线、使能脚、中断脚、采样节点这四部分的接法逐一说明。多数问题都是在这层埋下的,等到固件阶段再去查,往往要花好几倍时间。
2.1 I2C 总线的上拉、电平与从机地址
PCA9422 作为 I2C 从机,SCL、SDA 两条线接到 PIC18F87J50 的 MSSP 外设引脚上。PIC 这边要先确认引脚方向设置为输入,因为 I2C 是开漏结构,主机在输出低电平时没有问题,输出高电平实际要靠外部上拉电阻实现。我在这块板子上用 2.2kΩ 上拉电阻接到 3.3V 电源轨,这个值在几十厘米 PCB 走线和一两个外设的情况下比较稳。如果总线上挂的设备多、走线长,可以换 1.5kΩ 增强驱动能力,但不建议低于 1kΩ,否则低电平灌电流偏大,会增加功耗也容易损伤端口。
从机地址这块需要注意,PCA9422 的 I2C 地址由芯片引脚决定,不同版本可能映射到不同地址。我遇到过一次按默认地址枚举失败的情况,排查时发现是地址引脚的电平被布线影响了。实际做法是在固件里做一次总线扫描,把 0x60 到 0x6F 范围都读一遍,通过应答地址确定从机位置,这样硬件哪怕改版也能自适应。另外,PCA9422 的 I2C 逻辑电平要和自己芯片的 VDDIO 对应,所以选 PIC18F87J50 时确认引脚输入阈值匹配,避免出现一边认为是高电平、另一边认为是低电平的尴尬。
2.2 使能脚、中断脚和电源好信号接法
PCA9422 的使能控制脚通常会挂一个外部信号来触发上电。考虑到这个项目需要 MCU 完全掌控时序,我用 PIC 的普通 GPIO 通过一个 RC 电路去驱动使能脚。之所以加 RC,是为了防止 MCU 复位瞬间 GPIO 出现不可控的抖动,导致 PMIC 误开启。RC 时间常数取 10ms 左右,既能滤除毛刺,也不会明显拖慢上电响应。正式量产固件里,这个使能脚初始化时要先拉低,等系统电压稳定、I2C 初始化完成后再拉高进入配置流程。
中断脚接到 PIC18F87J50 的 RB0 外部中断输入。这颗 PMIC 的中断脚是开漏输出,低电平有效,所以外部也要加上拉。我在中断线上串了一个 1kΩ 的电阻做保护,并在 MCU 侧对地并联一个 100pF 电容滤除高频噪声。之所以选择中断驱动而不是轮询方式,是因为电源异常往往需要微秒级响应,轮询在这种场景下要么太慢要么太耗 CPU。还有一个被很多人忽略的信号是电源好输出,我把它接在 PIC 的一个普通输入引脚上,开机流程里 MCU 会在使能 PMIC 输出之后检查这个信号,确认各路电源真正稳定后才继续后续初始化,而不是盲目等固定延时。
2.3 电压与电流采样节点的布局
监控电压和电流是电源管理里很有价值的部分。电压采样我用精密电阻分压后进 MCU 的 ADC,分压电阻取了 1% 精度,并在 ADC 引脚并联 0.1µF 电容做滤波。电流采样则在高边放一颗 0.02Ω 的采样电阻,采用差分走线,两根线尽可能靠近且等长,避免采样误差被地弹噪声淹没。这类采样走线在布局时要特别注意远离开关节点,因为 BUCK 输出的 SW 节点是全板噪声最强的区域,采样线一旦从这里穿过,ADC 读数会明显跳变。我在第一版 PCB 上就吃过这个亏,模拟前端电压显示一直有规律的小幅波动,最后把采样线绕开 SW 节点并且增加了一级 π 形滤波才解决。
PCB 布局方面还有几个通用原则可以分享:PCA9422 的输入电源引脚旁边要放足够的陶瓷电容,通常 10µF 加 0.1µF 组合,并且尽量靠近引脚;SW 节点走线要短且宽,减少寄生电感和辐射;各个电源域的输出电容要落在负载侧,而不是都堆在 PMIC 附近;四层板的话,给 PMIC 底下留一个完整的地平面,这比任何软件滤波都更实在。
3. 固件侧流程:MSSP 初始化到 PMIC 配置
硬件连接没问题后,固件就是整个方案的核心。PIC18F87J50 的 MSSP 外设既可以跑 SPI 也可以跑 I2C,我这里只讲 I2C 主机模式的用法和踩坑点。整个初始化流程分为三步:底层 I2C 通信打通、PMIC 寄存器配置、上电状态机与中断处理。
3.1 I2C 底层驱动:时钟、起始位、ACK 判断
MSSP 模块配置成 I2C 主机模式主要设置几个寄存器:SSPCON1 选择 I2C 模式并打开模块,SSPADD 决定通信速率。I2C 时钟的计算公式如下:
F_SCL = F_OSC / (4 * (SSPADD + 1))假设工作频率取 8MHz,想得到 100kHz 的 SCL,那么SSPADD应该配置为 19。这段配置代码可以直接抄:
void i2c_init(void) { TRISCbits.TRISC3 = 1; // SCL 设为输入,由外部上拉驱动 TRISCbits.TRISC4 = 1; // SDA 设为输入 SSPCON1 = 0b00001000; // I2C 主机模式,使能模块 SSPCON2 = 0b00000000; SSPSTAT = 0b00000000; SSPADD = 19; // 100kHz,基于 8MHz 晶振 } void i2c_start(void) { SSPCON2bits.SEN = 1; while (SSPCON2bits.SEN); } void i2c_stop(void) { SSPCON2bits.PEN = 1; while (SSPCON2bits.PEN); }写一个字节最简单的办法是把数据放进 SSPBUF,然后等待 SSPIF 置位。判断 ACK 状态看 SSPCON2 的 ACKSTAT 位,读一个字节则先启动作主机接收,再在第 9 个时钟周期上手动拉低或释放 SDA 来控制是否发 ACK。底层驱动建议把所有操作封装成i2c_write_byte、i2c_read_byte、i2c_read_reg这样的函数,并且增加一个超时判断,防止总线异常时程序卡死在等待循环里。
3.2 PMIC 寄存器配置示例与写回校验
PCA9422 的寄存器具体地址和位定义以官方数据手册当前版本为准,这里给出的是我在项目里实际验证过的配置思路。我们需要的功能是:两路 BUCK 分别输出 1.8V 和 3.3V,两路 LDO 输出 3.3V 和 1.8V,设置充电电流约 300mA。操作顺序必须遵循"先配置电压、再配置使能、最后启动排序"的原则,否则芯片可能按默认参数先上了电,之后再改电压就来不及了。
以下代码是配置流程的示意,实际使用要根据所选型号查手册确认寄存器编号和取值:
pca_write_reg(0x10, 0x40); // BUCK1 输出电压设为 1.8V pca_write_reg(0x11, 0x20); // BUCK2 输出电压设为 3.3V pca_write_reg(0x12, 0x0F); // LDO1 输出 3.3V pca_write_reg(0x13, 0x0A); // LDO2 输出 1.8V pca_write_reg(0x20, 0x01); // 使能 BUCK1 和 BUCK2 pca_write_reg(0x21, 0x03); // 使能 LDO1 和 LDO2 pca_set_charge_current(300); // 充电电流约 300mA这里我最想强调的一点是写回校验。I2C 通信不是每次都可靠,电磁干扰、电平不匹配、时序超时都可能导致寄存器写入失败。如果配置失败而代码继续往下走,电源时序就会乱,后果是硬件可能损坏。所以我每写一个寄存器,都会紧跟着读回来比较,不一致就重试三次,还是失败就直接报错并停止上电序列。这套"写前备份、写后回读"的习惯看起来多花了一点时间,但在现场排查时能帮你快速定位是通信问题还是 PMIC 自身的问题。
3.3 上电状态机与故障中断处理
上电流程我用一个简单的状态机来管理:OFF、CONFIG、SEQUENCE、READY、FAULT五个状态。系统刚复位时处于 OFF 状态,此时 GPIO 保持默认安全电平,PMIC 处于关闭状态;等主电源稳定后,I2C 初始化、寄存器配置和写回校验全部完成,才进入 SEQUENCE 状态。在 SEQUENCE 状态下,先使能 BUCK1,延时 10ms 等待输出电压稳定,再使能 BUCK2,又延时 10ms,最后打开 LDO。每一路使能后都会检查电源好信号,只要有一路没有按时变高,就跳到 FAULT 状态,保留现场信息并等待进一步处理。这套带超时的顺序控制比单纯"一股脑全开"可靠太多,特别是在模拟前端这种对时序敏感的部分。
故障中断处理是另一个关键环节。PCA9422 的中断脚一旦拉低,MCU 的外部中断就会触发。中断服务程序里不应该做复杂处理,只做一件事:读取 PMIC 的中断状态寄存器,确定故障类型,清除中断标志,然后置状态机标志位。具体动作交给主循环去执行。比如过压就立即关闭对应电源域,过温就以较低优先级逐步降载而不是直接断电,充电故障则尝试重新读取状态确认是否误报。这个"ISR 只快读、主循环做决策"的写法既能保证响应速度,又能避免在中断里调用耗时函数导致其他中断丢失。
4. 实测中的波形、纹波和低功耗数据
固件调通之后,真正的战场在实验室。这里记录了几个实测过程中比较有代表性的问题,每一个都是实际可复现的场景,能帮后面做类似方案的人少走不少弯路。
4.1 逻辑分析仪抓到的 I2C NACK 问题
第一版固件在系统上电后立刻初始化 I2C 并访问 PCA9422,结果有三成的概率在读第三、第四个寄存器时收到 NACK。一开始怀疑是 PMIC 坏了,后来用逻辑分析仪抓总线波形,确认前面的读 ID 都正常,NACK 发生在电源输出使能之后的第一次访问。这就把目标锁定在"PMIC 内部状态发生变化导致暂时不可访问"。查了芯片手册发现,PCA9422 在启动排序过程中内部模块需要短暂切换,此时 I2C 接口会暂时无响应。解决方式很简单:初始化完成之前不使能任何输出,使能输出之后再延时 20ms,期间不做任何总线访问,后续通信就稳定了。从这个经历得到的经验是,遇到偶发 NACK 不要急着改硬件,先在总线上抓真实波形,确认 NACK 出现的时机,往往答案就在时序里。
4.2 动态负载下的纹波治理
无线模组在全速发射瞬间会抽电 300mA 以上,导致 3.3V 输出纹波从空载的 20mV 飙升到接近 80mV。这个量级对无线模组影响不大,但是同板上模拟前端会对这种纹波敏感。处理方式分了两步:第一步在输出端增加一组 22µF 陶瓷电容,尽量贴近负载端放置,降低高频阻抗;第二步调整 PMIC 进入强制 PWM 工作模式,避免负载切换时在 PFM 和 PWM 之间来回跳变。调整后整条负载变化过程的纹波稳定在 30mV 以下。这个案例也说明了 PMIC 的工作模式选择不能只看静态效率,动态负载场景下稳定优先,牺牲一点空载效率换负载调整率是值得的。
4.3 待机电流与休眠策略实测
低功耗是便携设备的刚需。实测数据对比很明显:整板全速运行时电流约 34mA,进入休眠模式后,MCU 切换到睡眠、无线模组和模拟前端的电源域全部关闭,整机电流降到 0.5mA。这个结果的实现依赖两部分配合:一是 MCU 在休眠前通过 I2C 配置 PMIC 关闭对应输出域,二是 PMIC 在轻载时自动进入高效 PFM 模式。需要注意的是,I2C 关域的顺序要和在开机时的使能顺序相反,否则会有短暂的上电残留电压。同时建议给 MCU 开一个低频看门狗定时器,周期性唤醒检查电池电压,再决定是否加深睡眠或者执行低电量保护,而不是让系统一睡到底。
4.4 充电和温升实测记录
电池充电部分我们也做了实际测量。设定 300mA 充电电流,电池电压到 4.2V 之后进入截止判定流程,状态寄存器能正确回读各种充电阶段。整块板在持续运行一小时后,PMIC 外壳温度比环境温度高约 8℃,这个温升幅度在可接受范围内。如果散热量更大的应用,建议在 PCB 上 PMIC 底部增加散热过孔阵列,并且不要把充电电流顶到规格上限,留出 20% 的余量对长期可靠性更有利。充电电流太大时 PMIC 自身损耗也会显著上升,反而降低整体效率。
5. 经验总结与后续扩展方向
方案做完整整一圈,回头看最有价值的不是最终的电路和代码,而是整个调试过程中形成的判断方法。核对寄存器花的精神远小于排查硬件的时间,先用逻辑分析仪抓总线、再用示波器看电源轨、最后才动代码,这个顺序能解决绝大部分问题。还有一个个人体会:任何电源管理方案的改动,都要遵循"先确认现状、再小步改动、每次只改一个变量"的原则。比如调整纹波时,如果同时改了电容、驱动模式和开关频率,最后出了问题根本不知道是哪一个改动引起的。
另外,调试时备好几样基础工具能让效率高很多:一台双通道以上示波器、一台带解码功能的逻辑分析仪、一台电子负载,再加一个数字万用表。逻辑分析仪看 I2C 时序最直观,示波器用来测纹波和上电波形,电子负载用来模拟动态负载变化。实测上电波形时有个小技巧,用示波器的单次触发模式,触发源选使能 GPIO,这样可以准确抓到每一次上电过程中每一路电源的真实上升斜率,比看数据手册估算靠谱得多。
后续如果要继续完善这套方案,可以考虑加一个上位机配置接口,通过串口把目标电压和时序参数下发到 MCU,再由 MCU 动态改写 PMIC 寄存器,这样同一块板子就能适配不同负载模块的需求。也可以把运行日志、历史故障记录都存进 MCU 的闪存里,方便现场返修时快速定位是电源问题还是负载问题。整体来说,PCA9422 加 PIC18F87J50 这套组合的灵活性是非常够用的,真正的成本在于把电源时序和故障处理想清楚、做扎实,而这些恰恰是电源管理项目里最有价值的部分。