资讯动态

MCU+PMIC协作的嵌入式电源管理系统设计:PCA9422与PIC24FJ256GB110实战

发布时间:2026/10/24 1:28:08 来源:尧图企业网站定制
做嵌入式电源设计这些年我越来越觉得“单芯片电源方案”是个甜蜜又危险的词。甜蜜在于它让板子瞬间简化危险在于你省掉的那一路控制细节会在量产和调试时十倍讨回来。这篇文章要聊的项目就是用一颗PCA9422和一颗PIC24FJ256GB110搭建一套完整的电源管理系统——前者负责电池充放电、电压转换和关键保护后者负责状态调度、充电策略和应用逻辑。适合正在做电池供电便携设备的工程师、学生也适合想搞懂 PMIC 与 MCU 到底如何打配合的嵌入式开发者。文章里我会把从选型、硬件连线到固件状态机、低功耗调优的完整过程拆开讲也会把调试时踩过的坑直接摆出来。1. 项目从哪里开始为什么需要“MCU PMIC”这样组合1.1 单电源芯片方案看起来很美但问题藏在决策层很多团队做小设备时习惯一上来就找一颗“什么都能干”的电源管理芯片希望它既能充电、又能输出好几路电压、还能自动切换路径。这种芯片确实存在但你会发现它在“能自动处理”的同时也意味着“你很难干预”。比如某一路负载进入低功耗模式你想把对应输出电压动态调低芯片可能不支持或者充电协议变了你想临时提高充电终止电压固件层面却没给你开放寄存器。这个项目最初的需求来自一款便携数据采集设备单节锂电池供电需要 3.3V 主干电压给 MCU 和传感器还需要一路 1.8V 给存储芯片充电部分要支持 USB 输入同时整机待机电流必须控制在微安级别。单纯用一颗“电源管理一体芯片”当然省面积但后续要扩展蓝牙通信、要接多路传感器、还要根据运行状态切换功耗档位控制权必须握在固件手里。所以最终方案定为 PMIC 管功率通路MCU 管策略调度两者通过 I2C 沟通。1.2 PCA9422 和 PIC24FJ256GB110 各自的分工边界PCA9422 这一侧主要精力放在功率转换和充电安全上。它内部集成了充电管理、多个电压转换通道、以及过压过流保护。典型场景是把单节锂电池、USB 输入和系统负载连接在一起电源路径能在适配器供电和电池供电之间自动切换。比较关键的是它支持通过 I2C 修改充电参数和输出状态我可以在不停机的情况下调整某一路电压幅值或者直接把某一路关闭来省电。PIC24FJ256GB110 这一侧则是系统的“大脑”。它有足够的 Flash 和 RAM 跑通信协议和状态机而且低功耗模式做得比较灵活可以做到快速唤醒。它通过 I2C 读取 PCA9422 的状态寄存器比如充电电流、系统电压、故障标志也能写配置寄存器比如设定充电目标电压、使能某一路输出。简单的说PCA9422 是提供能量的“心脏”PIC24FJ256GB110 是调度能量的“大脑”。从整体系统看这种“逻辑控制 功率执行”的架构最大的优势是解耦。功率部分出问题不会影响 MCU 的逻辑判断MCU 跑飞了PMIC 还有独立的安全保护。比把电源管理和逻辑控制全塞进一颗芯片稳得多。2. 整体架构与电源树先画清楚每一毫安的去向2.1 系统的电源树设计画电源树是设计前期最重要的一步。先别急着看芯片手册先把整个板子上需要供电的部分列出来再反推需要几路输出、每路最大电流多少、允许的纹波多大。我这个项目的电源树如下输入USB 5V用于充电器和系统主供电切换电池单节锂电池工作电压范围 3.0V~4.4V系统主干3.3V给 MCU、传感器、通信模块存储通道1.8V给 NOR Flash 和逻辑电平转换电路另外预留一路可关闭的 3.0V给外部可插拔传感器模块PCA9422 的多个转换通道刚好可以对应这些需求。USB 和电池之间采用路径管理当 USB 接入时优先使用 USB 供电同时给电池充电USB 断开时无缝切换到电池供电。这里我特别强调“无缝”因为 MCU 不能因为电源切换而产生复位否则整个系统就失去了意义。2.2 为什么把功率控制和逻辑控制分成两颗芯片我之前做过一个项目把电源管理功能集成在 MCU 内部确实省了一颗 IC但遇到一个非常头疼的问题MCU 自己在某些深度睡眠模式下内部的电源管理模块也跟着休眠导致外部传感器需要供电时必须先唤醒 MCU再打开电源输出整个唤醒延迟变大而且逻辑特别容易绕晕。拆成两颗芯片之后PCA9422 作为独立 PMIC即使 MCU 进入深度睡眠它依然能保持系统电压稳定输出只是通过中断引脚在特定事件发生时叫醒 MCU。这样逻辑更清晰低功耗调度也好写。更重要的是PMIC 的功率转换效率通常比 MCU 内部的 LDO 好不少这对电池供电产品来说差距很明显。在这个项目里MCU 和 PMIC 的职责划分是这样的模块负责内容PCA9422电池充电、路径切换、降压转换、过压过流保护、中断上报PIC24FJ256GB110I2C 配置、充电策略、低功耗状态机、传感器采集、通信协议电池组提供能量内置 NTC 温度检测USB 输入充电和系统供电的来源带 ESD 保护这样的划分让我在做固件时非常省心不需要关心功率管怎么开关、环路补偿怎么调只需要管好“什么时候让 PMIC 进入什么状态”。3. 硬件设计原理图画对后面少熬三个通宵3.1 电源输入保护与电池接入细节硬件上我吃过一次大亏USB 接口没有加合适的 ESD 防护第一次插上调试线就把 PCA9422 的输入脚打到异常随后整套系统供电都在乱跳。后来所有 USB 输入都串联一颗低阻的 PTC 自恢复保险丝再加一颗专用的 TVS 管钳位电压选在 5.5V 左右。电池输入端则不能只看正负极。锂离子电池对过放非常敏感虽然 PMIC 有放电保护但我在电池正极和系统主回路之间还加了一颗低导通电阻的 MOSFET由 MCU 控制。这样在运输模式和无负载长时间放置时可以真正切断电池对后级的供电而不是只靠 PMIC 内部开关。NTC 热敏电阻必须紧贴电池本体而不是贴在 PCB 板边。之前有一块板子把 NTC 放在电路板角落测出来的温度比电池实际温度低了十度左右直接导致低温充电策略完全失效。后来把 NTC 用一根软线引到电池表面并用胶固定才算稳定。3.2 PCA9422 输出电压通道的建模与配置PCA9422 的每个功率通道不是随便连上负载就行。你需要根据负载电流选择合适的电感值输出电容的 ESR 也会直接影响瞬态响应。按照数据手册给出的参考值我选了 1.0µH 电感和 10µF 陶瓷电容的组合并且在靠近 PMIC 输出引脚的位置放置。不要在输出端盲目加大电容尤其是大容量钽电容或者几百微法的电解电容。PMIC 的控制环路是内部补偿的输出电容超过推荐范围可能引起环路不稳定表现为轻载时电压振荡或者纹波变大。调试时用示波器看输出纹波如果发现轻微啸叫或者电压毛刺先查是不是电容超了。两个通道的配置位在 I2C 寄存器里可以在初始化时设为待机输出或主动关闭。我把存储通道1.8V设置成默认关闭状态只有需要读写 Flash 时才打开这样能让整机待机功耗明显下降。你可能会觉得多一路少一路没多少差别但在微安级别的待机电流目标下每一路转换器的静态电流都是要算进预算的。3.3 MCU 与 PMIC 的 I2C 连接注意事项PCA9422 的 I2C 接口是标准从机模式我直接接到 PIC24FJ256GB110 的硬件 I2C 外设上。接线很简单SCL、SDA、中断输出引脚还有一个是重置引脚。需要注意的是上拉电阻的选择。千万别图方便接 10kΩ 上拉就完事。PCA9422 的 I2C 时钟在高速模式下频率要求不低上拉电阻太大边沿会变得太慢导致通信偶尔出错。我最终选了 2.2kΩ 上拉电阻到 3.3V配合 400kHz 的 I2C 时钟跑了一整天的压力测试没有出现一次 NACK。中断引脚是开漏输出也需要接上拉电阻并且要确认 MCU 端配置成“下降沿触发”。如果 MCU 的中断引脚配置成电平触发高电平期间会反复进入中断处理不当就会把系统拖在一个忙碌状态里。4. 固件落地从初始化到充电状态机的完整代码思路4.1 初始化 PMIC 的时序和步骤PCA9422 在上电后默认状态并不一定符合你的项目需求所以 MCU 启动后的第一件事就是完成 PMIC 初始化。这个顺序不能乱如果输出还没配置好就先打开了充电可能出现电压异常。我一般按以下顺序初始化读取寄存器 ID确认真实芯片在线避免 I2C 总线地址冲突。关闭所有输出通道进入安全状态。配置充电参数目标电压、充电电流、终止电流阈值。配置每个输出电压通道的幅值和驱动模式。配置中断掩码只使能需要 MCU 处理的事件。最后才打开充电再打开系统主输出。关键点在于第 5 步。中断不要全部打开否则 PMIC 内部一些不太重要的状态翻转也会唤醒 MCU导致功耗曲线变得很难看。这个项目里只使能了四种中断充电完成、电池欠压、输入电源插入/拔出、系统故障。下面是一段简化后的初始化逻辑用来说明整体思路。不同版本的芯片寄存器偏移可能不同具体操作时一定对照最新的寄存器手册改地址。void pmic_init(void) { uint8_t id 0; uint8_t cfg; // 1. 确认PMIC在线 pmic_read_reg(PMIC_REG_CHIP_ID, id); if ((id 0xF0) ! PMIC_EXPECTED_ID) { system_set_fatal_error(); return; } // 2. 所有输出先关闭 pmic_write_reg(PMIC_REG_OUTPUT_EN, 0x00); // 3. 设置充电目标电压和电流 cfg CHG_VTARGET_4V35 | CHG_ICURRENT_500MA; pmic_write_reg(PMIC_REG_CHG_CFG, cfg); // 4. 配置输出电压通道 pmic_write_reg(PMIC_REG_BUCK1_CFG, BUCK1_VOUT_3V3); pmic_write_reg(PMIC_REG_BUCK2_CFG, BUCK2_VOUT_1V8); // 5. 中断掩码 pmic_write_reg(PMIC_REG_INT_MASK, PMIC_INT_CHARGE_DONE | PMIC_INT_BAT_LOW | PMIC_INT_VBUS_IN); // 6. 打开主输出和充电 pmic_write_reg(PMIC_REG_OUTPUT_EN, 0x03); pmic_write_reg(PMIC_REG_CHG_EN, 0x01); }4.2 充电状态机不要只盯着一个充电标志位很多人在做充电逻辑时只看“充满”标志这是不够的。锂电池充电流程包含预充电、恒流充电、恒压充电、终止几个阶段PMIC 内部会自己处理这些状态但 MCU 需要在关键节点做出决策。我定义了一个四状态充电状态机空闲、预充电、充电中、充满。每次从 PMIC 读取状态寄存器后会把原始状态映射到这四档。读状态不能太频繁。PCA9422 的状态变化不像通信信号那么快充电过程以分钟为单位所以用 1 秒的轮询周期完全够。如果每次都阻塞式读取反而会增加 I2C 总线占用和功耗。更好的做法是把“充满”和“输入电源拔出”做成中断MCU 睡在低功耗模式里只在中断到来时醒来处理。typedef enum { CHG_IDLE, CHG_PRE, CHG_ACTIVE, CHG_DONE } chg_state_t; static chg_state_t chg_state CHG_IDLE; void charge_state_machine(void) { uint8_t raw_status; pmic_read_reg(PMIC_REG_CHG_STATUS, raw_status); if ((raw_status CHG_FLAG_PRE) ! 0) { chg_state CHG_PRE; } else if ((raw_status CHG_FLAG_CHARGING) ! 0) { chg_state CHG_ACTIVE; } else if ((raw_status CHG_FLAG_DONE) ! 0) { chg_state CHG_DONE; } else { chg_state CHG_IDLE; } // 根据状态更新LED指示或上报给上位机 status_report(chg_state); }4.3 固件层面对故障标志的分级处理PCA9422 报告故障的方式不只一个寄存器。有全局故障标志也有逐通道的故障标志。我在固件里把故障分成三级一级可忽略例如温度传感器数据稍微超出范围记录日志即可。二级警告保持当前输出但限制大电流操作并上报给用户。三级致命立刻关闭相关输出并尝试重新初始化 PMIC。这套分级在调试时特别有用。有一次我接到反馈说设备偶尔自动重启查了很久发现是 PMIC 因为输入电压瞬时跌落触发欠压保护而我原来的代码对所有故障一视同仁直接关闭整个系统输出。后来把欠压事件改成“警告”级别并加上 5 秒延时确认问题就消失了。5. 低功耗策略从待机电流到运行电流的“毫安级管理”5.1 整机功耗预算表做电池供电设备第一步就是要列一张功耗预算表。不会列表的项目大概率会在后期为电量不足而返工。下面是我这个项目的初期估算模块运行电流典型待机电流MCU 核心5.0mA 16MHz2.0µA睡眠模式传感器组3.0mA0.1µA关闭电源存储芯片2.0mA读写时0.2µAPCA9422 静态损耗约 30µA约 15µA通信模块15mA瞬态1.0µA整机预估值约 25mA约 20µA这张表做出来之后你会发现待机电流的关键瓶颈不是 MCU而是 PMIC 自身和传感器是否真正断电。这也是为什么我把存储通道和传感器通道都做成可关断的原因。5.2 利用睡眠模式和中断唤醒配合 PMICPIC24FJ256GB110 的休眠模式有几种我最终选的是带 RAM 保持和快速唤醒的睡眠模式唤醒源包括外部中断、定时器和 I2C 事件。MCU 睡眠时PCA9422 仍然保持 3.3V 主输出这样 RAM 数据不丢唤醒之后能快速恢复到工作状态。低功耗状态切换的执行顺序很关键。如果先睡 MCU 再关负载电源负载可能因为瞬间掉电产生最后一次误操作正确顺序是先停止后端设备通信再关闭 PCA9422 对应通道最后确认电流降下来才让 MCU 进入睡眠。我在工程里实际测过光是“先关传感器电源再睡 MCU”和“直接睡 MCU”两种顺序待机电流就能差出 300µA 左右。看似不起眼但用一块 500mAh 的电池理论上能让待机时间差出上百个小时。5.3 动态调整输出电压不要一直跑满压PCA9422 支持通过 I2C 改变输出电压幅值。这个特性可以用来做动态电压调节。比如 MCU 全速跑通信时3.3V 输出需要带 50mA 负载进入长待机之后负载只有几毫安我可以把输出电压从 3.3V 稍微下调到 3.2V降低系统整体功耗。需要注意的是电压下调不能超过负载芯片允许的范围。我这个项目里的 Flash 存储芯片正好允许 1.7V~2.0V所有我在读 Flash 的时候把电压设为 1.8V写完立刻降回 1.7V。代码里只需要一行寄存器写入但对整机功耗的贡献非常可观。6. 排错实录那些容易被忽略的坑6.1 I2C 通信时好时坏上拉电阻和地线回流问题有一次整板老是随机出现充电配置丢失现象是插上 USB 之后偶尔能充偶尔不能充。通过示波器抓 SCL/SDA 波形发现下降沿很钝存在明显的边沿过缓。我把上拉电阻从 4.7kΩ 改到 2.2kΩ 之后波形明显改善。但随后又出现一个新问题I2C 偶发 NACK 都集中在充电电流较大的时候。后来查了一圈发现是地线布局问题功率地和信号地没有完全分离充电的大电流在地线上形成压降干扰了I2C 的参考地。最后通过单点接地把功率地汇聚到电池负极附近问题才彻底解决。这件事提醒我I2C 不稳定不一定只查 I2C 本身还得看功率环路。6.2 电池充满但上报未充满状态寄存器读取时机太早另一个测试中发现的怪问题是充电明明结束了上位机显示“充电中”。跟踪代码后发现是因为我在读取状态寄存器后没有等待足够时间恰好读到的是“充电立刻重新开始的窗口”。解决办法是在读取充电完成标志后延时 500ms 再确认一次同时也允许充电终止后自动重启的机制所以加了连续三次读取都是完成状态才最终判定为充满。这里要特别提醒不要试图用充电电流估算电池容量PMIC 内部读到的电流值是采样值存在一定误差只能做趋势判断不能做精确的电量计算。要算精确电量需要用库仑计芯片或者在 MCU 端做电压补偿表。6.3 负载切换瞬间的掉电复位输出电容配合不足有一次接上通信模块瞬间MCU 直接复位观察 3.3V 波形发现有几百毫伏的跌落。这是因为通信模块启动瞬间需要大电流PMIC 响应速度没跟上输出电容储能也不够。方案是在 3.3V 输出端额外并联了一个 100µF 的低阻抗钽电容同时把通信模块的启动序列改成“先开时钟、再开射频前端”避免瞬态电流叠加。如果你也遇到类似问题建议按三个方向排查先看输出电容是否够再看负载启动是否有软启动控制最后看 PMIC 的输出驱动能力是否被配置限制住。7. 关于这套方案的一些个人体会做完整套系统之后我对“电源管理完整方案”的认识有了一点变化。真正完整的电源管理不止是输出电压和充电电流能调还要有清晰的边界意识——哪些事应该由 PMIC 自己做哪些事必须留给 MCU 决策。PCA9422 在功率端把该做的保护都做完了PIC24FJ256GB110 则让我可以在策略层灵活控制整机状态。最后分享一个小技巧量产前一定要做一次整机老化测试重点看两个指标——充电终止电压漂移和待机电流稳定性。我曾经遇到一批电池在循环四十次之后出现电压异常排查到最后是 PMIC 和电池 NTC 热敏电阻的匹配问题而不是芯片本身故障。这类问题只有在长时间运行中才会暴露靠短期功能测试是发现不了的。如果预算允许建议在测试架上同时监测 PMIC 的 interrupt 引脚电平它比任何软件轮询都能更快反映电源路径上的异常。

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

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

免费获取报价 →
↑