1. 从一颗PMIC和一颗MCU聊起:这套电源管理方案到底解决什么问题
做嵌入式系统这几年,电源管理这块我踩过的坑,比代码调试多得多。换过电池方案、折腾过LDO阵列、甚至为了一个电源噪声问题焊了整整一周的板子。后来在一次低功耗物联网设备的设计里,我正式用上了 PCA9422 和 PIC18F57Q43 这套组合,算是把“从电池到系统供电再到功耗监控”这一整条链路彻底理顺了。
先说清楚这两个东西是什么。PCA9422 是一颗电源管理IC(PMIC),集成了充电管理、多路输出电压、电源路径管理和电池监控这些功能。而 PIC18F57Q43 是微控制器(MCU),Cortex-M0+级别的处理能力,当然它是8位架构,但外设丰富程度在同级别里相当能打,尤其是它的内核外设互联(CLC、NVM、DMA这些)非常适合做电源时序控制和系统状态管理。
这套方案解决的核心问题,说白了就是三个:第一,系统供电链路太散,单靠分立器件做电源管理,PCB面积大、故障点多、调试麻烦;第二,电源状态和系统功耗缺乏统一管理,待机功耗压不下去;第三,硬件上缺少“电源健康度”的感知手段,电池衰减、温度漂移、负载瞬态这些只能靠猜。PCA9422负责把“电”管好,PIC18F57Q43 负责把“状态”管好,两者配合起来,电源系统就变成了一个可编程、可监控、可策略化控制的子系统。
这篇文章适合谁看?如果你正在做电池供电的便携设备、IoT 终端、手持仪器,或者准备学习怎么把 PMIC 和 MCU 协同起来做电源架构设计,那这篇内容应该能给你省不少弯路。我会把方案选型逻辑、硬件连接、寄存器配置、固件状态机,以及我在实际调试中遇到的坑和排查思路全部展开,尽量做到可以照着操作。
2. 为什么选 PCA9422 + PIC18F57Q43:这套组合背后的设计逻辑
2.1 先看清楚 PCA9422 这颗 PMIC 的家底
选 PMIC 和选 MCU 的逻辑不一样。MCU 看生态、看外设、看开发便利性;PMIC 更多是硬碰硬的技术指标比拼——输入电压范围、充电电流能力、输出通道数量、静态功耗、保护机制、封装尺寸。
PCA9422 我当初看重的是这几点:
- 输入支持宽电压范围,适配单节锂电池、USB 5V 输入,甚至某些场景下直接用太阳能板输出也能扛住;
- 充电管理支持可编程充电电流,最大能到 1.2A 左右(具体看配置),对于容量 2000mAh 上下的电池来说,充电时间控制在两小时内没问题;
- 输出通道有多个 LDO,电压可编程,适合给 MCU、传感器、射频前端分别供电;
- 静态功耗非常低,在待机模式下能压到微安级别,这对低功耗产品来说是刚需;
- 内置电池监控和 ADC,可以反馈电池电压、电流,甚至温度信息。
选 PMIC 的时候还有个容易忽略的点:封装和引脚密度。PCA9422 的封装属于比较好手工焊接的级别(QFN 封装,引脚间距在 0.5mm 左右),这对打样调试来说太重要了。用过的都懂,引脚间距 0.4mm 以下的芯片,吹上去容易连锡,修起来想哭。
2.2 PIC18F57Q43 的“Q”系列到底强在哪
PIC18F57Q43 是 Microchip 去年主打的新一代 8 位 MCU,它有个很大的卖点:内核独立外设(CIP,Core Independent Peripherals)。
什么叫内核独立外设?简单说,就是很多外设可以在没有 CPU 参与的情况下独立工作。比如 CLC(可配置逻辑单元)可以做信号组合逻辑,NVM(数控振荡器?不对,这里应该是 NCO,数控振荡器)可以产生精确时钟信号,DMA 可以搬数据。这些外设组合起来,就能在没有 CPU 干预的情况下完成很多“智能”操作。
对应到电源管理场景里,这个能力的价值是:电源状态的切换、时序控制、故障响应,不用每步都靠 CPU 轮询,可以把 CPU 解放出来跑协议栈或者干脆进入休眠。
PIC18F57Q43 具体到我用的几个外设:
- CLC(可配置逻辑单元):把多个电源状态信号做逻辑组合,比如“电池电压低 + 充电完成 + 负载关闭”三个条件同时满足时,自动产生一个中断唤醒 MCU;
- ADCC(带硬件累加器的 ADC):对电池电流做多次采样累加,计算平均功耗时不占 CPU;
- UART + DMA:把电源状态数据通过串口发出去,DMA 搬运,CPU 不需要参与每个字节的发送;
- 多个定时器:用于电源时序延时,比如“LDO1 使能后等 10ms 再使能 LDO2”。
除此之外,这颗 MCU 的工作电压范围宽(2.3V~5.5V),可以直接由 PCA9422 的 LDO 输出供电,不需要额外的电平转换,简化了硬件设计。
2.3 为什么不能只用 PMIC 或者只用 MCU
这里我想多说一句。市场上有很多 PMIC 已经内置了复杂的时序控制,甚至自带简单的状态机,为什么还要外挂一颗 MCU?
原因有三个。
第一,PMIC 内置的状态机通常是“固定剧本”,它很难适配你产品的差异化逻辑。比如你的产品有一个“夜间低功耗模式”,需要关掉屏幕供电、降低传感器采样率、保持无线通信模块的唤醒监听,这种多维度的策略组合,PMIC 自己内部做不了那么灵活。
第二,PMIC 的监控数据需要有人“看懂”。电池电压曲线、充电电流变化、负载瞬态响应,这些数据采集回来后,需要校验、滤波、存储、上报。PMIC 不是拿来跑算法的,MCU 才是。
第三,产品迭代过程中,硬件不改,策略要改。如果所有逻辑都用硬件实现,烧一版板子可能就为了改一个时序参数。而 MCU 方案,只需要改固件、刷进去,完全不需要动硬件。
所以 PCA9422 管“电”,PIC18F57Q43 管“策略”,两者各司其职,又不互相冗余,这套架构的核心逻辑就是把电源变成软件可定义的子系统。
3. 硬件设计要点与连接方案:把 PMIC 和 MCU 正确接起来
3.1 系统架构总览
我先画一个整体的供电拓扑,这样后面讲每个模块时会更有画面感。
系统输入端接的是单节锂电池(3.7V 标称,4.2V 满电),同时留了一个 USB 5V 输入口用于充电和调试供电。PCA9422 负责电池充电管理、电源路径选择(有 USB 时优先用 USB 供电并给电池充电,拔掉 USB 自动切到电池供电),并且输出三路 LDO:
- LDO1:3.3V,给 MCU 和数字逻辑供电;
- LDO2:3.0V,给传感器组供电;
- LDO3:1.8V,给射频模块和低电压模拟电路供电。
PCA9422 的 I2C 接口连接到 PIC18F57Q43 的 I2C 外设。三路 LDO 的使能脚 EN1/EN2/EN3 分别接到 MCU 的三个 GPIO。PCA9422 的中断输出引脚 INT 接到 MCU 的 INT0 引脚,用于事件通知(充电完成、电池低压、输入电源切换等)。
PIC18F57Q43 内部固件负责:
- 上电初始化时配置 PCA9422 的寄存器;
- 运行状态机管理电源模式(正常运行、待机、休眠、充电中);
- 通过 ADC 采样电池电压和充电电流;
- 把电源状态信息通过 UART 输出。
用一句简单的话概括硬件连接:PMIC 提供电,MCU 提供脑,中间用 I2C + GPIO 打通信息流和控制流。
3.2 引脚连接表
这里给出我实际使用的连接参考,具体引脚编号以你的 PCB 封装和引脚功能复用来决定,但逻辑关系是通用的:
| PCA9422 引脚功能 | 连接到 PIC18F57Q43 | 说明 |
|---|---|---|
| SCL | I2C SCL(RB6) | I2C 时钟,频率建议 400kHz 以下 |
| SDA | I2C SDA(RB7) | I2C 数据,需要上拉电阻 |
| INT | INT0(RB0) | 中断通知,低电平有效 |
| EN1 | GPIO(RA0) | LDO1 使能控制 |
| EN2 | GPIO(RA1) | LDO2 使能控制 |
| EN3 | GPIO(RA2) | LDO3 使能控制 |
| BAT_ADC | ADC 通道(RA3) | 电池电压监测(如果 PMIC 不自带) |
| STAT1 / STAT2 | GPIO(RA4/RA5) | 充电状态指示(可选) |
上拉电阻这里我多说一句:I2C 总线的上拉电阻,PCA9422 和 MCU 的手册上通常都会给推荐值,一般在 2.2kΩ~4.7kΩ 之间。实际取值要综合考虑总线电容和通信速率,我一般从 4.7kΩ 起步,遇到信号质量问题时再往下调。如果是长走线或者有多个 I2C 从设备,建议先量一下波形再决定。
3.3 PCB 布局与去耦:电源设计里最常见的翻车点
电源设计里面,布局走线没做好,后面调试时会出现各种“幽灵问题”——比如系统无故复位、ADC 采样跳变、射频性能差。我总结几条实战经验:
- PMIC 的输入电容和输出电容必须尽量靠近芯片引脚。PCA9422 的输入去耦电容建议用 10μF + 0.1μF 组合,输出 LDO 也各放 1μF~4.7μF 陶瓷电容。位置远了,高频开关噪声滤不干净,LDO 输出纹波会明显增大。
- 电池走线要粗。电池到大电流路径的走线建议至少 1mm 宽度甚至铺铜,因为充电电流可以达到 1A 级别,走线太细会发热,压降也会让电池电压采样不准确。
- 模拟地和功率地要分离,但最终要单点连接。PMIC 的功率地(大电流回流路径)和小信号地(I2C、ADC 参考地)分开走,在芯片下方的焊盘处汇聚,这样能有效减少地弹噪声对 ADC 采样和通信的影响。
- LDO 输出不要并联大电容直连负载,一定要经过合理的电容网络。特别是给射频模块供电时,负载瞬态变化很快,LDO 的环路响应可能跟不上,这时候输出电容的大小和 ESR 特性就很重要了。我习惯在 LDO 输出到敏感负载之间串联一个磁珠,隔离高频噪声。
3.4 供电顺序:为什么 MCU 必须先于外设上电
电源时序问题在复杂系统里是大坑。PCA9422 三路 LDO 同时使能的话,上电瞬间负载同时涌入,可能导致输入电压跌落,触发欠压保护,整个系统反复重启。
我在这个项目里的时序策略是:
- 上电后先使能 LDO1(MCU 供电);
- 延时 20ms,等待 MCU 启动、初始化 I2C;
- MCU 跑起来后,通过 GPIO 依次使能 LDO2、LDO3;
- 每次使能之间间隔 5ms~10ms;
- 全部 LDO 稳定后,再让系统进入正常运行状态。
这样做的好处是:MCU 永远有电,即使外设供电异常,MCU 也能保持工作,记录错误日志并通过串口上报。如果反过来,外设先上电而 MCU 没起来,那出了问题就完全失控了。
PIC18F57Q43 实现这个时序非常简单——几个 GPIO + 定时器延时就行了。如果对时序精度有要求,可以用它内置的定时器中断来做。不能靠裸延时函数在睡眠模式下计时,一定要用硬件定时器。
提示:电源时序控制在很多产品认证测试(特别是做 EMC 相关测试时)里也可能是关键指标,提前设计好时序策略能省掉后期很多兼容性修改。
4. 固件实现细节:从初始化到状态机再到功耗监控
4.1 I2C 通信与寄存器操作基础
PCA9422 的 I2C 从机地址根据 ADDR 引脚的配置不同而不同,我用的配置默认地址是 0x6C(7 位地址)。通信格式就是标准的 I2C 写寄存器 / 读寄存器方式,但这里有几个需要注意的地方:
- 寄存器写入不需要等待,但写关键配置前最好先读出来确认当前值,避免覆盖了其他字段;
- 部分寄存器是只读的,比如芯片版本号、状态标志位等,写之前一定要先看数据手册;
- 有些寄存器位是“写 1 清 0”的类型(比如中断标志位),操作不当会把状态清掉。
我习惯在初始化时把需要用到的寄存器值都定成宏定义,方便后期维护。下面是一个初始化示例片段:
#define PCA9422_ADDR 0x6C // 7-bit I2C address #define REG_IO1 0x03 // LDO1 电压配置 #define REG_IO2 0x04 // LDO2 电压配置 #define REG_IO3 0x05 // LDO3 电压配置 #define REG_CHG_CTRL 0x0A // 充电控制配置 #define REG_INT_MASK 0x0C // 中断屏蔽寄存器 #define REG_SYS_STATUS 0x0D // 系统状态寄存器 void pca9422_init(void) { uint8_t buf[2]; // 配置 LDO1 输出电压为 3.3V buf[0] = REG_IO1; buf[1] = 0x33; // 示例值,具体请按数据手册的 VOUT 映射表确认 i2c_write(PCA9422_ADDR, buf, 2); // 配置充电电流为 500mA buf[0] = REG_CHG_CTRL; buf[1] = 0x05; // 示例值,对应 500mA 充电电流 i2c_write(PCA9422_ADDR, buf, 2); // 使能需要的充电中断和电源健康状态中断 buf[0] = REG_INT_MASK; buf[1] = 0x00; // 全部使能(0 = 使能中断) i2c_write(PCA9422_ADDR, buf, 2); }注意,上面代码里的地址和值是我按记忆和通用逻辑写的示例,实际应用时必须以你手里的芯片数据手册为准。PMIC 寄存器映射每个批次可能有细微差异,不能想当然。
4.2 电源状态机设计:把系统行为拆成状态和迁移条件
电源管理的核心逻辑是状态机。没有状态机,靠散落的 if 语句堆逻辑,代码写一万行之后自己都看不懂了。我设计的状态比较简单,但很实用:
- STATE_OFF:系统完全断电(只有 RTC 或唤醒逻辑保持最小供电);
- STATE_BOOTING:上电初始化中,按序使能 LDO1 → LDO2 → LDO3;
- STATE_RUNNING:正常运行,所有外设供电开启,MCU 执行业务逻辑;
- STATE_SLEEP:待机状态,关闭非必要 LDO,MCU 进入休眠,定期唤醒检测环境;
- STATE_CHARGING:充电状态下,限制负载电流、监控充电状态;
- STATE_ERROR:检测到异常(过压、过温、电池低压),进入保护性降级模式。
每个状态的迁移条件要定义清楚:
| 当前状态 | 迁移条件 | 目标状态 |
|---|---|---|
| STATE_OFF | 检测到 USB 插入或 RTC 唤醒 | STATE_BOOTING |
| STATE_BOOTING | 三路 LDO 全部稳定 | STATE_RUNNING |
| STATE_RUNNING | 用户按下休眠键或超时 | STATE_SLEEP |
| STATE_SLEEP | 唤醒事件(外部中断/RTC) | STATE_BOOTING |
| STATE_RUNNING | 充电完成且电池充满 | STATE_CHARGING(充电完成后回到RUNNING) |
| 任意状态 | 电池电压低于阈值且无外部电源 | STATE_ERROR |
状态机用 C 语言实现时,我习惯用枚举定义状态,用函数指针数组做状态处理函数映射,这样读代码时一目了然。PIC18F57Q43 的内存足够这样做。
typedef enum { STATE_OFF = 0, STATE_BOOTING, STATE_RUNNING, STATE_SLEEP, STATE_CHARGING, STATE_ERROR } sys_state_t; void state_off_handler(void) {} void state_booting_handler(void) {} void state_running_handler(void) {} void state_sleep_handler(void) {} void state_charging_handler(void) {} void state_error_handler(void) {} const void (*state_handlers[])(void) = { state_off_handler, state_booting_handler, state_running_handler, state_sleep_handler, state_charging_handler, state_error_handler }; sys_state_t current_state = STATE_OFF; void state_machine_run(void) { if (state_handlers[current_state] != NULL) { state_handlers[current_state](); } }这个状态机的好处是:以后新增一个状态(比如“深度休眠”),只需要在枚举里加一个值,再写一个处理函数放进函数指针表就行,不需要改动其他代码。
4.3 如何用 PIC18F57Q43 的外设做“无 CPU 干预”的电源监控
这里要重点说下 PIC18F57Q43 的 ADCC 和 CLC 的配合,因为这是它和其他普通 8 位机拉开差距的地方。
传统 MCU 做电源监控,一般流程是:定时器中断 → ADC 采样 → CPU 处理 → 判断 → 可能的动作。问题在于,整个流程每个周期都要唤醒 CPU,低功耗模式下很难受。
PIC18F57Q43 的 ADCC 支持自动采样和累加。配合它内部的自动触发功能,可以做到:设置好采样通道、采样次数,然后 ADC 自动连续采样 16 次,把结果累加到一个寄存器里,累加完成后产生 DMA 请求,DMA 自动把结果搬到内存缓冲区。整个过程 CPU 完全不用参与。
我在这个项目里的实际用法是:
// 配置 ADCC 自动采样 ADCON0 = 0x01; // 使能 ADC ADCON1 = 0x02; // 选择内部参考电压(示例) ADPCH = 0x05; // 选择 AN5 通道,连接电池输出电压分压后的信号 // 配置累加次数(代码示例,具体寄存器以手册为准) ADACQ = 16; // 连续采样 16 次 // 配置 DMA 自动搬运 DMA1SSA = ...; // 源地址设为累加结果寄存器 DMA1DSA = ...; // 目标地址设为 RAM 变量 DMA1CON = 0x80; // 使能 DMA设置好后,每次需要获取电池电压平均值时,直接读 RAM 里的结果变量就行了。因为 16 次采样是硬件完成的,数据可靠性比单次采样高很多,而且不占 CPU 时间,CPU 可以继续处理其他任务或者进入休眠。
再配合 CLC,我还能实现一个硬件的“欠压锁存”:把 ADC 的比较器输出和电池电压阈值比较器输出作为 CLC 的输入,当电池电压持续低于阈值 N 个采样周期时,CLC 输出一个低电平信号,直接拉低 PCA9422 的 EN 引脚——这个动作是纯硬件完成的,不依赖任何固件逻辑。即使 MCU 死机,这个保护也依然有效。
4.4 充电管理与状态读取:不要编程前先燥,读完再动手
PCA9422 的充电管理寄存器是最值得仔细看的。它相当于是“三段式充电”(预充电 → 恒流充电 → 恒压充电)的硬件实现,你需要配置的参数包括:
- 预充电电流:电池电压低于 3.0V 时使用的涓流充电电流,一般在 50mA~100mA;
- 恒流充电电流:主充电阶段电流,根据电池容量和散热能力设定,我用的 500mA;
- 恒压充电电压:4.2V 或 4.35V(取决于电池化学特性);
- 充电截止电流:恒压阶段电流下降到该值时停止充电。
读取充电状态时,注意 PCA9422 的状态寄存器里可能有“正在充电”、“充电完成”、“充电暂停(温度过高)”等标志,建议通过中断方式感知,不要轮询。中断引脚拉低时,去读状态寄存器,然后处理。
void pmic_isr_handler(void) { uint8_t status = read_reg(REG_SYS_STATUS); if (status & STATUS_CHG_COMPLETE) { // 充电完成,进入运行待机 current_state = STATE_RUNNING; } if (status & STATUS_BATT_LOW) { // 电池电压低,进入降级模式 current_state = STATE_ERROR; } }这里有个坑要重点提示:PCA9422 的中断不是电平触发而是脉冲触发,具体来说,部分标志位在读取后会自动清除。如果你的代码逻辑是在中断里读了标志位,然后又去处理,处理过程中又来了新的中断事件,新的标志可能会被旧的处理逻辑误读或者清除。解决方法是:进中断后先完整读取所有状态寄存器,保存到静态变量,退出中断后再慢慢分析。中断服务函数里只做“保存现场 + 触发一个标志”,不要做复杂判断。
4.5 低功耗模式的设计:把待机电流压到微安级
低功耗产品的核心指标就是待机电流。我实测过这颗方案的整机待机电流,如果把所有 LDO 关掉、只保留 PCA9422 的最低功耗模式 + MCU 睡眠,整机可以做到 10μA 左右。这个数字在同类方案里很有竞争力。
具体怎么实现的呢?
第一,PCA9422 进入休眠模式。平时三路 LDO 只有 LDO1 给 MCU 供电,LDO2/LDO3 通过 EN 脚关闭。进入睡眠时,LDO1 也关闭输出,PCA9422 进入待机模式,只保留充电检测和电源路径管理功能。
第二,MCU 进入深度睡眠。PIC18F57Q43 有多级睡眠模式,我用的最深的睡眠模式电流在 1μA 以下(手册标称值,实际测试在 2μA 左右,加上 PMIC 的功耗,整机 10μA 量级)。
第三,唤醒方式分两种:外部唤醒(USB 插入、按键按下)通过 GPIO 中断;定期唤醒通过内部 RTC 定时器。这两种事件对应到 PCA9422 的输入检测引脚和 MCU 的唤醒源。
有一点要特别提醒:低功耗设计不是写完代码调一版就能达标的,一定要实测。测电流时,不要用万用表串联在电源线上直接测——动态电流变化太快,万用表响应不过来。正确做法是使用电流探头 + 示波器测量,或者用带有高精度电流采样功能的电源来分析。 如果没有条件,可以在电源输入端串联一个 10Ω 采样电阻,示波器测电阻两端电压,换算电流。
4.6 电池电压监测与 ADC 校准
电池电压监测是这个系统里另一个重要环节。锂电池电压不是线性的,空电 3.0V、满电 4.2V,中间有比较平坦的区域,软件需要把 ADC 采样值换算成真实电压,并做低通滤波防止瞬时波动导致误判。
电路上,电池电压首先要经过分压电阻(比如 100kΩ + 100kΩ),把 4.2V 分压到 2.1V,再进入 MCU 的 ADC 引脚。这样做的原因很简单:ADC 参考电压一般不一定是 4.2V 的信号适合测量的范围,而且直接测量超过 VDD 的电压会损坏引脚。
换算公式:
V_battery = ADC_result * (V_ref / ADC_resolution) * (R1 + R2) / R2假设 V_ref = 3.3V,ADC 分辨率 12 位(4096),分压比 2:1,那么:
- 满量程对应的电池电压 = 3.3V * 2 = 6.6V(实际用不到)
- 3.0V 电池电压对应的 ADC 读数 = 3.0 / 2 / 3.3 * 4096 ≈ 1862
- 4.2V 对应的 ADC 读数 = 4.2 / 2 / 3.3 * 4096 ≈ 2607
软件里维护一个 ADC 读数阈值表,就能精确判断低压、正常、充满这些状态。
注意:分压电阻的选择要权衡两个因素——电阻太大,漏电流小但 ADC 采样精度受影响;电阻太小,采样精度高但漏电大。100kΩ 级别在低功耗系统里一般是平衡点。还有就是分压电阻一直连接电池,即使系统休眠也在漏电,所以更严格的设计是在分压网络后面加一个 MOSFET 开关,只在采样瞬间打开。如果你的产品要拼微安级的待机电流,这一步不能省。
5. 实操全过程记录:从焊接评估板到跑通第一版固件
5.1 评估板搭建与最小系统验证
我没有一开始就画 PCB,而是先用评估板和转接板搭建了最小系统,把风险点提前排掉。这是我在复杂电源系统设计上的习惯:先验证芯片本身的性能,再验证芯片之间的配合,最后才投入 PCB 设计。
评估板阶段需要验证的内容:
- PCA9422 单独上电,确认各路 LDO 输出正常、纹波在规格内;
- PCA9422 通过 I2C 能正确读写寄存器;
- PCA9422 的充电功能:接上电池和 USB 输入,确认充电电流、充电截止符合配置;
- PIC18F57Q43 单独跑点灯程序,确认最小系统没问题;
- 两芯片连接 I2C,互相通信成功;
- 模拟电池低压(用可调电源代替电池),确认中断产生和 MCU 处理正确。
其中第 2 步看起来简单,但我见过不少人在这一步就卡住——大多是 I2C 上拉电阻没接、或者地址搞错了。建议调试 I2C 时用逻辑分析仪看波形,一目了然。
5.2 固件调试实录:遇到的三个典型问题
问题一:PCA9422 的寄存器写不进去。
排查过程:一开始以为 I2C 时序不对,用逻辑分析仪抓波形后发现 SCL 频率太高—我配置的是 1MHz,但 PCA9422 的 I2C 最高只支持 400kHz。降到 400kHz 后问题解决。
经验:I2C 通信不要太贪,宁可慢一点也要稳。很多传感器模块的高速模式都有坑,默认先跑 100kHz 或 400kHz 比较稳妥。
问题二:电池电压采样值波动很大。
排查过程:ADC 读数在 ±50 LSB 左右跳动。用示波器测量发现电池电压本身没有波动,问题出在 ADC 参考电压上。PIC18F57Q43 的 ADC 参考电压来自 VDD,而 VDD 是 LDO1 的输出,负载瞬态变化时会有几十毫伏的波动,导致 ADC 参考漂移。
解决方法是:ADC 参考电压改成内部固定参考电压(比如 2.048V),分压比也重新设计,保证电池电压在分压后不超过参考电压的最大值。
问题三:低功耗模式下,MCU 被意外唤醒。
排查过程:检查所有 GPIO 的配置,发现有几个引脚没有设置为数字输入且没有使能内部上拉/下拉,导致悬浮电平在噪声干扰下触发了唤醒中断。把所有不用的引脚统一配置为模拟输入,并开启内部弱下拉,问题解决。
这个坑几乎每个做低功耗的人都踩过,特别是从高功耗模式切到低功耗模式时,一定要重新审查 GPIO 的配置,不能沿用上电默认值。
5.3 功耗实测:数据讲真话
配置完成并调通之后,我做了整机功耗测试。测试条件如下:
- 电池电压 3.8V(模拟正常使用状态)
- LDO1 输出给 MCU + 少量逻辑电路
- LDO2 给传感器组(关闭状态)
- LDO3 给射频模块(关闭状态)
- MCU 处于深度睡眠模式
实测结果:
| 电源模式 | 整机电流(实测) | 说明 |
|---|---|---|
| 正常运行(满负载) | 35mA | 传感器开启、射频间歇发射 |
| 正常运行(空载) | 12mA | MCU 运行,外设关闭 |
| 待机(MCU 睡眠) | 18μA | LDO2/LDO3 关闭 |
| 深度睡眠 | 8μA | 所有 LDO 关闭,PMIC 待机 |
这个数据比我预想的还要好一点,核心贡献在于 PCA9422 自身的低静态电流设计。当然,实际产品里还要加上电池保护板的自耗电、分压电阻漏电等,整机标称待机电流控制在 15μA 以内是完全可行的。
6. 常见问题与排查技巧:电源调试中值得死磕的细节
6.1 系统反复重启:从“供电不稳”到“电源时序”的排查路径
现象:系统上电后运行几秒就重启,或者运行几分钟后随机重启。
可能的原因和排查顺序:
- 先用可调电源代替电池,缓慢升高输入电压,看是否是因为输入电压跌落导致 PCA9422 欠压保护重启。如果是这个原因,检查输入电容和电源路径上的压降;
- 检查 LDO 输出是否短路或过载。用万用表量 LDO 输出对地电阻,排除焊接短路;
- 检查电源时序是否满足要求。用示波器抓三路 LDO 的上升沿,看是否在 MCU 初始化前就同时上电;
- 如果以上都正常,考虑是不是固件死循环导致看门狗复位,排查代码逻辑。
实际遇到最多的情况是第二个:QFN 封装的 PCA9422 底部的散热焊盘如果没焊好,会导致某些引脚虚连或者短路,表现就是极其随机的问题。建议打样后第一件事就是多角度检查焊接质量。
6.2 充电状态不更新:中断触发条件没弄对
现象:电池插上 USB 充电,PCA9422 的充电状态中断不产生或者中断标志一直被置位。
排查思路:
- 检查充电配置寄存器是否真的写进去了。很多 PMIC 芯片的寄存器和真实硬件状态之间有时序(比如需要等 N ms),写完后必须读回来确认;
- 确认电池是否真的连接。PCA9422 如果检测不到电池,可能不会进入充电状态;
- 确认中断屏蔽寄存器。我踩过一次坑:默认中断屏蔽寄存器是全屏蔽的,得先明确使能哪些中断源;
- 检查中断标志位的清除方式。如果中断标志是“写 1 清 0”,而你读完后没写 1 清除,下次中断就不会再触发了。
6.3 ADC 读数偏大或偏小:参考电压和分压电阻的匹配
问题容易出在两个地方:
- 分压电阻的精度。1% 精度的电阻和 5% 精度的电阻,直接导致 1%~5% 的电压测量误差。要做精度要求高的低电压检测,就选 1% 精度的电阻;
- ADC 参考电压的选择。如果参考电压来自 VDD(LDO 输出),负载变化会导致参考电压波动,进而影响转换结果。推荐用内部固定参考电压。
此外还可以在软件里做多点校准。我通常的做法是:用精密可调电源分别给电池端口加 3.3V、3.7V、4.2V,记录 ADC 读数,做线性拟合,把增益和偏移存到 Flash 里,每次上电时加载校准参数。这个方法能有效消除电阻精度、ADC 增益误差等固定系统误差。
6.4 低功耗模式下电流反弹:一个容易被忽略的 IO 漏电
曾经遇到一个奇怪问题:深度睡眠模式下,实测电流从 5μA 慢慢爬升到 50μA,不规律地波动。
最后发现是 I2C 的 SDA 引脚悬空。虽然我没在睡眠时使用 I2C,但 SDA 引脚没有接上拉电阻,也没有配置为数字输入或模拟输入,导致它在悬空状态下反复跳变,每次跳变都产生一个电流脉冲,推高了平均功耗。
这个问题的普遍性很高。做低功耗时,所有不使用的引脚全部要配置成模拟输入,并检查有没有外部不必要的上拉/下拉电阻。PMIC 的中断引脚虽然内部可能有上拉,但建议外部也放一个 100kΩ 上拉,防止在初始化前的默认状态下抖动。
6.5 常见问题速查表
| 现象 | 最可能原因 | 解决措施 |
|---|---|---|
| I2C 通信失败 | 地址错误/上拉电阻缺失/速率过高 | 确认 7 位地址,补上拉电阻,降速到 400kHz |
| 系统重启 | 输入电容不足导致电压跌落 | 增加 10μF + 0.1μF 输入电容 |
| 充电不工作 | 电池未连接/充电使能位未置位 | 检查电池连接和充电配置寄存器 |
| 待机电流高 | GPIO 悬空/未配置 | 统一配置模拟输入,拉起/拉低 |
| ADC 波动大 | 参考电压不稳 | 使用内部固定参考电压 |
| 中断丢失 | 标志位未清除 | 按手册要求“写 1 清 0” |
7. 最后分享两个实战中的心得
如果要把这套 PCA9422 + PIC18F57Q43 的电源管理方案总结成几句话,我最想说的是:“电源管理不是接线和配寄存器,而是状态机和策略的梳理。” 硬件是底座,真正让产品省电、稳定、智能的,是软件里那套完整的电源状态思维。
第一点心得是:不要把 PMIC 当傻瓜电源用,把它的每个寄存器位都当作你产品的功能配置项去读一遍数据手册。PCA9422 里很多寄存器的默认配置并不一定适合你的应用,比如充电截止电流、低压阈值、中断屏蔽位,这些值不去调,系统能用但可能性能差很多。
第二点心得是:用 PIC18F57Q43 内部的 CIP 外设,能帮你实现很多“即使 MCU 在睡觉也能让系统安全运行”的功能。比如用 CLC + ADC 比较器做硬件欠压保护,用 DMA + ADCC 做无人值守的数据采集,这些都是很值得花时间研究的领域。
第三点更实在:调试电源系统,示波器和逻辑分析仪是必备的,有条件的话再加一个电子负载和可编程电源。没有这些工具,你会在各种“幽灵问题”上浪费大量时间。而一旦硬件和固件接口打通了,这套方案在性能和功耗上的表现,会让你觉得前期的折腾是值得的。
如果你也在捣鼓类似的电池供电产品,希望这篇记录能帮你少踩几个坑。后续我还想继续分享在这套方案上扩展出的“基于 RTC 的定时唤醒数据采集”以及“电源健康状态上报到上位机的协议设计”,到时候再接着聊。