多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

基于PCA9422与PIC18F96J65的电池供电电源管理设计

基于PCA9422与PIC18F96J65的电池供电电源管理设计 做电池供电的手持设备电源管理从来不是把几颗 DC-DC 摆上去那么简单。两年前我在做一台便携采集终端系统里要同时跑 5V、3.3V、1.8V、1.2V 四路电源最初用分立方案上电时序靠 RC 延时网络硬拼结果低温环境下时序完全漂移板子间歇性起不来。后来换成PCA9422这颗带 I2C 接口的 PMIC配上PIC18F96J65这颗 8 位 MCU 专门做电源管理状态机整套系统才算真正稳定下来。这篇文章把这次方案的设计思路、寄存器配置、软件状态机、实测数据以及踩过的坑完整记录下来适合正在做便携设备、工业仪表或者电池供电产品的硬件和嵌入式工程师参考。1. 选型逻辑电源管理这件事为什么需要一颗专门的 PMIC 配一颗 8 位 MCU很多人一开始会问电源管理不就是几个 DC-DC 加 LDO 吗为什么非要搞一颗 PMIC 再加一颗 MCU是不是过度设计我先从实际场景说起。1.1 我在项目里遇到的电源问题四路电源的时序噩梦我的项目里有四路主要电源5V 给传感器和电机驱动3.3V 给数字逻辑1.8V 给存储接口1.2V 给 MCU 核心。最开始用的是两颗 DC-DC 加两颗 LDO 的分立方案每颗芯片的 EN 引脚上接一个 RC 延时网络让它们按顺序上电。这个方案在常温下看起来没问题但产品要做 -20℃ 低温测试时问题全出来了。电容的容值随温度变化RC 延时时间漂移有时 1.2V 比 3.3V 先起来存储器的 I/O 域还没建立就收到了操作指令直接导致系统反复复位。只能用示波器四通道一遍遍抓时序用一把电烙铁换来换去调 RC 参数一个简单的时序问题折腾了快两周。那时候我才意识到上电时序这种东西靠硬件延时网络去拼本质上是把逻辑写死在电阻电容里一旦环境变了或者负载变了根本没有自适应能力。正确的做法是让时序成为一段可编程的配置而不是一堆焊在板子上的 RC 参数。1.2 PCA9422 的定位能做什么不能做什么PCA9422 是一颗带 I2C 接口的电源管理芯片内部集成了多路降压转换器、LDO、时序控制单元、电压监测和故障保护逻辑。它最核心的能力是三件事多路电源轨的输出电压可以通过寄存器配置芯片内部有精确的反馈基准不需要靠外部电阻分压器去调电压。各路电源的上电顺序、延迟时间可以通过寄存器配置时序控制由芯片内部逻辑完成不受温度影响。具备过压、欠压、过流、过温保护而且故障状态可以通过中断引脚通知外部控制器。但它的局限也很清楚PCA9422 只是一颗执行器它不知道系统当前处于什么状态不知道用户有没有按电源键不知道应用层的任务跑完没有。它的能力边界是把各路电源按配置的时序打开并维持它们稳定输出而什么时候打开、打开哪些路、异常之后怎么处理这些决策必须由外部控制器来做。1.3 PIC18F96J65 的定位低成本高确定性的电源大脑PIC18F96J65 是一颗 8 位 MCU在这套方案里担任电源管理大脑的角色。有人可能会觉得搞电源管理为什么不上 32 位 MCU性能更强、外设更多。我的考虑其实很直接。第一电源管理是一个纯粹的状态机逻辑不需要跑操作系统不需要复杂计算8 位 MCU 的算力绰绰有余。第二8 位 MCU 的功耗下限通常更低PIC18F96J65 这类器件在深度睡眠模式下静态电流可以做到微安级这对电池供电产品至关重要。第三PIC 系列在工业环境下的稳定性和供货周期是经过验证的做电源控制这种关键功能可靠性比性能重要得多。它在这套方案里的具体角色通过 I2C 访问 PCA9422 的寄存器读取各路电源状态接收 PCA9422 的中断信号执行按键开关机逻辑并且在系统异常时做出降级处理。一句话总结PCA9422 负责干活PIC18F96J65 负责决定干什么。如果非要说选型逻辑的教训那就是不要因为一颗芯片功能多就去选它先把谁执行、谁决策这条边界划清楚再决定每颗芯片的分工。2. 接口与电路PCA9422 和 PIC18F96J65 的脚位级连接选型理由聊清楚了接下来就是最枯燥也最容易翻车的硬件连接环节。这一节不谈理论只讲我实际画过的原理图上的细节。2.1 最小连接关系I2C、中断、PGOOD、按键开机PCA9422 和 PIC18F96J65 之间的核心接口是 I2C但完整的电源管理还需要几个状态信号配合。我的连接关系如下表PCA9422 引脚PIC18F96J65 引脚连接说明SCL / SDA对应 MSSP 模块引脚两根线都接 3.3kΩ 上拉到 3.3VINT中断输出低有效RB0外部中断输入PMIC 检测到故障时拉低通知 MCUPGOOD各路输出已就绪RA1普通 GPIO用于软件轮询上电状态不做硬复位EN / PWRONRA2普通 GPIOMCU 控制 PMIC 主使能按键输入RA3 按键到 GND按键信号同时给 PMIC 和 MCU有几点细节需要特别说。I2C 上拉电阻的位置要靠近 PCA9422 那侧而不是靠近 MCU 那侧。很多人习惯把上拉放在 MCU 端但总线上如果串了排阻或者经过连接器远端信号边沿会变差长时间运行容易偶发通信错误。我是把一颗 3.3kΩ 排阻放在 PMIC 附近示波器实测 SCL 上升沿大约 80ns很干净。按键开机这部分我把按键信号同时接给 PMIC 的使能引脚和 MCU 的一个 GPIO。这样做的原因是完全关机状态下PMIC 的输出全关断MCU 自身也断电此时只有按键直接触发 PMIC 使能系统才能从死亡状态重新上电。等 MCU 起来之后再通过 GPIO 锁住电源状态此时按键就变成一个普通的输入信号由软件判断短按、长按。2.2 电感电容选型额定电流之外的几个经验值PCA9422 的 buck 输出电压高了之后电感选型是最容易出问题的地方。我的第一版 PCB 选了一颗额定电流刚好等于负载最大电流的电感结果满载工作半小时后电感温度升到 75℃ 都不止效率也明显下降。后来我总结了一套在参考设计基础上修正的选型规则电感饱和电流至少留 40% 余量。比如 1.2V 输出最大 1A电感的饱和电流必须选 2.5A 以上。电感饱和不只是发热问题饱和后感值急剧下降输出纹波会突然变大严重时甚至引起环路不稳定。DCR 优先选尽量低的。对电池供电设备一颗电感的 DCR 每高 10mΩ满载时就要多 10mV 的压降和一部分热损耗这个账一定要算。输出电容用 X5R 或 X7R 陶瓷电容但要注意直流偏压特性。22μF 的陶瓷电容在加 3.3V 直流偏压后实际容量可能只剩 12μF 左右所以我在每路输出用了并联两到三颗小封装的电容而不是单独一颗大封装电容。PCA9422 数据手册里一般会给典型应用电路我的做法是先按典型电路的参数搭第一版然后根据实测纹波和负载阶跃响应微调。直接抄参考设计不是不行但一定得理解每个元件为什么在那里。2.3 PGOOD、INT 与复位信号怎么接才不容易误动作这里有一个我印象深刻的坑一开始我把 PGOOD 直接连到了 PIC18F96J65 的 MCLR 复位引脚想着电源出问题就自动复位 MCU多省事。实际调试时被坑惨了。PCA9422 在负载瞬时变化时PGOOD 信号会因为输出电压短暂跌落产生一个几百微秒的低脉冲。这个脉冲直接复位了 MCU然而过流或欠压的故障原因未必存在。更麻烦的是电源恢复之后 PGOOD 又变高MCU 重启之后根本查不到刚才发生了什么电路表现就是莫名其妙复位。正确的做法PGOOD 只接 MCU 的一个普通 GPIO任何复位动作都由 MCU 决策后执行。INT 引脚接外部中断输入故障发生时 MCU 先读取 PCA9422 的中断状态寄存器区分是过压、欠压、过温还是过流再决定是记录日志、软复位还是直接关断输出。把故障检测和故障处理解耦整个系统的鲁棒性会好很多。3. 上电时序与电压配置寄存器层面最先要写对的东西硬件焊接完成、I2C 能够通信之后第一件要做的事不是写完整驱动而是把 PCA9422 的电压和时序配置弄对。这一步错了后面所有调试都会被不稳定的电源干扰而且很难排查。3.1 先读 DEVICE_ID再谈其他I2C 通信确认这一步别省我的调试习惯是不管新的 PMIC 板卡多简单上电后第一段代码永远是读 DEVICE_ID 寄存器把读回的值和手册上的期望值对比。这一步至少能验证三件事I2C 地址对不对、寄存器映射是不是手册里描述的那一版、电平转换是否正常。我在某次调试中就遇到过PMIC 实际从机地址的最低有效位由硬件引脚决定而我原理图上画的是默认地址结果读不响应。如果当时直接写配置代码大概率就是看起来写成功了实际上什么都没发生这种问题最难查。#define PMIC_I2C_ADDR 0x48 // 我的板上 ADDR 引脚为高地址见手册 #define REG_DEVICE_ID 0x00 // 器件 ID 寄存器具体偏移以手册为准 #define REG_SYS_CTRL 0x10 // 系统控制寄存器示例偏移 #define REG_BUCK1_CFG 0x12 // Buck1 电压配置示例偏移 #define REG_BUCK2_CFG 0x15 // Buck2 电压配置示例偏移 #define REG_LDO1_CFG 0x1A // LDO1 电压配置示例偏移 #define REG_SEQ_CTRL 0x20 // 上电时序配置示例偏移 #define REG_INT_STATUS 0x30 // 中断状态寄存器示例偏移 uint8_t PMIC_Init(void) { uint8_t id 0; if (PMIC_ReadReg(REG_DEVICE_ID, id) ! PMIC_OK) { return PMIC_ERR_COMM; // 通信失败直接返回 } if (id ! PMIC_EXPECT_ID) { return PMIC_ERR_ID; // 器件 ID 不匹配停止配置 } // 先关断所有输出再开始配置 PMIC_WriteReg(REG_SYS_CTRL, 0x00); // 配置 Buck1 1.2VBuck2 3.3VLDO1 1.8V PMIC_WriteReg(REG_BUCK1_CFG, PMIC_VOLT_1V2); PMIC_WriteReg(REG_BUCK2_CFG, PMIC_VOLT_3V3); PMIC_WriteReg(REG_LDO1_CFG, PMIC_VOLT_1V8); // 配置上电时序Buck2 - LDO1 - Buck1 PMIC_WriteReg(REG_SEQ_CTRL, PMIC_SEQ_BUCK2_FIRST | PMIC_SEQ_LDO1_SECOND); // 使能三路输出PMIC 内部按配置时序依次打开 PMIC_WriteReg(REG_SYS_CTRL, PMIC_EN_BUCK1 | PMIC_EN_BUCK2 | PMIC_EN_LDO1); return PMIC_OK; }上面代码里的寄存器地址和电压宏定义值是我针对手头这颗器件整理后的写法。不同批次、不同封装的 PCA9422 在寄存器偏移上可能有差异抄代码之前务必对着实际手册核对一遍寄存器地图。我每次换一个新硬件版本都会重新核对一遍这个习惯帮我避过好几次坑。3.2 输出电压与时序配置的几条原则配置输出电压和时序的时候有几条原则是我后来固化到团队规范里的第一所有输出先全局关断再逐项配置。如果你在配置过程中就使能了输出某些电源轨可能在你写完整颗芯片配置之前就处于一个不确定的电压状态下游器件可能已经启动了。一次干净的配置应该是关断所有输出写完所有电压值和时序参数最后写一个总使能触发命令。第二时序延迟不是越小越好。有些工程师追求上电时间快把各路间隔设到几百微秒。但下游器件的复位释放时间、晶体振荡器起振时间、Flash 初始化时间都比这长时序间隔太短等于没有时序。我一般把相邻电源轨之间的间隔放在 1ms 到 5ms 之间给下游电路留足稳定时间。第三读出后再修改不要盲写。PMIC 寄存器通常是一个字节包含多个位段比如高四位是目标电压低四位是使能和模式。如果直接写入一个全新值很容易把其他位段覆盖掉。正确的操作是先读回当前寄存器值用掩码清理要修改的位段再写回。3.3 动态调压运行中改电压的正确顺序PCA9422 支持运行中动态调整某路输出电压也就是 DVS。这个功能对需要 DVFS 的应用场景很有用比如 MCU 在低负载时降到更低的核心电压可以明显省电。动态调压操作的正确顺序是先读当前配置修改目标电压位段写回配置寄存器然后再单独触发 DVS 切换命令。如果直接把目标电压和切换命令写在一个字节里部分 PMIC 会立即执行切换但实际上你连写目标电压这个动作都没完成就可能出现电压跳变到错误值的风险。uint8_t PMIC_SetBuck1Voltage(uint8_t new_mv) { uint8_t val 0; if (PMIC_ReadReg(REG_BUCK1_CFG, val) ! PMIC_OK) { return PMIC_ERR_COMM; } // 清掉电压选择位段填入新目标电压 val ~CFG_BUCK_VSEL_MASK; val | (PMIC_MV_TO_CODE(new_mv) CFG_BUCK_VSEL_SHIFT); // 第一步先写目标电压 PMIC_WriteReg(REG_BUCK1_CFG, val); // 第二步触发 DVS 切换 PMIC_WriteReg(REG_DVS_CTRL, DVS_UPDATE_BUCK1); return PMIC_OK; }还有一点经验调压之后不要立刻去读 PGOOD 判断完成与否因为 DVS 切换需要一个斜坡时间。我在实际项目里用轮询周期 1ms调压后等 5 到 10 个周期再检查电压是否稳定到目标值基本不会误报。4. 软件状态机电源控制从硬件逻辑变成代码逻辑寄存器配置只是把 PMIC 的动作准备好了真正让整套方案运转起来的是 PIC18F96J65 里的电源状态机。这一节是整个软件的核心。4.1 五种电源状态与迁移事件我把系统电源分成了五个状态分别是关断、保持、运行、睡眠和故障。每个状态定义了 PMIC 哪些输出打开、MCU 自身处于什么工作模式。状态PMIC 输出状态MCU 状态典型电流PWR_ST_OFF全部关闭仅待机通道深度睡眠10μA 级PWR_ST_HOLD仅保持通道电源运行配置阶段数 mAPWR_ST_ON全部输出开启正常运行满载电流PWR_ST_SLEEP部分关闭保留唤醒通道轻度睡眠数百 μAPWR_ST_FAULT按策略降级或全关记录状态并处理视策略而定状态迁移事件包括按键短按、按键长按、PMIC 中断、PGOOD 超时、外部唤醒信号等。每个事件在状态机的入口处统一处理避免在中断服务程序里做复杂分支。4.2 状态机驱动核心代码骨架状态机主体用一个大 switch 实现每 10ms 在主循环里调用一次。这个周期对电源管理来说足够快也不会给 8 位 MCU 带来太大负担。typedef enum { PWR_ST_OFF 0, PWR_ST_HOLD, PWR_ST_ON, PWR_ST_SLEEP, PWR_ST_FAULT } PowerState; PowerState pwr_state PWR_ST_OFF; volatile uint8_t pmic_int_flag 0; volatile uint8_t button_event 0; void Power_StateMachine(void) { switch (pwr_state) { case PWR_ST_OFF: // 完全关机状态按键低电平唤醒 if (button_event B_EVT_PRESS) { PMIC_EnableHoldOn(); // 打开保持电源轨 pwr_state PWR_ST_HOLD; } break; case PWR_ST_HOLD: // 等待 PGOOD 确认电源稳定 if (PMIC_CheckPgood()) { PMIC_EnableAllOutputs(); // 打开全部电源轨 pwr_state PWR_ST_ON; } else if (pmic_int_flag) { pmic_int_flag 0; PMIC_ReadIntStatus(); // 清中断并记录 pwr_state PWR_ST_FAULT; } break; case PWR_ST_ON: if (button_event B_EVT_LONG_PRESS) { App_FlushConfig(); // 关机前保存数据 PMIC_DisableAllOutputs(); pwr_state PWR_ST_OFF; } else if (button_event B_EVT_SHORT_PRESS) { PMIC_EnterSleepMode(); pwr_state PWR_ST_SLEEP; } if (pmic_int_flag) { pmic_int_flag 0; Power_HandleFault(); // 故障处理在函数内决定是否降级 } break; case PWR_ST_SLEEP: if (button_event B_EVT_PRESS) { PMIC_ExitSleepMode(); pwr_state PWR_ST_ON; } break; case PWR_ST_FAULT: // 故障状态只允许复位或者硬件断电恢复 if (button_event B_EVT_LONG_PRESS) { PMIC_DisableAllOutputs(); pwr_state PWR_ST_OFF; } break; default: pwr_state PWR_ST_OFF; break; } // 每个周期清除一次事件标志避免重复触发 button_event 0; }这个骨架很简单但很可靠。实际产品里我在 HOLD 状态加了一个 50ms 的 PGOOD 超时判断防止 PMIC 硬件异常导致系统卡在等待上。PGOOD 超时后进入故障状态同时点亮一个故障指示灯提示用户需要重新插拔电源。4.3 中断处理原则ISR 里绝不直接做 I2C 操作PCA9422 的 INT 引脚是低有效中断输出。MCU 侧把它接到外部中断引脚中断服务程序里的代码只有三件事清标志位、记录中断时间、退出。真正的中断原因分析放在主循环里做。不在 ISR 里做 I2C 操作的原因有两个第一I2C 通信本身有时序要求ISR 里调用读写函数会占用不确定的时间可能影响其他中断的响应第二PMIC 在故障状态下I2C 总线不一定稳定如果在 ISR 里读寄存器失败还要处理错误返回逻辑会变得非常复杂。我的做法是 ISR 只置一个 volatile 标志位主循环的下一个周期去读 PCA9422 的中断状态寄存器根据中断位区分过压、欠压、过温、过流再决定执行什么动作。这里有一个细节我觉得特别值得分享清中断标志的顺序。我一开始先读 INT_STATUS 然后写回清位但在某些 PMIC 上如果故障源还存在INT 引脚会一直保持低电平读到的状态永远相同。正确做法是先处理完故障源比如把引起过流的电源轨关掉再读一次中断状态寄存器确认故障已经恢复最后清中断位。这样系统不会在同一个故障上反复进入中断。5. 实测数据与调试排雷纹波、动态响应、三个典型故障软件状态机跑通之后真正的验证工作才开始。电源管理芯片的数据手册上写着一堆指标但那些都是在理想测试条件下测出来的到了自己的 PCB 上布局、地平面、负载特性都会影响最终表现。5.1 我的测量方法示波器怎么接、负载怎么切测量电源纹波有一个非常容易踩的坑示波器探头的接地线如果用鳄鱼夹地线环路会像一个天线感应各种噪声测出来的纹波可能比实际大十倍。正确的做法是用探头自带的弹簧接地短针或者用同轴探头直接点在输出电容两端最大限度缩小测量环路面积。我测量纹波时同时做两件事把示波器带宽限制在 20MHz再打开平均模式。带宽限制去掉高频噪声干扰平均模式减少随机噪声这样读到的数值才接近真实纹波。测量负载阶跃响应时我用电子负载设置从 10% 负载到 90% 负载、切换时间 1μs 的瞬态模式看电压跌落多少、恢复时间多长。上电时序用四通道示波器同时抓几个电压轨触发放到最后启动的那路。实际测试时发现示波器探头的地线夹子接点位置对波形影响很大最好把所有地线都接在同一个测试点上避免地电位差。5.2 实测数据电压轨、纹波、启动时间的对应关系以下是这套方案在常温下的实测数据电源轨目标电压稳态纹波20MHz 限带启动时间备注Buck11.2V 核压1.20V18mVpp1.6ms强制 PWM 模式下Buck23.3V 数字3.30V22mVpp2.2ms轻载时纹波略大LDO11.8V 模拟1.80V9mVpp2.8ms纹波最小负载阶跃测试中Buck1 从空载切换到 800mA 时电压跌落约 85mV恢复时间约 120μsBuck2 从空载切换到 1A 时电压跌落约 90mV恢复时间约 150μs。这个数据在我的应用场景里是可以接受的如果你的负载对电压跌落更敏感可以适当增大输出电容或者调整 PMIC 的环路补偿参数。上电时序实测中三路电源按配置顺序依次建立相邻两路的间隔大约 2ms没有出现电源轨重叠或者反串的情况。和之前 RC 延时方案相比这套时序在 -20℃ 到 60℃ 范围内几乎没有漂移误差来源只剩下 PMIC 内部的时钟精度实测在 3% 以内。5.3 三个让项目晚了两周的坑第一个坑是 I2C 总线被钳位。我把 MCU 侧 I2C 上拉接到了 5V但 PCA9422 的 I2C 引脚耐压上限只有 3.6V总线一直处于一个模糊电平状态通信时好时坏。排查方法也很费劲因为现象不是完全不通而是偶发性的写失败。后来用示波器抓 SDA 波形才发现高电平只有 3.2V 而低电平没有完全拉低。解决办法是把上拉统一改到 3.3V确认信号电平在芯片规格书允许范围内。第二个坑是上电顺序配反导致下游器件反复复位。我把存储器的电源轨排在了核电压前面但存储器的 I/O 域由另一路电源供电I/O 域还没建立的时候存储器收到了来自控制器的操作信号瞬间进入错误状态。这个问题在低温下特别明显因为低温下存储器启动需要的时间更长。修改了时序寄存器之后把控制逻辑电源放在最前负载电源放在后面问题消失。第三个坑是轻载纹波被误判为环路振荡。Buck 在轻载模式下会自动进入 PFM 模式PFM 模式下纹波相对较大而且频率不固定示波器上看着就像环路在振荡。我花了一整天在调补偿网络后来翻手册才发现是轻载模式的正常行为。解决方法是软件里在轻载时把 Buck 切换到强制 PWM 模式纹波降下来了代价是静态电流增加约几百微安但换来的稳定性完全值得。6. 低功耗专项待机电流从 15mA 压到 500μA 的实操对电池供电设备来说电源管理做得好不好最终要落在待机电流这个数字上。这一节讲我在这套方案上压低待机电流的完整过程。6.1 先拆功耗账再动手每一毫安都要有出处第一次测完整系统待机电流时数字是 15.2mA比预期的 1mA 以下高了一个数量级。我没有直接猜问题而是把系统分成几个子电路逐个量电流。模块实测电流优化手段PIC18F96J65 正常运行2.6mA转深度睡眠模式电流降到 1.2μAPCA9422 三路全开空载7.8mA睡眠时关掉 Buck1、Buck2电源指示灯 LED 常亮2.2mA软件进入低功耗后关掉 LEDI2C 上拉电阻0.4mA保持无法避免传感器常供电2.2mA增加负载开关睡眠时断开拆完账就清楚了主要消耗不是单颗芯片的性能差而是所有东西都在空转。优化的核心思想是把不需要工作的模块在睡眠时彻底断电或者使其进入低功耗模式而不是去换更贵的芯片。第一版优化后待机电流降到 850μA主要贡献来自 MCU 深度睡眠和 PMIC 关断两路 Buck。第二版把传感器的供电开关也断开同时把未使用的 I/O 引脚全部配置成高阻或固定电平待机电流进一步降到 530μA。第二版中一个容易被忽视的点是MCU 上未使用的输入引脚如果悬空可能因为内部保护二极管产生漏电电流每个引脚几十微安积少成多。把所有不用的 I/O 都初始化成输出低电平问题立刻缓解。6.2 按键开关机链路硬件使能与软件关断的分工低功耗产品必然会遇到一个问题完全关机之后怎么再开机。PCBA 上不能有人拿螺丝刀去碰 PMIC 的 EN 引脚用户只能按一个电源键。我的设计是电源键信号同时接到 PCA9422 的硬使能引脚和 PIC18F96J65 的一个 GPIO。系统关机状态下MCU 断电PMIC 也不会因为按键之外的因素误开启。用户按下电源键后PMIC 硬使能生效保持电源轨先建立MCU 开始启动。MCU 启动后软件接管按键判断逻辑区分短按唤醒和长按关机。软件关机的顺序很重要。MCU 先向应用层发起保存请求等待数据落盘然后写 PMIC 寄存器关闭除保持轨之外的所有输出最后执行一条 SLEEP 指令进入深度睡眠。此时 PMIC 的保持轨还在给 MCU 供电但 MCU 已经停止刷程序系统电流只有保持轨的静态消耗加 MCU 睡眠电流大约 10μA 级。下一次按键到来时PMIC 的 EN 引脚电平变化MCU 从深度睡眠中被唤醒整个系统重新进入运行流程。有一个细节我优化了好几轮关机状态下保持轨是否还需要给 MCU 的 RTC 供电。我的第一版是彻底切断所有输出完全依靠按键使能但这样 RTC 时间每次关机都会丢失用户会抱怨时钟不对。后来改成保留 LDO1 作为常电给 RTC 供电代价是待机电流增加几微安但用户体验提升明显。这就是一个典型的工程取舍低功耗不是越低越好要结合产品的实际诉求去权衡。6.3 进一步优化测量方法、I/O 漏电和上拉电阻的细节待机电流压到 530μA 之后再往下压就进入细节战了。测量方法也要换万用表的电流档内阻会引入压降容易影响被测电路的工作状态。我改用高精度的电流探头串接在电池输出端或者用并联采样电阻的方式测平均电流。真正的细节问题来自三个方面。第一I2C 上拉电阻在睡眠状态下仍然消耗电流。I2C 总线空闲时是高电平上拉电阻会有一个持续的压降电流我把上拉电阻从 3.3kΩ 改成 10kΩ通信速率依然能满足 100kHz 的需求但静态电流省了一半。第二PMIC 的待机通道如果带载很轻可以考虑把它切到更低功耗的模式。第三电源路径上的保护二极管反向漏电流在温度升高时会成倍增加我在选型时专门挑了一颗常温反向漏电只有 0.1μA 的型号在 60℃ 环境下表现也比原来的普通二极管好很多。这套方案做下来我最深的体会是电源管理不是一个硬件模块而是一个横跨硬件和软件的子系统。PCA9422 把动作做好了PIC18F96J65 负责决策两者配合之后原来要十几个分立器件拼出来的时序和低功耗控制变成了一份可配置的状态机代码可靠性、可维护性和功耗表现都上了一个台阶。最后分享一个量产阶段的小经验在设计 PCB 时一定要预留一组电源轨测试点把 GND、3V3、1V8、1V2 用 1.27mm 排针引出来。生产抽检时四通道示波器同时抓上电时序一次能省半天逐板测试的时间。这个细节看似不起眼真到产线出问题需要快速定位的时候价值就体现出来了。
返回列表