资讯动态

PCA9422 + PIC32MX 构建低功耗电池设备完整电源管理方案

发布时间:2026/10/9 21:57:25 来源:尧图企业网站定制
我最近把一个户外采集器的电源方案整个重做了一遍。核心思路不复杂用 PCA9422 做前端电源管理用 PIC32MX795F512L 做主控把充电、多路输出、电压监测、休眠唤醒全部收到同一套 I2C 寄存器体系里。之前那版方案是分立 LDO 加独立充电模块外围器件多休眠电流一直压不下去加功能就得加器件系统越来越难维护。换到这两颗芯片之后供电链路清晰了固件侧的状态机也顺了。这篇文章不聊纸面参数只讲我完成这套“完整电源管理”方案时怎么选型、怎么配寄存器、怎么调状态机以及在实测里踩过的几个坑对正在做低功耗电池设备的朋友应该有参考价值。1. 项目起点为什么把电源管理交给一对专用芯片1.1 系统的真实需求完整电源管理到底指什么很多时候大家聊电源管理以为就是选一个 DCDC 再加个 LDO把电压供出来就行。真放到电池供电的产品里会发现“把电供上”只是最表层的问题。我这边设备的需求大致是电池输入范围 3.0V 到 4.2V主控需要 3.3V 数字轨模拟前端需要 1.8V 低噪声轨要支持 USB 充电还要实时知道充电状态系统需要在没有任务时进入低功耗休眠整机电流要压到几十微安级别休眠之后还要能被外部事件或定时器唤醒并且唤醒后要能快速恢复到正常工作。这些需求叠在一起就变成一套完整的电源管理问题充电要不要由主控管理是硬件自动充还是软件介入多路输出怎么分配是先上 3.3V 还是先上 1.8V谁去使能休眠时哪一路电源可以关掉哪一路必须保持电池电压掉到多少伏要开始保护数据而不是等掉电瞬间才傻眼。之前我拿分离器件拼的方案每个问题都要单独想办法而这次直接用 PMIC 加 MCU 的组合等于把充电、供电、监控这些杂事统一成一组寄存器读写思路顺畅很多。1.2 PCA9422 的定位充电与多路供电的前端集成PCA9422 是一颗面向便携设备的电源管理芯片内部集成了线性电池充电管理以及两路可配置输出的稳压通道还带 I2C 控制接口和中断输出。选它的主要原因有几点。第一它把最容易被忽视的充电路径管理做进去了USB 插入时系统优先走 USB同时给电池充电USB 拔掉后自动切到电池外部不需要额外加 PMOS 切换电路。第二两路输出都可以通过寄存器调整电压我可以用一模一样的硬件板子通过固件把电压改成 3.3V 或 1.8V对调试和多版本硬件很友好。第三它有一颗专门的中断输出脚能上报 VBUS 插入、充电完成、电池低压等事件配合 MCU 的外部中断就能实现真正的低功耗唤醒而不是让主控反复轮询。当然这颗芯片也有它的边界比如充电电流上限不算高所以它更适合中小容量电池的设备。做电动工具那种十几安培充电电流的场景直接另选其他方案会更合适。但在我这个采集器项目里电池容量在 2000mAh 左右充电电流几百毫安完全够用。1.3 为什么主控选 PIC32MX795F512L 而不选更低功耗的 MCU很多人会问既然做低功耗为什么不直接用一颗 Cortex-M0 或者更小的 8 位 MCU我选 PIC32MX795F512L 不是因为它功耗最低而是因为这颗器件把 USB、多个 UART、多路 ADC、比较器、I2C/SPI 全塞进了一颗芯片512KB Flash 和 128KB RAM 也让我不用抠着资源写代码。实际做下来PIC32MX795F512L 在 80MHz 全速运行时电流并不低但低功耗产品通常不是让主控一直全速跑而是“跑一下、睡很久”。所以真正重要的是它能进入合适的睡眠模式并且能被中断快速唤醒。PCA9422 的中断线直接接到 RB0 外部中断充电事件一发生MCU 从深度睡眠醒来也就是几个微秒级别的时间完全够用。另外PIC32 的 ADC 通道多我可以同时监测电池电压、PMIC 输出电流采样信号和温度 NTC这在做完整电源管理时特别方便不需要再外挂一颗专门的 ADC 芯片降低了不少系统成本和布局压力。2. 电源树设计从电池到每一路电压轨的实际走线2.1 电池输入级保护、路径管理与输入电容电池输入不是直接把电池焊到 PMIC 就完事。我在这条链路上加了 TVS 管做 ESD 防护后面接一颗 10μF 陶瓷电容和一颗 0.1μF 高频电容靠近 VBAT 引脚放置。这颗 PMIC 的 VBUS 引脚接 USB 的 5V 输入内部具备电源路径选择能力检测到 VBUS 有效时系统轨由 VBUS 供电同时把多余电流送去充电VBUS 断开后系统轨自动切到电池。这块完全由硬件完成不需要 MCU 介入所以即便系统已经进入深度睡眠插上 USB 充电线后设备也能安全供电和充电。这里有个很实际的经验输入电容不要只追求容量大要注意陶瓷电容的直流偏压特性。一颗标称 10μF 的 0603 电容在 5V 偏压下实际容量可能只有 3μF 左右所以我选了 0805 封装、额定电压 16V 的规格留足裕量避免输入电压跌落时 PMIC 误判。2.2 输出电压轨分配与去耦策略我的电源树里PCA9422 的 DCDC1 被配置成 3.3V专门给 PIC32MX795F512L 数字电源、Flash、外围数字逻辑供电DCDC2 被配置成 1.8V给模拟传感器、ADC 参考电压、运放供电。把模拟轨和数字轨分开非常有必要因为 DCDC 开关噪声会通过公共电源阻抗耦合到模拟部分直接表现为 ADC 读数跳动。去耦电容按通道布置每个输出端放 10μF 陶瓷电容做主储能再并一个 1μF 的低 ESR 电容靠近 PMIC 输出引脚到了负载端每个 IC 旁边再放 0.1μF 到 1μF 不等的去耦电容。PCB 布局上DCDC 的输入环路和输出环路要尽量短且粗功率地回流的路径不要和模拟地重叠。我在中间最窄处只留了一个单点连接也就是模拟地只通过一个 0 欧电阻或者直接窄铜皮在一点汇入系统地。2.3 上电顺序与使能控制虽然这颗 PMIC 的两路输出默认上电就会启动但我在实际设计里把 DCDC2 的使能控制交给了 MCU 的一个 GPIO 管脚。也就是说每次系统复位后DCDC1 先给主控供电PIC32 启动完成、端口初始化完毕之后再去拉高 GPIO 使能 DCDC2模拟部分才开始工作。这样做有两个好处一是避免模拟传感器上电瞬间的浪涌电流拉低 3.3V导致主控复位二是休眠时可以通过软件把 DCDC2 关断彻底断开模拟前端的供电减少漏电通路。2.4 测量电源质量的几个小技巧想判断电源设计有没有问题一定要学会看纹波。用示波器测纹波时把带宽限制开到 20MHz探头使用弹簧接地短线把探头尖直接点在输出电容正极接地环压在电容负极这样测出来的数据才是真实的开关纹波。我之前用过普通长地线夹子测出来有 80mV 峰峰值一开始以为是 PCB 布局问题换成弹簧地线后实际纹波只有 15mV完全是虚惊一场。3. I2C 寄存器配置充电参数与输出电压的计算逻辑3.1 先读懂寄存器地图地址、默认值与写保护使用 PCA9422 的第一步不是急着写代码而是要把寄存器地图结构搞清楚。这类 PMIC 通常包含设备 ID 寄存器、充电控制寄存器、DCDC 输出电压配置寄存器、中断状态寄存器、模式控制寄存器。上电后 PMIC 会用内部默认配置输出一组电压和电流MCU 需要在这一基础上做覆盖写入。我的建议是先读 ID 寄存器做一次通信握手确认 I2C 地址正确、器件活着然后再开始配置。另外要注意有些寄存器是 write-once 的误写后只能靠重新上电恢复调试起来很痛苦。为保险起见每次写入后都立即读回对比一旦不一致就进入错误上报分支。3.2 充电电流和终止电压的计算过程充电参数设计直接决定电池寿命和充电时长。我选了一块 2000mAh 的锂电池终止电压 4.2V。充电电流我设置成了 320mA大约 0.16C。对电池来说这个倍率相当温和充电发热很小基本不会触发 PMIC 内部温度保护。充电时间可以用一个工程近似来估算恒流恒压充电的总时长大约是容量除以充电电流再乘 1.2 到 1.5 的经验系数。按 2000mAh / 320mA 计算理论恒流段约 6.25 小时加上恒压段收尾阶段电流逐步下降完整充满大概在 7 到 8 小时。如果项目对充电速度有硬指标就需要把电流上调但这时要重新评估 PCB 铜宽和散热。终止电压不能乱设。4.2V 是常规电池标准但如果电池电芯本身支持 4.35V可以在寄存器里改。我提醒一句用 4.35V 满充确实能多出一些容量代价是电池循环寿命下降长期高温下鼓包风险也会增加。户外采集器这类设备我更看重可靠性所以一直用 4.2V。3.3 输出电压、限流与动态功耗调节DCDC 输出电压寄存器通常按固定步进划分。在代码里我会把配置做成带注释的宏定义而不是直接填数字。比如 DCDC1 目标 3.3V对应某个字段值DCDC2 目标 1.8V对应另一个字段值。这里有个动态调压的玩法PIC32 在 80MHz 全速跑时3.3V 电压是必要的但如果某个阶段只做定时采集主频降到 10MHz此时把 DCDC1 电压临时调到 3.0V 也能正常工作这样可以省下一点动态功耗。不过要小心Flash 在较高频率读写时对电压有最低要求降压过头会导致程序跑飞。我实测下来的可接受下限在 2.9V 左右但为了稳动态调压路径我暂时没有用到产品模式里只在验证阶段玩过。数据手册给定的最小工作电压才是最终约束。3.4 初始化代码与 I2C 时序的实操细节下面是一段精简的初始化代码骨架用来说明写 PMIC 寄存器的基本套路。寄存器编号我会用功能宏代替具体编号请以你手头的数据手册为准。#define PMIC_I2C_ADDR 0xA8 // 7位地址实际由硬件ADDR引脚决定 #define PMIC_REG_CHG 0x10 #define PMIC_REG_DCDC1 0x20 #define PMIC_REG_DCDC2 0x21 #define PMIC_REG_STATUS 0x30 uint8_t pmic_write(uint8_t reg, uint8_t val) { uint8_t tx[2] {reg, val}; return i2c_master_write(PMIC_I2C_ADDR, tx, 2); } void pmic_init(void) { // 充电电流320mA终止电压4.2V while (pmic_write(PMIC_REG_CHG, 0x0C) ! 0); // DCDC1输出3.3V while (pmic_write(PMIC_REG_DCDC1, 0x1B) ! 0); // DCDC2输出1.8V while (pmic_write(PMIC_REG_DCDC2, 0x06) ! 0); }这里如果 I2C 驱动本身重试机制做得好可以让pmic_write返回非零后自动重试。实测中我遇到过 PMIC 刚上电的前几百微秒内 I2C 外设还没完全稳定连续写入会偶发 NACK所以后来我在初始化等待里加了至少 5ms 的延时之后通信就稳定了。4. 固件状态机充电、运行、休眠、唤醒的闭环4.1 系统状态定义与迁移条件电源管理不能散落在主循环的各个角落我最后把它收敛成了一个显式状态机。状态包括BOOT、RUN、CHARGE、SLEEP、BATLOW。BOOT 是上电初始化完成 PMIC 寄存器的写入和内部数据恢复RUN 是正常采集和通信充电事件通过中断异步进入 CHARGESLEEP 是低功耗待机可以定时醒来或由外设事件唤醒BATLOW 是低压保护状态只保留最低限度进程比如保存关键数据到 Flash然后进入深度睡眠。状态迁移关系很直接BOOT 完成后进 RUN检测到 VBUS 插入进 CHARGE充电完成后退回 RUN运行中电量低进 BATLOW收到休眠指令进 SLEEP睡眠中被充电插拔或定时器唤醒后回到 RUN。4.2 充电管理状态轮询、充电完成与错误处理PMIC 硬件会自动执行恒流恒压充电但完整充电流程还是需要 MCU 参与管理状态。我在主循环里周期读取 PMIC 状态寄存器识别充电中、充电完成、充电故障三类事件。充电完成通常发生在电流降到某个阈值时PMIC 会相应置位状态位并拉低中断引脚。错误处理要兜底如果充电时电池温度过高PMIC 可能有内部保护也可能需要 MCU 通过 NTC 读取温度自行切断充电。我的做法是在状态机里保留一个“温度异常”分支一旦检测到温度超阈值直接通过寄存器停止充电直到温度回落再恢复。户外设备夏天太阳直射下外壳温度可能很高这个保护逻辑很实用。4.3 休眠与唤醒PCA9422 中断线如何接进 MCU低功耗休眠的关键是把 PMIC 的中断输出接到 MCU 的外部中断引脚。PCA9422 的中断脚通常是开漏输出低电平有效我把它接到 PIC32MX795F512L 的 RB0/INT0并在引脚上加了一个 10kΩ 上拉电阻。休眠前需要做的准备工作比想象中多先把 DCDC2 输出关闭然后关掉传感器供电再把 PMIC 配置成允许 VBUS 插入、充电完成、电池低压这几类事件触发中断最后 MCU 执行睡眠指令。外部事件来时PMIC 把 INT 拉低MCU 从睡眠中被唤醒进入中断服务函数去读取 PMIC 的中断状态寄存器清标志后再恢复 DCDC2。这里最容易被忽略的是中断标志清理顺序。我最初是先清 MCU 外部中断标志再去读 PMIC 状态寄存器结果下次睡眠前又发生了一次误触发原因就是 PMIC 的 INT 引脚还没恢复高电平MCU 再次被拉低唤醒。后来改成“先读 PMIC 状态、清 PMIC 中断标志、再清 MCU 外部中断标志”整个系统才安静下来。4.4 实现要点不要在主循环里直接写 PMIC 寄存器一个容易犯的错误是把 PMIC 操作直接塞进主循环的某个业务分支里。I2C 写入本质是阻塞操作在等总线期间会耽误传感器采集和通信。我现在的做法是把 PMIC 相关操作包装成一个事件请求比如“请求进入充电模式”“请求关闭 DCDC2”然后由统一的状态机在合适的时候真正执行 I2C 写入。这样主循环永远保持非阻塞PMIC 的寄存器读写只发生在状态切换点调试时问题也好定位。5. 实测排坑三个典型问题的完整排查链路5.1 ADC 采集噪声从“数据跳动”到“DCDC 开关耦合”的定位系统联调时我发现 ADC 读到的电压值在每次系统唤醒后都会出现规律性跳动幅度大约有 30mV已经超出传感器手册给的噪声底线。我第一反应是传感器干扰结果把传感器断开后主控内部 ADC 采样依然有跳动。于是我用示波器挂了 ADC 采样引脚的波形发现采样保持期间有大约 80mV 的毛刺频率恰好等于 PMIC DCDC1 的开关频率。这就基本锁定噪声是从 1.8V 电源轨上耦合进来的。因为模拟电源轨同样由 PMIC 的 DCDC2 输出DCDC1 的开关噪声通过共用的输入电源或地平面耦合到了 DCDC2。最终我做了两处改动一是让 ADC 采样延时到 DCDC 开关周期相对平稳的时间点二是在 1.8V 输出到 ADC 参考引脚之间加了一级 RC 低通滤波时间常数约 2μs。改完之后噪声降到了 5mV 以内问题解决。5.2 I2C 偶发 NACK时钟速率与上拉电阻的联合排查系统进入低功耗模式后I2C 通信变得不太稳定主要表现为初始化阶段偶发写失败重试两三次后才能成功。我用示波器同时抓 SCL 和 SDA发现 SDA 在时钟下降后建立时间明显不足信号波形在门槛电压附近缓慢爬升这是典型的上升沿过缓。排查下来根因有两个一个是 I2C 总线上的上拉电阻用了 10kΩ对 400kHz 速率来说太大另一个是 PMIC 和主控之间的走线穿过了两层板总线上还挂了另一个传感器等效电容比预想大。解决办法是把上拉电阻换成 2.2kΩ同时把 I2C 速率从 400kHz 降到 100kHz。PMIC 的控制寄存器操作并不频繁100kHz 完全够用可靠性的优先级更高。改完后连续跑了两天没有一次 NACK。5.3 电池低压瞬间掉电引起的 MCU 复位第一次户外试用时电池电压低于 3.2V 后设备开始反复复位最后一次数据没有保存。用电池监测脚看电压发现负载一加重电池端电压瞬间跌到 3.0V 以下PMIC 内部欠压保护直接切断了输出MCU 来不及保存数据就掉电了。这不是单纯降低 PMIC 保护阈值能解决的事因为电池有内阻负载越大电压跌落越严重。我最后给出的方案是让 MCU 在 BATLOW 进入条件上做提前量当电池电压低于 3.4V 时立即停止采集先把关键数据和文件系统日志保存好再进入深度休眠。这样就算电池继续缓慢放电PMIC 的硬件保护仍然在 MCU 后面兜底数据不会再丢。5.4 休眠电流测量误区万用表串联导致的电压跌落调试休眠电流那天我把万用表电流档串进电源正极读数一直不太对而且 MCU 偶尔还会复位。后来发现万用表电流档内阻带来的压降接近 300mV在系统从休眠唤醒瞬间瞬间电流会让电压跌得更多导致 PMIC 误判电池电压不足直接把系统切断了。准确做法是串一个 1Ω 精密采样电阻用示波器差分档测电阻两端电压再换算成电流。这样既能看见休眠平均电流也能捕捉到唤醒瞬间的电流尖峰。我顺手把唤醒瞬间的 2ms 电流尖峰记录了下来这组数据对后面优化低功耗启动逻辑非常有帮助。6. 功耗数据与后续优化建议6.1 实测功耗数据表经过这一轮改造整机功耗已经完全可接受。以下是实测数据数据来自同批次三块板子的平均值。工作模式电流说明全速运行80MHz外设全开38 mA主要用于调试和通信普通运行10MHz周期采集6.8 mA常规工作状态休眠RTC 定时唤醒47 µADCDC2 关闭主控睡眠深度休眠等待外部事件唤醒12 µAPMIC 低功耗模式MCU 深度睡眠充电中额外电流320 mA充电电流占大头这个数据比最初用分立方案时低了不止一个量级之前仅休眠电路就有 800µA。对于一块 2000mAh 的电池正常一天几次采集加无线上报可以用到一个月以上。6.2 进一步优化方向如果后面要把功耗再往下压我会优先做三件事。一是尝试在轻载时把 PMIC 的 DCDC 切换到 PFM 模式让待机效率进一步提高二是对模拟前端做更细的电源域拆分把用不到的传感器轨彻底断电而不是只是关闭模块三是把 PIC32MX795F512L 的时钟树重新调整睡眠状态下只保留 32kHz 辅助振荡器给 RTC其他所有高频振荡器全部关闭。另外我还打算把充电状态和电池电压日志做成统一事件队列配合无线模块上报到后台这样室外设备即使无人值守也能远程看到电池健康和充电异常。电源管理这件事做到这个程度才算是真正闭环了。

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

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

免费获取报价 →
↑