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

文章详情

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

PCA9422与STM32L162ZE的低功耗电源管理设计实战

PCA9422与STM32L162ZE的低功耗电源管理设计实战 第一次把 PCA9422 和 STM32L162ZE 放到同一块板子上是在做一个电池供电的温湿度采集节点。当时我还在用一堆 3.3V LDO 给 MCU、传感器、射频模块分别供电结果电池电压稍微掉到 2V 以下系统就开始随机复位查了一整天才发现是 LDO 压差不够、加上掉电时序混乱导致的。换上 PMIC 方案后电源问题几乎一夜消失。这篇文章就围绕 PCA9422 这颗电源管理芯片和 STM32L162ZE 低功耗 MCU 的组合从选型逻辑、硬件电路、I2C 驱动、低功耗协同一路讲到调试时踩过的三个坑。整套方案做下来整机休眠电流能做到微安级动态负载下电源纹波也控制得不错。正在做电池供电设备的嵌入式工程师可以直接把这篇文章当成一份可复现的电源管理设计参考。1. 选型逻辑PCA9422 与 STM32L162ZE 是怎么凑到一起的1.1 从分立 LDO 到 PMIC一次被迫升级的选型很多低功耗设备最初都是 LDO 方案MCU 一个 LDO、传感器一个 LDO、射频一个 LDO。这种方案看似简单实际用起来问题很多。第一多个 LDO 并联静态电流累加起来很可观一颗普通的 3.3V LDO 自身就要吃掉几十微安三颗就是上百微安。第二电池电压跌落时LDO 的压差不够输出就跟着掉MCU 处于欠压状态表现就是随机复位、Flash 写入出错。第三上下电时序完全不可控谁先上电、谁后上电全看输入电容大小碰上对时序敏感的 MCU 就特别头疼。PMIC 的思路不一样它相当于把配电室搬到了芯片里。一个芯片统一管理输入电压、多路输出、保护逻辑、上电时序通过 I2C 还能随时开关某一路电源、调整电压大小。这个能力对电池供电设备来说是刚需平时不用的传感器电源轨直接关掉进入休眠前把 MCU 主电压调低需要唤醒时再通过 I2C 把电压抬回来。1.2 PCA9422 的核心特性盘点PCA9422 是一颗面向低功耗处理器和便携设备的 PMIC最核心的输入电压范围覆盖到 2.5V-5.5V这意味着两节 AA 电池、单节锂电池甚至 USB 5V 输入都能直接用它处理。我用的这颗集成多路可配置输出其中一路输出接主控核心电源一路接传感器一路接射频模组彼此之间还能设置不同的上电时序。比较关键的一点是PCA9422 的输出电压不是靠电阻分压焊死在板上的而是可以通过 I2C 软件配置。这个能力叫做动态电压调节也就是 DVS。对 STM32L162ZE 这类支持宽电压范围的低功耗 MCU 来说在运行低频任务时可以把核心电压调到 1.8V 省电在高负载任务前通过 I2C 把电压升到 3.3V这样性能和功耗的平衡能做到很细。我用一个表格总结一下这颗 PMIC 真正派上用场的特性特性说明我的实际用法宽输入电压2.5V-5.5V直接接单节 18650 锂电池多路 DC-DC/LDO 输出可软件开关每一路主控一路、传感器一路、射频一路I2C 可编程电压运行中动态调压跑任务前升压休眠前降压可配置软启动控制每路上电时间按 MCU 上电时序要求配置启动顺序过流/过压/过温保护芯片自动保护减小负载短路烧坏板子的概率状态输出 PGOOD所有电源轨稳定后指示接 MCU 的外部中断感知异常掉电1.3 为什么主控选 STM32L162ZESTM32L162ZE 属于超低功耗系列特点主要体现在几个方面。供电范围宽1.8V 到 3.6V 都能工作正好匹配 PMIC 的动态电压调节范围。低功耗模式齐全Sleep、Low-power run、Stop、Standby 都有休眠电流可以做到微安级。外设里自带 EEPROM不用额外挂存储芯片做数据记录非常方便。还有一个容易被忽略的点它支持 VBAT 独立供电即使主电源轨被 PMIC 完全关断RTC 和备份域寄存器依然可以靠一颗纽扣电池维持这对需要时间戳记录的采集设备关键性极高。这套组合的分工很清晰PCA9422 负责物理层面的电源分配和保护STM32L162ZE 负责策略层面的调度比如什么时候关传感器、什么时候降压、什么时候唤醒。MCU 和 PMIC 通过 I2C 通信所有电源状态都能被读取和改写。2. 硬件设计电源树、I2C 接口与 PCB 布局2.1 电源树与负载分配我实际搭建的电源树如下输入是一节 3.7V 锂电池经过 PCA9422 分配出三路电源和一路直通 VBAT。3.7V 锂电池 → PCA9422 主输入 ├─ BUCK1 3.3V → STM32L162ZE VDD含 I/O 与主 Flash 供电 ├─ BUCK2 3.3V → 射频模组只在发送时开启 ├─ LDO 2.8V → 传感器只在采集中开启 └─ VBAT 直通 → STM32 VBAT 引脚RTC 备份域常开把射频模组和传感器放在独立电源轨上是低功耗设计的关键。如果没有 PMIC让传感器一直通电即使 MCU 睡了传感器和上拉电阻的漏电也会让整机休眠电流居高不下。有了独立电源轨MCU 在进入 Stop 模式前只需要给 PMIC 写一个寄存器把 BUCK2 和 LDO 关掉整机的休眠电流就能立刻降下来。STM32L162ZE 的 VDD 和 VDDA 都接 BUCK1注意 VDDA 最好串一个小磁珠再加滤波电容避免射频发射时的大电流纹波干扰 ADC 采样。2.2 I2C 接口、使能与中断引脚PCA9422 和 MCU 之间的控制通道是 I2C。这个 I2C 总线有几个地方需要特别注意。首先是上拉电压域SDA 和 SCL 的上拉电阻要接到 PMIC 的 I/O 供电域上去而不是随便接 MCU 的 3.3V。如果 MCU 的 3.3V 和 PMIC 的 I/O 电压域不匹配轻则通信不稳定重则总线卡死。其次I2C 总线上除了 PMIC 不要挂太多设备挂得越多总线电容越大400kbps 模式下的波形边沿就越难看。EN 使能引脚我直接接 MCU 的 GPIO。这个引脚不是必须要用但把它留出来就有两种控制路径掉电时 GPIO 拉低PMIC 立即关断所有输出需要彻底断电时MCU 也可以在进入 Standby 前拉低 EN比逐个写寄存器关电源轨更彻底。INT 中断引脚接到 MCU 的一个 EXTI 引脚上配置成下降沿触发当发生过压、过流、欠压或者 PGOOD 异常时MCU 可以第一时间知道。PCB 上 INT 线旁边最好包地避免被 DC-DC 的开关噪声误触发。2.3 外围元件参数与 PCB 布局注意事项PMIC 的 DC-DC 部分需要外部电感。我选的电感值是 1.0uH 到 2.2uH 之间额定电流必须大于最大负载电流的 1.5 倍。电感 DCR 越小越好虽然价格贵一点但在 5V 转 3.3V 这种场景下效率差两个点就影响续航。输入输出电容也不能省输入侧至少放一颗 10uF 陶瓷电容输出侧各放一颗 10uF 加一颗 0.1uF高频去耦和容量维持都要兼顾。PCB 布局方面最容易踩坑的是 SW 开关节点。这个节点的电压在输入电压和地之间高频切换走线面积越大向外辐射的噪声就越强所以我尽量让 SW 走线短而粗并且把电感放在距离 PMIC 引脚尽量近的位置。反馈采样线要远离电感不要和 SW 走线平行。GND 采用单点汇接先把 PMIC 的散热焊盘、输入输出电容的地、MCU 的地分别连到各自的小平面再用一个过孔区域汇聚到主地平面避免大电流地环路干扰模拟信号。3. 软件驱动寄存器配置、初始化时序与动态调压3.1 用模拟 I2C 还是硬件 I2CSTM32L162ZE 本身有硬件 I2C 外设但它的硬件 I2C 在 L1 系列上表现一般中断处理不好容易卡死在总线 BUSY 状态。我这次用的是 GPIO 模拟 I2C频率 400kHz代码简单可控出问题也容易排查。如果不需要在 I2C 总线上跑超过 100kHz 的频率模拟 I2C 是绝对够用的。模拟 I2C 的核心就两个函数起始条件加写字节读字节加应答位。读写 PMIC 寄存器前要先发送设备地址加写标志然后发寄存器地址再发数据。寄存器地址写入方式是自动递增的所以连续读多个寄存器可以用一个函数带 outData 和 inData 两个数组一次性搞定。模拟 I2C 的延时用 nop 循环就行不用上定时器中断反而减小了低功耗模式切换时的干扰。3.2 核心寄存器一览PCA9422 的寄存器映射以我手头这颗器件的丝印版本为准不同批次可能略有差异但功能分类基本一致。真正会动到的寄存器其实就四类可以看下面这个表。寄存器示意地址功能我实际写的值EN_CTRL0x01独立开关各路输出默认全开休眠时只留 BUCK1VSET0x02-0x04设定各路输出电压BUCK1 一根 1.8V-3.3V 可调MODE0x05PWM/PFM 模式切换高负载用 PWM轻载自动切 PFMSTATUS0x06PGOOD、过流、过温状态只读上电后轮询一次需要注意EN_CTRL 寄存器的复位值默认可能是全开。这意味着 MCU 上电后所有电源轨都在供电。如果你要做低功耗必须在初始化时立刻把不需要的电源轨关掉。这个细节在后面的坑三会详细说。3.3 初始化时序与伪代码PCA9422 的初始化时序分为四步读芯片 ID 确认通信正常配置各路电压和模式使能需要的输出等待 PGOOD。伪代码如下uint8_t chip_id pmic_read_reg(0x00); if (chip_id ! 0xXX) { // 芯片通信异常建议进入错误处理 } // 配置 BUCK1 为 3.3V使能 PWM/PFM 自动切换 pmic_write_reg(0x02, 0x3A); // 关闭传感器和射频电源轨只留 MCU 主电源 pmic_write_reg(0x01, 0x01); // 等待所有电源轨稳定 uint8_t status pmic_read_reg(0x06); while ((status PGOOD_MASK) ! PGOOD_MASK) { status pmic_read_reg(0x06); }这个序列看起来简单但有几处容易被忽略。读取 STATUS 寄存器不能只读一次因为 BUCK 软启动需要时间PGOOD 会在输出接近目标电压后才拉高。如果 MCU 一上电就开始做高频外设初始化而电源还没稳定很容易出现外设初始化失败或者 Flash 写入异常。我的做法是PGOOD 拉高后再延时 10ms然后才开始初始化 GPIO 和外设。3.4 DVS 动态电压调节的操作要点动态电压调节是这套方案里比较有价值的功能。常规做法是在系统负载低时把 BUCK1 输出电压降到 1.8VMCU 运行功耗可以降低 30% 以上需要执行复杂任务、提升主频时再把电压升回 3.3V。电压切换的流程是先通过 I2C 写入目标电压值等待芯片内部寄存器更新再读取回读寄存器确认最后延时几十微秒让输出稳定。实际操作中有一个注意点电压跳变幅度不要一次跨太大从 3.3V 直接降到 1.8V负载电流突变的瞬间可能触发欠压保护。我一般分成两步先降到 2.5V稳定 1ms再降到 1.8V。升压也是同理。对比直接写入目标值的做法分步压在实测中没有出现过复位代价只是多两次 I2C 写入几乎可以忽略。4. 低功耗协同从 Stop 模式到 PMIC 电源轨的联合调优4.1 STM32L162ZE 的几种低功耗模式怎么选STM32L162ZE 有四种常用低功耗模式我整理成表格对比一下。模式RAM 保持RTC 运行典型电流退出方式Sleep保持可运行数十 uA任意中断Low-power run保持可运行数 uA直接切换Stop保持可运行1-2 uAEXTI/RTC 闹钟Standby丢失可运行百 nA 级唤醒引脚/RTC做电池设备我用得最多的是 Stop 模式。它保留 RAMMCU 唤醒后可以从断点继续执行不用重新初始化全局变量和堆栈对数据记录类应用非常方便。如果追求极限功耗可以进 Standby但 RAM 内容全部丢失唤醒后相当于复位必须从启动向量重新走一遍。我的建议是除非设备对休眠功耗要求低于 2uA否则优先用 Stop开发效率和功耗之间更好平衡。4.2 PMIC 侧为低功耗做了什么PMIC 侧的功耗分两部分自身静态功耗和外部负载功耗。PCA9422 在轻载时会自动切换到 PFM 模式开关频率降低静态电流变小。如果我希望某个电源轨在高负载和低负载下都能维持高效率就把 MODE 寄存器配置成自动切换模式而不要强制 PWM。强制 PWM 的好处是纹波小但轻载效率低电池设备没必要。另外PMIC 每路输出在进入低功耗前都应单独判断是否关闭。传感器、射频模块这类外设在休眠期间没有任何作用保持供电只会白白消耗电流。对于必须保持供电的电路比如电压监测分压电阻也要检查是否可以直接接到 VBAT 域而不是经过 PMIC 输出省掉 DC-DC 自身的静态电流消耗。4.3 我的板子实测数据软件配置完成后我用万用表加采样电阻实测了整套系统在不同状态下的电流。数据不通用仅供参考但可以作为一个合理的数量级参考。系统状态实测电流说明运行 8MHz所有电源轨全部开启12.5mA传感器和射频都通电运行 8MHz只开 MCU 电源轨4.2mA传感器和射频已关Stop RTCPMIC 只保留 BUCK14.5uA外设全部断电主控低功耗StandbyPMIC 全关1.8uAEN 拉低彻底断掉输出从 12.5mA 到 4.5uA降到原来的千分之一PMIC 可关断电源轨的功劳最大。如果没有独立电源轨传感器漏电和射频待机电流会让 Stop 模式至少多出几十微安。4.4 低功耗模式切换的联动流程进入休眠前MCU 执行的最后几步是有顺序的先关数据采集外设然后写 PMIC 寄存器关掉外设电源轨再把 I2C 引脚切换成带上拉的输入或者推挽拉高防止总线漏电最后才进入 Stop。唤醒后顺序反过来先初始化时钟再恢复 PMIC 电源轨等待 PGOOD最后做外设初始化。这里有一个容易被忽略的细节I2C 的 SDA 和 SCL 在 PMIC 电源轨全关时不能浮空。如果这两个引脚是开漏结构且外部上拉到了 BUCK1 的输出上BUCK1 如果也关了两条线就会通过内部保护二极管给 PMIC 反向供电造成一个很难查的漏电路径。我通常的做法是关电源轨前把 GPIO 配置成推挽输出拉高或者配置成模拟输入模式切断内部路径。5. 调试实录三个让我加班到深夜的坑5.1 坑一上电时序不对MCU 完全不启动现象很直接板子上电后电源指示灯亮但程序不跑调试器也连不上 STM32L162ZE。第一反应是晶振问题换了晶振、检查负载电容问题依旧。后来用示波器同时抓 MCU 的 VDD 和复位引脚才发现 VDD 的上升沿比复位释放晚了几百毫秒。原因出在 PCA9422 的软启动配置上。我给传感器电源轨配置了较长的软启动时间而 PMIC 的软启动逻辑是所有使能的输出轨都要达到目标电压后 PGOOD 才会拉高。MCU 的复位电路默认在 VDD 上升到阈值后开始释放复位但复位释放那一刻 VDD 还在爬坡MCU 内部上电复位逻辑判断不了正确状态系统就卡在启动阶段。修复方法是把 MCU 主电源轨配置成最短软启动时间让 VDD 快速到达目标电压传感器和射频轨继续保持慢启动。同时把 MCU 的 NRST 引脚外接一个 100nF 电容让复位信号再多延迟几十毫秒等 PMIC 的所有电源轨都稳定后再释放。改完后再次用示波器确认VDD 先稳定复位最后释放程序一次就能正常启动。提示选 PMIC 的软启动参数时不要只关注各路输出的缓启动是否柔和更要关注 MCU 对上电时序的要求。主控电源轨永远应该是第一路快速爬升的输出。5.2 坑二I2C 总线偶尔卡死读寄存器返回全 0xFF这个问题很隐蔽表现为系统运行几分钟后 PMIC 寄存器读取值全部变成 0xFF写入也无效。从示波器看总线波形发现 SCL 和 SDA 在空闲状态下高电平不到 2.0V边沿明显变缓偶尔还会出现 SCL 低电平被拉得很长的情况。排查后发现两个叠加的原因。第一个原因是 I2C 上拉电阻接错了电压域上拉接到了 MCU 侧的 3.3V而 PMIC 的 I/O 供电域实际只有 1.8V高电平虽然能识别但噪声容限不够总线一有干扰就误判。第二个原因是业务逻辑里有一个外部中断服务函数内部直接调用了 I2C 读写函数当高频中断打断正在进行的 I2C 时序时总线状态机就被搞乱了。修复方案分两步。上拉电阻改接到与 PMIC I/O 域一致的电压源上保证逻辑电平匹配。外部中断服务函数里不再做 I2C 操作只置一个标志位主循环检测到标志后再执行 PMIC 状态读取。这两处改完后连续跑 48 小时再没有出现过总线卡死。5.3 坑三睡眠电流降不下去实测在 4mA 而不是 4.5uA这是低功耗设备最常见的问题。代码里明明已经进入了 Stop 模式电流还是好几毫安。我开始怀疑是某颗电容漏电或 PCB 脏污用热像仪扫了一遍没有发现明显发热点后来逐一断开各路电源轨才定位到传感器供电还在。问题根源是 PCA9422 的 EN_CTRL 寄存器复位值默认全开。我的代码在初始化 PMIC 时写过一次关闭传感器电源轨但后续因为某次调试重新调用了一版更早期的初始化函数把全部输出都打开了。MCU 进入 Stop 模式前代码只处理了 GPIO 和时钟没有再次确认 PMIC 各路输出的使能状态于是传感器就在休眠期间一直通着电。修复方式是在进入 Stop 模式前增加一个 PMIC 状态检查函数逐位查询所有电源轨的使能状态确认外设电源轨全部关闭后再执行 WFI 指令。同时把所有默认不需要带电的电源轨在 PMIC 初始化阶段就把复位值改掉避免误开。之后实测电流恢复正常。还有一点值得提手动测量静态电流时如果把万用表串在电池和板子之间PMIC 输入电容的充电伪电流会让电流读数虚高要等几秒再读数。如果你也在调这套组合最后再分享一个小经验把 PCA9422 的 PGOOD 信号接到 STM32L162ZE 的一个外部中断引脚上任何掉电、过流、欠压事件都能第一时间感知。我在一次电池接插件松动的现场就是靠这个中断及时保存了关键数据整个过程 MCU 甚至没有发生复位。电源管理的价值一半在硬件设计另一半就是这种关键时刻的可靠响应。
返回列表