PCA9422与PIC32MX470F512H的便携设备电源管理系统设计
发布时间:2026/10/24 3:25:40 锦皓数字建站

做便携电池设备这些年我越来越觉得电源管理不是接个 LDO 就完事的事情。最近一款便携数据采集终端项目里我锁定了 PCA9422 这颗 PMIC 配合 PIC32MX470F512H 做主控把它俩搭成了一套完整的电源管理系统。整个过程走下来从硬件布局到 I2C 寄存器配置再到低功耗调度有不少值得记录的经验这篇文章就把这趟实现过程完整拆开讲清楚。1. 为什么把 PMIC 和 MCU 凑在一起一个带电池便携系统的真实痛点1.1 传统模块拼接方案的三个坑之前做过好几个类似的小设备最开始图省事直接一片 5V 升压模块、一片 3.3V LDO、一片锂电池充电板拼在一起。看起来每个模块都成熟稳定但拼起来问题不少。先说充电部分。普通充电板只管把电池充满至于现在充了多少电是不是还在涓流阶段温度有没有异常完全拿不到状态。想做个电量显示只能额外加库仑计成本和工作量立刻上去。再说各路电源之间的时序关系。MCU 和传感器同时上电经常出现 3.3V 还没稳定、外设已经初始化到一半的尴尬局面。最后是静态功耗每个模块都有自己固定的静态电流几块板子合起来动不动就好几毫安对电池设备来说完全不可接受。1.2 PMIC 不等于几路电源输出那么简单PMIC 和普通电源模块最大的区别在于它把自己当成系统的一部分。PCA9422 这种级别的芯片不是简单提供几路输出而是把整个电池充放电链路管理起来充电电流/电压可配有升压降压的电源路径切换有多路受控输出还能通过 I2C 回传各种状态。对我来说最有价值的其实是电源路径管理。什么意思就是电池和 USB 输入之间有一个智能切换插上 USB 时系统用外部电源供电同时给电池充电拔掉 USB 时无缝切到电池供电中间不能出现电压跌落或者重新上电的瞬间。这个功能如果自己用 MOSFET 搭光是设计防倒灌、防短路的电路就得折腾很久还容易翻车。1.3 MCU 在电源系统里的角色是管理层有了 PMIC 做执行层还需要一个管理层来决定什么时候充电、充多大电流、哪些外设供电、什么时候进入低功耗。这颗 PIC32MX470F512H 配合这套系统很对路。一方面PIC32MX 系列的外设资源很适配这种任务硬件 I2C 用来跟 PMIC 通信ADC 用来采样电池电压和充电电流定时器负责状态轮询UART/USB 负责跟外部通信。另一方面它的工作电压范围、时钟配置、低功耗模式也灵活可以在不同电源状态之间切换。提示MIPS M4K 内核的 PIC32MX 系列虽然算不上一线旗舰但做这种中等复杂度的便携设备很合适。512KB Flash 可以放下完整的电源管理协议栈128KB RAM 足够缓存应用数据。配套规划阶段我先把系统各路电源的需求整理成了一张表后面所有配置都以这张表为准。电源域电压峰值电流用途待机策略VSYS3.3V约600mA主控、LCD 背光、SD 卡背光休眠时关断VDD_1V81.8V约120mA传感器模拟电路待机模式下调低VBAT_IO电池电压约50mARTC、唤醒逻辑保持常开充电输入5V USB最大1A锂电池充电插入外部电源时启用2. PCA9422 的资源拆解充电、路径切换与多路输出背后的原理2.1 恒流/恒压充电的切换逻辑锂电池充电整个过程分三个阶段预充、恒流CC、恒压CV。PCA9422 的充电部分通过寄存器可以设置预充电流、恒流值、恒压目标值。实际配置时要注意一个容易忽略的地方恒流值不是随便设的它受输入能力和芯片散热能力的双重限制。我在这套系统里把充电电流设为 500mA恒压 4.2V。为什么 500mA因为设备用的是 18650 单节电池容量大概 2500mAh0.2C 充电对电池寿命更友好而且 500mA 对应的发热也更容易处理。如果图快直接设到 900mA小 PCB 板子在夏天持续充电时PMIC 表面温度很容易超过 80°C长期工作可靠性会打折扣。充电电流的实际计算可以简单理解成目标恒流值 设定值但芯片内部会实时比较输入电流、电池电压、芯片温度自动降额。这不是线性关系所以在选取时留出 20% 的余量比较稳妥。2.2 电源路径管理USB 插入那一瞬间发生了什么电源路径管理是整套方案里我觉得最值回票价的功能。没有它的时候系统由电池供电USB 插入后电池依然在放电等到充电电压高于电池电压才被动切换那一瞬间往往伴随一个几毫秒的电平跌落主控可能就复位了。PCA9422 的做法是检测到适配器插入后优先让系统从外部电源取电同时用剩余能力给电池充电。拔掉适配器时路径切换回电池整个过程由芯片内部硬件完成不需要主控干预。软件上只需要读取一个状态位确认事件发生。我在初始化时把这个状态位接到了主控的中断输入这样 USB 插拔可以打断主控的低功耗睡眠立刻调整系统行为。这比定时轮询省电得多。2.3 多路输出的分配和取舍PCA9422 内部提供多个可编程输出包括一路降压 DCDC 和若干 LDO。对这套系统我把降压输出配成固定的 3.3V 给数字部分LDO 给 1.8V 模拟域另外一组输出作为外设可控开关。关于 DCDC 和 LDO 的取舍原则是老规矩大电流、压差大的用 DCDC效率高、发热小小电流、对纹波敏感的用 LDO。传感器模拟电路 120mA 不算大1.8V 对纹波比较敏感用 LDO 更合适。如果全部用 LDO 从 4.2V 往下压压差大时效率只有 40% 左右静态电流也会浪费在发热上所以大电流路径绝对不能省掉 DCDC。2.4 保护机制不只是保险丝替代品PMIC 的保护电路值得多说两句。过压、过流、过温这些基础保护都有但实现时要注意它的响应行为过压保护之后是打嗝模式还是锁死充电过温是暂时降额还是直接停充我在调试时特意把状态寄存器在不同异常条件下读了一遍确认每个保护事件的状态位语义后面排查问题会节省大量时间。3. PIC32MX470F512H 侧的 I2C 主控设计接线、速率与初始化顺序3.1 引脚分配与电平配合PIC32MX470F512H 和 PCA9422 之间主要走 I2C另外还接一个 INT 引脚用于事件中断。PCA9422 的 I2C 地址由 ADDR 引脚决定。这里有个我一开始就踩到的坑I2C 地址不是固定的取决于 ADDR 引脚接高还是接低。设计原理图时一定要先确定 ADDR 接法再在软件里填对应的从机地址。我这次把 ADDR 接低从机地址是 0x08不含读写位7 位地址如果接高就得往后偏移。不同批次的寄存器手册写法也不完全一样最好用逻辑分析仪抓一次启动条件确认。引脚分配上I2C 的 SDA 和 SCL 分别接到了 PIC32 的两个可映射引脚。PIC32MX 系列外设引脚的映射能力很方便可以在初始化代码里把 UART、I2C 这些外设重新指到任意引脚不像有些 MCU 写死引脚、PCB 一画错就得割线。3.2 I2C 速率与上拉电阻的计算I2C 速率我选了 400kHz 的标准快速模式。PCA9422 和 PIC32 都支持这个速率但要注意总线电容对上拉电阻的影响。总线电容一般可以从 PCB 走线长度估算信号线上每厘米大约 0.7pF 到 1pF 寄生电容再加上芯片引脚的输入电容总线上两三个器件通常会在 20pF 到 50pF 之间。上拉电阻的取值要保证上升时间满足 400kHz 的要求I2C 规范里快速模式的上升沿时间要求是 300ns 以内。经验公式近似是上升时间约等于 RC 乘积50pF 电容配 4.7kΩ 电阻算出来大约是 235ns刚好满足。我最终在 SDA 和 SCL 上各放了 4.7kΩ 上拉到 3.3V实测波形上升沿 250ns 左右余量适中。注意选 2.2kΩ 会让上升沿更快但会增加驱动电流和功耗对于电池设备不划算。4.7kΩ 是 3.3V 系统下兼顾功耗和速度的常用值。3.3 电源管理协议的初始化顺序先配充电还是先开输出PMIC 上电后默认状态可能不是我们最终想要的工作状态。我建议初始化按以下顺序执行原因是每个环节依赖前面的配置完成。首先等待 PMIC 的输入电源稳定。通过读取 I2C 通信是否成功来判断芯片是否就绪推荐在读取到有效设备 ID 之前不要做任何写操作。第二步配置充电参数充电电流、恒压目标、截止电流。这个顺序要在开路输出之前因为如果先让外设上电、再让充电电路开始工作插入 USB 的瞬间会有较大浪涌影响稳定性。第三步配置各路 DCDC/LDO 输出电压和限流。第四步使能需要保持常开的输出。最后使能中断事件。示例代码示意具体寄存器地址请对照原厂数据手册void pmic_init(void) { // 1. 等待 I2C 通信就绪 while (pmic_read_reg(REG_DEVICE_ID) 0xFF) { delay_ms(1); } // 2. 配置充电参数500mA 恒流4.2V 恒压100mA 截止 pmic_write_reg(REG_CHG_VOLTAGE, 0x42); // 例如 0x42 4.2V pmic_write_reg(REG_CHG_CURRENT, 0x50); // 例如 0x50 500mA pmic_write_reg(REG_CHG_TERM_CURR, 0x10); // 截止电流 100mA // 3. 配置 DCDC 输出为 3.3VLDO1 为 1.8V pmic_write_reg(REG_DCDC_VOUT, 0x33); pmic_write_reg(REG_LDO1_VOUT, 0x18); // 4. 使能需要保持常开的 LDO pmic_write_reg(REG_ENABLE, 0x01); // 5. 使能充电状态变化中断 pmic_write_reg(REG_INT_MASK, 0x00); }4. 电源管理软件框架用状态机把充电、运行、休眠串起来4.1 系统电源状态的定义硬件只是骨架真正让电源管理活起来的是软件状态机。我把系统分成了五个电源状态关机态、充电态、运行态、睡眠态、深度睡眠态。关机态只有 RTC 保持在电池直连的 LDO 上主控不工作。充电态插入 USB 或充电器后PMIC 给电池充电主控可以被唤醒处理充电事件。运行态主控和外设全部正常供电系统执行采集、存储、通信等任务。睡眠态LCD 背光关断传感器掉电主控进入空闲模式定时唤醒执行轻量任务。深度睡眠态除 RTC 和唤醒逻辑外其余全关主控进入睡眠模式电流压到微安级。这几个状态并不是简单的电平高低切换而是由 PMIC 的各路输出使能组合出来的。管理每一路输出的本质是控制寄存器里的对应使能位这比外接 MOSFET 去做电源开关要优雅得多。4.2 充电状态检测从寄存器到位域解读PMIC 会通过 I2C 寄存器暴露充电状态比如正在充电、充电完成、充电异常。轮询读取这些状态位虽然实现简单但浪费主控资源。更好的做法是把中断引脚接进 PIC32 的外部中断充电状态变化时由硬件事件驱动软件响应。我最后采用了中断事件 查询确认的组合收到中断后读取 PMIC 状态寄存器确认具体是哪个事件插入适配器、充电完成、过温等然后清除中断标志。这个组合既省电又不会漏事件。状态机的核心代码大概长这样typedef enum { POWER_SHUTDOWN 0, POWER_CHARGING, POWER_RUNNING, POWER_SLEEP, POWER_DEEPSLEEP } power_state_t; power_state_t power_current_state; void power_state_machine(pmic_event_t event) { switch (power_current_state) { case POWER_CHARGING: if (event PMIC_EVENT_CHARGE_DONE) { pmic_disable_charging(); power_current_state POWER_RUNNING; } else if (event PMIC_EVENT_ADAPTER_REMOVED) { power_current_state POWER_SLEEP; } break; case POWER_RUNNING: if (event PMIC_EVENT_ADAPTER_REMOVED) { pmic_set_output(LCD_PWR, OFF); power_current_state POWER_SLEEP; } break; case POWER_SLEEP: if (event PMIC_EVENT_WAKE_TIMER) { pmic_set_output(SENSOR_PWR, ON); power_current_state POWER_RUNNING; } break; default: // 关机态只能通过外部唤醒源触发 break; } }4.3 掉电保护和低功耗联动便携设备最怕的是电池没电时数据写一半就死掉。我在软件层做了两道保险第一道低电压阈值检测电池电压低于 3.3V 时不再启动高耗电任务系统降级运行第二道再低到 3.1V 时触发深度睡眠同时让 PMIC 关掉所有非必要输出只保留 RTC 电源域。这两道保险配合下来实测设备在静置状态下可以撑很长时间。具体的功耗数据在后面章节会列出。5. 硬件设计避坑布局、去耦与噪声控制5.1 电池接口到 PMIC 的输入路径电池输入路径看似简单其实有很多细节。第一电池连接器到 PMIC 电池引脚的走线要尽量短、尽量粗因为充电电流和系统瞬时电流都会走这段线线阻太大不仅降压还会导致传感器采样不准。我这块板子在电池路径上加了 0805 封装 100μF 的陶瓷电容有效缓解了负载瞬变时的电压跌落。第二电池端必须保留防反接保护。PCA9422 本身有输入保护但外部再加一个 P-MOS 防反接电路会更稳妥。有一次同事手滑把电池装反多亏了这个保护才没烧掉一片板子这属于花钱买保险的场景省不得。5.2 电感与电容选型对 DCDC 输出的影响PMIC 内部 DCDC 的电感和电容选型直接影响纹波和稳定性。电感值选小了纹波大选大了动态响应慢。这次选择的电感规格在数据手册推荐范围内直流电阻选的较小值满载时效率能多一两个百分点。电容方面输出电容主要看等效串联电阻ESR和容量输出端用了 22μF 陶瓷电容外加 10μF 钽电容的组合利用不同介质电容的频率特性互补纹波表现比单一电容方案好很多。这里有一个容易被忽略的问题MLCC 陶瓷电容在直流偏压下容量会大幅下降。例如 22μF 的 X5R 电容在 3.3V 偏压下实际容量可能只剩 60%。所以选型时不能只看标称值最好按降额后的有效容量计算。这也是为什么我并了一颗钽电容就是怕陶瓷电容在偏压下容量衰减导致输出不稳定。5.3 模拟地与功率地的处理系统里既有 DCDC 的开关噪声又有传感器的小信号PCB 布局时功率地和模拟地要处理好。我采用的是在 PMIC 底部单点连接两个地功率地走独立回路模拟地单独一条线回到 PMIC 下方中间不透传数字信号。这块板子实测下来传感器 ADC 的噪声底比之前模块拼接方案明显降低。5.4 电池电压采样走线电池电压采样必须走独立的感测线绝对不能和充电电流的路径共用。充电电流哪怕只有 500mA在几十毫欧的走线电阻上也会产生几十毫伏压降这个误差直接进 ADC 会让电量判断失真。所以我把电池正极的采样线单独拉了一根细线到 MCU 的 ADC 引脚ADC 引脚旁边还有一个小电容做滤波。采样时序上我会在充电关闭的瞬间多等 200ms 再去读取电压避免测量点正处于电流波动期。6. 实测数据与翻车记录效率、纹波、充电异常排查6.1 充电效率实测整个系统做完后我用电子负载和精密万用表做了几组实测。充电阶段用 USB 5V/1A 适配器输入输出到电池的平均充电效率约 87%。这部分损耗主要来自 PMIC 内部的路径电阻和降压变换属于正常水平。充电完成后的静态电流在深度睡眠状态整套系统PMIC MCU 睡眠大约是 28μA这个数据我非常满意比之前模块拼接方案两三百微安有了数量级提升。6.2 负载纹波实测DCDC 输出 3.3V 满载 600mA 时用示波器测量纹波峰峰值约 28mV。LDO 输出 1.8V 满载 120mA 时纹波约 6mV。这个水平对传感器模拟电路来说完全够用ADC 参考电压的抖动在可接受范围内。如果后续需要更低纹波可以再串一级 LC 滤波不过目前没有这个必要。6.3 待机功耗数字背后的调优过程实际功耗调优时有几个细节值得分享。第一PMIC 的空闲输出如果没有使用一定要通过寄存器显式关掉不能只靠软件不访问。曾经有路 LDO 默认就是使能的硬件上又不接负载白白浪费了几十微安。第二PIC32 在睡眠模式下外设时钟要逐个关闭。留着一个没有喂狗的超时定时器就能让睡眠电流多出 100μA 左右。把每一项都关干净了才有后面的 28μA 总电流。6.4 这次踩过的三个大坑先说第一个PMIC 的 NTC 热敏电阻引脚悬空导致充电异常。第一版硬件没有接电池温度检测以为不接也能工作实际上充电流程会因为检测不到温度而拒绝进入恒流阶段。对策是在这个引脚上接了 10kΩ 固定电阻模拟正常温度同时软件上读温度寄存器确认状态。第二个坑是 I2C 从机地址搞错。前面提到 ADDR 引脚接法决定地址我在第一版软件里照搬了默认地址结果通信失败。用逻辑分析仪抓总线后才确认最终地址比默认地址偏移了 2 个 bit属于读数据手册不仔细的典型失误。第三个坑是 LDO 输出电容 ESR 过高导致带载掉压。当时顺手从料箱里抓了一颗普通电解电容结果在负载突变时电压跌落了几百毫伏。换回低 ESR 陶瓷电容后恢复正常。这也印证了第 5 章说的PMIC 的每一路输出电容都应该认真对待不能随手拿一颗标称容量够的电容就往上焊。这三组数据记录下来之后我又把所有相关寄存器配置打印出来归档。后续如果换电池或者改负载特性这些原始数据可以用来快速重新调参。7. 从这个项目里沉淀下来的实践体会整套 PCA9422 PIC32MX470F512H 的电源管理方案做完我最大的体会是电源管理不是供电能亮就行它需要被当作一个独立的子系统来设计。从充电策略、路径管理、输出使能、状态监测到低功耗联动每一环都得提前想清楚。PMIC 解决了执行层面的问题但策略还是要靠 MCU 跑起来两者配合才能让设备在效率、稳定性和续航之间找到平衡点。最后分享一个可以继续扩展的方向后续如果产品需要支持 USB OTG 反向供电可以在现有架构上增加一路可配置的放电输出模式配合 MCU 的 USB 检测逻辑就能实现设备之间的电量互济。另外把充电日志和电量统计数据写入内部 Flash通过 UART 导出也能在量产阶段把每片设备的电源参数一致性做一个快速摸底。这些都是在现有软硬件框架上顺理成章能加的活儿不用再动板子设计这也是这类整体 PMIC 方案比模块拼接方案更耐用的原因之一。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。