
一台需要在户外连续跑十几个小时的便携数据采集设备电源方案却让我推翻重来了三次最后才定下 PCA9422 PIC18F85J10 这套组合。这两颗芯片一个管电一个管策略PCA9422 负责锂电池充电、USB 输入管理、各路电压输出和基本的过压过流保护PIC18F85J10 负责上电时序、工作状态切换、按键与中断处理以及异常时的数据保存和关机流程。整套做下来BOM 比原先用分离元件拼的方案少了一大半调试反而省了更多时间。如果你也在做带锂电池、需要 USB 充电、同时还要 3.3V/1.8V/5V 多路电源轨的便携产品这篇内容可以直接当参考。1. 为什么不用一堆分立器件而要上一颗PMIC1.1 分立方案的三个痛点先说说我用过的反面教材。第一版方案很“传统”一颗单节锂电充电管理芯片负责充电一颗升压芯片把电池电压抬到 5V再挂两颗 LDO 出 3.3V 和 1.8V充电状态靠充电芯片的 STAT 引脚接 LED电压检测用比较器搭窗口上电时序靠 RC 延时加逻辑门。参数标称都能对上实际联调的时候问题全出来了。第一个痛点是 BOM 和面积。充电、升压、LDO、比较器、逻辑门加上配套的电容电阻一共多出十几个器件。对一块大板子来说无所谓但设备要做成手持式PCB 面积就被电源部分吃掉一大块。第二个痛点是上电时序。分立方案里各路电源的延时完全靠 RC 常数和逻辑门凑温度一变、电容容差一变顺序就可能翻转。外设里最怕这个尤其是同时挂 SD 卡和液晶屏的时候电源顺序错了总线竞争、闩锁、初始化失败什么情况都能遇到。第三个痛点是故障处理。充电过温、电池反接、输出短路分立的保护逻辑散布在各芯片里状态信号要么没有要么只有一根引脚MCU 根本拿不到完整的电源状态。出了问题只能拿示波器从头查非常痛苦。1.2 这套架构的分工换到 PCA9422 之后输入端、充电通路、电源路径、各路输出轨、NTC 温度检测、I2C 状态回读全部集成在一颗芯片里。PIC18F85J10 的角色不是“参与供电”而是“管理供电”它通过 I2C 读写芯片的配置寄存器和状态寄存器决定什么时候开启哪一路输出、什么时候进入充电、检测到故障后怎么响应。两者分工如下表功能模块承担方具体职责充电管理PCA9422CC/CV 充电曲线、输入限流、温度窗口、充电截止电源路径PCA9422USB 在位时由外部供电并同时充电拔掉后自动切到电池电源输出PCA9422升压 5V、降压、LDO 输出多路低压轨参数配置PIC18F85J10上电后通过 I2C 写入充电电压、电流、使能位状态判断PIC18F85J10读取状态寄存器、按键、IRQ 中断驱动状态机异常处理PIC18F85J10掉电保存、关闭非必要外设、进入低功耗或安全关机这套模式最值得推荐的地方在于MCU 拿到的是一份“结构化”的电源状态而不是几根电平信号。充电中、充电完成、输入插入、温度异常芯片都会置位对应标志并拉低 IRQMCU 轮询或者中断处理都方便。1.3 选型时最该看的三个参数不是所有带充电的 PMIC 都适合你的产品我后来总结出三个必看参数输入限流挡位。需要能配到 USB 枚举后的 500mA否则插电脑充电会被识别成非法负载。输出轨的数量和电流能力。像我这个项目一颗搞定 5V 升压 3.3V 主轨 1.8V 模拟轨BOM 才真正省下来。中断/状态信息来源。至少要能区分充电完成、充电故障、输入插入、温度过限几类事件。另外PMIC 封装通常不大散热一定不能忽略。芯片底部的散热焊盘要好好焊最好打过孔到地层。全速充电时裸片温度上升很明显内置热折返会主动降低充电电流所以 layout 阶段就要把热通路留好。2. PCA9422 电源侧资源盘点充电、电源路径和输出轨2.1 充电链路PCA9422 的充电部分是典型的 CC/CV 方案针对单节锂电。整体流程电池电压低于约 2.9V具体以手册为准时先小电流预充回到安全电压后才进入恒流快充接近目标电压4.2V 或 4.35V可通过寄存器配置后转入恒压电流逐渐下降降到终止电流一般是设定值的 1/10时判为充电完成。实际配置时我建议把终止电流设高一点比如 60mA 左右。设太低恒压阶段拖得特别长最后那 10mA 的电流可能要磨半个小时对用户体验是负优化。输入侧还有 USB 枚举和输入限流的问题插电脑时按 100mA/500mA 两档切换插适配器时再切成适配器限流。如果不做输入限流电脑 USB 口会先保护起来——这个我在第一版方案里吃过亏。2.2 电源输出轨这颗芯片上的电源轨组合大致是一路 5V 升压、一路降压、一到两路 LDO。这里要提醒一下升压是从电池电压往上抬电池电压低到 3.0V 以下时同样输出电流需要更大的输入电流输出能力会跟着下降。设计时不要按标称最大电流打满留 20% 余量。我们板子的实际分配如下输出轨电压用途电流余量升压5.0V传感器偏置、USB OTG 供电300mA 负载留 200mA降压3.3VMCU、逻辑电路、显示屏400mA 负载留 100mALDO11.8V模拟前端、基准50mA 负载留 30mALDO23.3V无线模块独立供电按协议峰值配无线模块我单独挂了一路 LDO这样模块发射时的大电流脉冲不会直接砸在 MCU 的 3.3V 轨上实测对屏幕闪烁和 ADC 噪声都有明显改善。如果无线模块和主控共轨发射瞬间电压跌落很容易把 MCU 拉进复位。2.3 电源路径管理电源路径是这颗芯片最值钱的功能之一。USB/适配器插入时系统负载直接从外部输入取电同时充电电路给电池充电外部输入拔掉后立刻无缝切换到电池供电。这意味着电池彻底放空、电压低于系统最低工作电压时只要插上 USB系统依然能立刻启动而不是要先等电池充到某个电压才能开机。对便携设备来说这个特性太关键了。我遇到过不少板子电池没电就得等充半天才能开机用户体验很差。电源路径做在芯片内部还省掉了一颗理想二极管控制器和周边元件这也是 BOM 大幅减少的原因。2.4 I2C 控制面芯片所有充电参数、输出轨使能、中断屏蔽、ADC 使能都挂在 I2C 寄存器上。我按用途把它分成四组设备信息组芯片 ID、版本上电先读这个确认 I2C 通路。充电控制组充电电压、快充电流、预充电流、终止电流、输入限流。输出控制组各路轨的使能、放电、电压设定。状态/中断组当前状态、各类事件标志、IRQ 输出使能。内置 ADC 可以回读电池电压、充电电流和芯片结温这个对后面的电量估算和热保护非常有用等于省掉了一颗独立的电池监视 ADC。下面代码里出现的寄存器宏是示意命名具体地址和位定义以芯片手册为准。3. PIC18F85J10 的角色I2C 主控、状态机和故障响应3.1 硬件连接与引脚分配系统里 PIC18F85J10 是唯一的主控外部只要一个 8MHz 晶振或者直接用内部振荡器都行代码量真不大。硬件连接就几根线但每根都有讲究PCA9422 引脚PIC18F85J10 引脚说明SCL硬件 I2C SCLMSSP400kHz上拉电阻 2.2k 到 3.3VSDA硬件 I2C SDAMSSP同上布线远离升压电感IRQINT0边沿触发芯片事件通知低有效使能相关普通 GPIO 输出控制 5V 轨和低功耗模式—按键输入内部上拉开机/关机按键选 PIC18F85J10 的原因一个是它有硬件 MSSP 模块发 I2C 不占 CPU另一个是 nanoWatt 低功耗模式系统空闲时可以睡下去电源状态完全交给 PMIC 维持。这里提醒一句IRQ 一定要接边沿触发而不是电平触发否则事件持续期间中断会在主循环里反复进入把系统卡死。3.2 I2C 读写实现代码用的是 MSSP 主模式400kHz。芯片手册里没特别说明的话标准 7 位地址加寄存器寻址就行。写一个字节的流程是发起 START、发芯片地址写位、发寄存器地址、发数据、STOP。读一个字节稍微绕一点要先写寄存器地址再发一次 START 转成读方向。uint8_t pmic_read_reg(uint8_t reg) { uint8_t v 0; i2c_start(); i2c_write((PMIC_I2C_ADDR 1) | 0); // 写方向 i2c_write(reg); i2c_restart(); i2c_write((PMIC_I2C_ADDR 1) | 1); // 读方向 v i2c_read_nack(); i2c_stop(); return v; }这里最容易翻车的是总线被从设备拉伸时钟。PCA9422 内部有些寄存器在 ADC 转换期间可能需要拉着 SCL主控必须支持时钟拉伸或者干脆把速率降到 100kHz。PIC 的 MSSP 主模式对时钟拉伸的支持要看具体硅版本我建议量产固件里加一个带超时的重试机制任何一次 I2C 操作超过 5ms 没有完成就重新初始化总线。3.3 中断与事件处理电源事件用中断处理而不是轮询好处是 CPU 大部分时间可以睡觉。我的做法是 IRQ 进中断后只置位一个事件标志主循环里再去读状态寄存器判断是充电完成、输入插入、温度过限还是充电故障然后驱动状态机。注意大部分 PMIC 的中断标志是读后清除或者需要写清除的进中断服务函数第一件事就是把标志读出来清掉不然中断会一直触发。我已经不止一次在联调时看到 IRQ 一直拉低查了半天发现是没清标志。3.4 低功耗配合PIC18F85J10 的 nanoWatt 模式很适合这个场景。系统空闲进入 SLEEP此时只有 PMIC 的中断能把它唤醒。电池供电时主控睡、PMIC 继续维持 3.3V 轨、无线模块休眠整机静态电流能做到几十微安级别。唯一要小心的是进入 SLEEP 之前要把 I2C 总线状态收拾干净避免挂在半截传输上把总线占住那样下次唤醒后第一次读寄存器就会超时。4. 上电时序设计从电池抵达系统启动4.1 为什么要按顺序上电很多人觉得上电时序是玄学直到有一天看到系统偶发性死机示波器一抓发现 3.3V 轨起来时 SD 卡还在复位卡初始化时序正好被破坏。上电顺序的本质是保证每个器件在初始化之前它的供电、复位和其它依赖关系已经就绪。乱序上电还会造成浪涌叠加多路电源同时启动时输入电容瞬间充电电流可能把 PMIC 打到限流保护。所以我在这个设计里把上电过程明确成状态机的第一步而不是简单地把所有使能位一次打开。4.2 我们的时序实现实测下来这套设备的上电顺序是按键按下或 USB 插入PMIC 先输出 3.3V 主轨PIC18F85J10 上电启动。MCU 复位后立刻用 I2C 配置芯片充电电压、输入限流、输出轨使能、中断屏蔽。等主轨稳定 10ms再使能 1.8V LDO给模拟前端供电。等 5ms使能 3.3V 第二路 LDO给无线模块供电。等 10ms最后使能 5V 升压确认升压输出 OK 后再点亮外设状态灯。实现上就是一个简单的状态机每步之间通过延时和寄存器回读确认void power_on_sequence(void) { // 第一步配置充电参数示例值以手册为准 pmic_write_reg(PMIC_REG_CHG_CTRL, 0x3A); // 第二步使能 1.8V LDO pmic_write_reg(PMIC_REG_LDO1_EN, 0x01); delay_ms(5); // 第三步使能 3.3V 第二路 LDO pmic_write_reg(PMIC_REG_LDO2_EN, 0x01); delay_ms(10); // 最后使能 5V 升压并回读确认 pmic_write_reg(PMIC_REG_BOOST_EN, 0x01); while (!(pmic_read_reg(PMIC_REG_STATUS) BOOST_OK)) { if (timeout 50) { enter_fault(); return; } } system_ready 1; }注意 5V 升压一定要最后开。升压输出电容容量大启动瞬间需要一个不小的浪涌电流如果此时 3.3V 主轨的外设还在初始化可能会触发输入欠压。实测中出现过一次主控没复位但传感器那边读回来的数据乱了一帧。4.3 掉电保护与安全关机掉电分两种电池电压缓慢下降和瞬时跌落。瞬时跌落通常是外设大电流造成的PMIC 自己有过压过流保护不用太担心。真正要处理的是持续下降到 MCU 无法稳定工作的临界点。我的方案是设置一个关机电压阈值比如 3.3V通过 PMIC 的 ADC 周期回读电池电压连续三次低于阈值且没有输入电源时进入关机状态机先向传感器发停止命令把当前配置写回 EEPROM然后关闭无线模块等 20ms把 5V 和 LDO 依次关掉最后只保留主控的掉电监测。整个流程不超过 200ms和电池剩余容量完全耗尽的速度相比操作窗口绰绰有余。5. 充电管理和电量监测的工程化细节5.1 充电参数设置充电参数不是“照着典型值抄”就行要结合输入方式和热设计。插电脑 USB输入限流先按 100mA枚举后切到 500mA充电电流我设成 400mA留 100mA 给系统负载。插适配器输入限流可以放到 1A但充电电流还是控制在 600mA。原因很简单这颗芯片的封装不大充电电流产生的热量集中在裸片上600mA 快充连续工作二十分钟芯片表面温度会明显升高内置热折返会悄悄把充电电流降下来。与其让它自己降不如在参数上留余量让充电时间可预期。这里还有个参数陷阱充电截止电压。同一颗电芯4.2V 和 4.35V 的截止电压对容量影响很大但 4.35V 电芯对充电精度要求更高。如果你的电芯规格书上写的是 4.2V千万别为了容量去配 4.35V循环寿命会肉眼可见地衰减掉。5.2 NTC 温度窗口与常见翻车点充电安全离不开温度窗口。芯片的 TS 引脚接电池组里的 NTC常温下建议 0°C 到 45°C 才允许快充。这里有个特别容易翻车的细节如果产品暂时没接热敏电阻TS 引脚不能悬空悬空时芯片可能误判温度异常直接停充。要在硬件上用一个固定电阻网络模拟 25°C让系统先跑起来等电池组带 NTC 之后再改。识别 NTC 分压阈值的寄存器组也可以配置迟滞电压我建议默认值就行不要试图把窗口收太窄否则冬天在户外充电经常会莫名其妙停充。5.3 电量显示的务实方案PCA9422 内置 ADC 能回读电池电压和充电电流但它不是电量计不能直接当 fuel gauge 用。对于这类成本敏感的便携设备我用的方案是电压-SOC 对照表加迟滞。具体做法是用 10% 步进从数据手册或实测中取一条“静态电压 vs SOC”曲线存到 Flash运行时每隔 30 秒采一次电压查表得到电量显示时加 5% 的迟滞防止跳变。这个方案精度在 ±10% 左右胜在零成本而且掉电不丢失。如果产品后续对电量精度有要求可以再外挂一颗带库仑计的电量计芯片通信接口走同一个 I2C 总线固件不用大改。5.4 充电状态的人机交互状态指示我用一颗双色 LED红色常亮等于充电中绿色常亮等于充电完成红绿交替等于故障灭灯表示无输入且电池正常。实现上不是用 PMIC 的 STAT 引脚直驱而是 MCU 读状态寄存器后驱动这样所有显示逻辑统一在主控手里以后加休眠、呼吸灯效果都不用改硬件。6. 实测数据和踩坑记录手册不会主动告诉你的那些事6.1 寄存器默认值的坑第一处坑是芯片的看门狗。某些 PMIC 加电后看门狗默认在跑如果 MCU 在指定时间内通常几十到几百毫秒没有喂狗芯片会自己复位所有寄存器回到默认值。我试过一版固件开机后先去跑传感器初始化再回来配 PMIC结果 500ms 后系统整个重来。解决办法很简单复位后第一件事就是 I2C 配置把看门狗关掉或改成最长超时然后再做其它初始化。第二处坑是 ADC 默认关闭。状态寄存器里能看到电压但那是因为内部有快速粗采如果要在运行中做电量估算记得显式打开 ADC 并配置采样通道和周期否则读到的一直是上一次的快照。第三处坑是 I2C 设备地址。数据手册默认地址不一定是你买到的丝印版本不同批次可能用不同引脚配置决定地址位。上电后先读设备 ID 寄存器校验通过了再继续别盲调。6.2 I2C 波形与抗干扰400kHz 下10k 上拉基本是不行的实测 SDA 上升沿明显变慢偶尔出现 ACK 丢位。后来全部换成 2.2k 上拉波形才干净。另外升压电感附近的磁场会把噪声耦合到 I2C 线上尤其是充电电流大、电感又是开磁路的时候干扰会在 SCL 上打出毛刺导致从设备误判时钟。Layout 上 I2C 走线尽量短、远离电感不要为了省事穿到电源底下。实在躲不开就加 33Ω 串联电阻并减小上拉。6.3 系统功耗实测整机各状态实测数据如下3.7V 电池、常温状态电流说明运行 无线模块发送68mA峰值持续 10ms运行 无线模块待机21mA主控工作、传感器周期采样低功耗待机0.4mAMCU SLEEP、模块休眠关机20uAPMIC 维持最小系统充电中系统运行总输入 650mA600mA 充电 50mA 系统低功耗待机里的 0.4mA 大部分是无线模块的休眠漏电主控加 PCA9422 本身贡献很小。想再往下压只能从模块选型下手PMIC 这边基本到底了。6.4 改版建议清单做完两版之后我把检查项固化成了清单每次改板都过一遍电池连接器附近放 100nF 10uF 去耦上电瞬间的插拔电流要靠它吸收。升压电感选屏蔽式额定电流至少是最大负载的 1.5 倍。PMIC 的散热焊盘必须打孔到地层不要只靠顶层铜皮。按键引脚在 PMIC 上电期间的电平要确认避免一插电池就误触发开机。所有使能脚配置成明确电平后再操作 I2C防止外部器件在 MCU 复位期间浮空。最后再分享一个小技巧MCU 复位期间所有 GPIO 会短暂处于高阻态如果某个引脚正好连到外设的使能端外设可能在上电瞬间被误启动。我在原理图阶段就把这类引脚加上下拉电阻固定到安全电平这个问题从此再没出现过。电源管理这种东西大部分时间在跟不确定的时序和噪声搏斗把这些边界条件提前焊死在硬件里固件才能活得轻松。