ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

STM32F732IE电源方案:PCA9422 PMIC可编程配置与低功耗实战

STM32F732IE电源方案:PCA9422 PMIC可编程配置与低功耗实战 1. 项目缘起与整体设计思路1.1 为什么偏偏选中 PCA9422 这颗 PMIC做过便携设备或者工业手持终端的兄弟应该都有体会STM32F7 系列虽然性能猛但电源这块是真的不能随便糊弄。F732 这颗芯片核心电压典型值 1.2V内部还集成了 USB PHY、多路 ADC、DMA 控制器不同外设对电源纹波和上电时序的要求都不一样。如果还用传统的分立 LDO 加几个电阻电容去搭板子面积先不说光是上电顺序和低功耗模式切换就能把人折腾到怀疑人生。PCA9422 这颗电源管理芯片吸引我的地方在于它把锂电池充电管理、多路降压输出、LDO 输出、看门狗、I2C 可编程控制全部塞进了一颗 QFN 封装里。它支持 2.7V 到 5.5V 的输入范围内置的 buck 转换器效率在轻载下也能维持在 85% 以上这对电池供电的设备来说太关键了。而且它有一路专门给 MCU 核心供电的 buck 输出电压可以通过 I2C 动态调节这就意味着我可以在 STM32 进入低功耗模式时把核心电压降下来进一步省电。选型的时候我也对比过几款同类产品有些方案虽然便宜但要么没有 I2C 控制接口要么上电时序固定死不能改。PCA9422 的灵活性在于它的每一路输出都可以通过寄存器配置电压、上电顺序、甚至软启动斜率。对于 STM32F732IE 这种需要多电压域配合的 MCU 来说这种可编程性几乎是刚需。1.2 整体电源架构是怎么规划的整个电源方案的核心思路是锂电池或者外部 5V 输入进来之后先经过 PCA9422 的充电管理和系统电源路径管理然后由它分出几路电压给 STM32F732IE 和外围电路供电。具体来说我规划了四路主要输出。第一路是 buck1输出 1.2V 给 STM32 的核心电压 VDD这路要求纹波小、动态响应快。第二路是 buck2输出 3.3V 给 IO 电压 VDDIO 和大部分外设比如 SPI Flash、传感器这些。第三路是 LDO1输出 1.8V 给 USB PHY 和部分模拟电路因为 LDO 的噪声比 buck 低对模拟部分更友好。第四路是 LDO2输出 2.5V 给 ADC 参考电压或者 LCD 背光驱动这类对噪声敏感但电流不大的负载。上电顺序我设置成 buck1 先起等核心电压稳定之后再启动 buck2 和 LDO1最后才是 LDO2。这个顺序不是随便定的STM32F732IE 的数据手册里明确写了 VDD 必须先于 VDDIO 建立否则内部 ESD 保护二极管可能会导通导致漏电流甚至损坏芯片。PCA9422 的寄存器里可以配置每一路的启动延时和顺序这个功能在调试阶段帮了大忙。注意上电顺序一旦确定在 PCB 设计阶段就要把每一路的去耦电容和负载分布考虑清楚不然后期改顺序可能发现某路电压被拖垮。1.3 方案的优势和潜在风险这套方案最大的优势是集成度高、可编程性强、低功耗模式切换灵活。PCA9422 的静态电流在待机模式下可以低到几十微安配合 STM32F732IE 的 STOP 模式整机待机功耗可以控制在毫安级以下。另外 I2C 接口让 MCU 可以实时监控每一路输出的状态比如过流、过温、欠压这些故障都能读到寄存器里方便做故障记录和恢复。风险方面主要有两个。一是 PCA9422 的 I2C 地址是固定的几个选项如果板上还有其他 I2C 设备地址冲突要提前规划好。二是这颗芯片的 buck 转换器在轻载时会进入 PFM 模式纹波会比 PWM 模式大一些如果对纹波特别敏感可以通过寄存器强制它工作在 PWM 模式但代价是效率会降低几个百分点。这个取舍在后面调试章节我会详细说。2. 核心细节解析与实操要点2.1 PCA9422 的寄存器配置逻辑PCA9422 的寄存器映射不算复杂但有几个地方容易踩坑。它的 I2C 从机地址是 7 位的默认是 0x34如果板上 I2C 总线上挂了其他设备需要确认没有冲突。寄存器分为几个大块充电控制、buck 控制、LDO 控制、系统控制和中断状态。配置 buck1 输出电压的时候寄存器里是一个 6 位的电压选择字段步进是 25mV从 0.6V 到 1.5V 左右。我要输出 1.2V计算方式是(1.2 - 0.6) / 0.025 24也就是写入十进制 24 或者十六进制 0x18。这里有个细节芯片实际输出电压会有几十毫伏的偏差跟反馈电阻的精度和负载电流都有关系所以配置完之后一定要用万用表实测必要时微调一两个步进。LDO 的电压配置类似但步进和范围不同。LDO1 的输出范围是 1.2V 到 3.3V步进 50mV。要输出 1.8V计算方式是(1.8 - 1.2) / 0.05 12写入 0x0C。LDO2 的范围是 1.8V 到 3.3V步进也是 50mV输出 2.5V 就是 (2.5 - 1.8) / 0.05 14写入 0x0E。上电顺序的配置在系统控制寄存器里每一路都有一个 2 位的顺序字段和一个 3 位的延时字段。顺序字段决定哪一路先启动延时字段决定启动后等多久再启动下一路。我一般设置 buck1 为顺序 0延时 0msbuck2 和 LDO1 为顺序 1延时 2msLDO2 为顺序 2延时 4ms。这样总的上电时间大概 6ms 左右对 STM32F732IE 的复位时序来说完全够用。2.2 STM32F732IE 的电源引脚怎么接STM32F732IE 是 LQFP176 封装电源引脚分布比较散。VDD 引脚有好多组每一组旁边都要放一个 100nF 的陶瓷电容另外还要在芯片附近放一个 4.7uF 的钽电容或者陶瓷电容做储能。VDDIO 也是类似但要注意 VDDIO 的电压范围是 1.7V 到 3.6V我选 3.3V 是为了跟大部分外设电平匹配。VDDA 是模拟电源必须单独处理。我的做法是从 LDO1 的 1.8V 输出经过一个磁珠或者 0 欧电阻再接到 VDDA旁边放一个 1uF 和一个 10nF 的电容做滤波。VREF 如果不用外部基准可以直接接 VDDA但要注意 ADC 的精度会受 VDDA 噪声影响。如果对 ADC 精度要求高建议从 LDO2 的 2.5V 输出单独给 VREF 供电这样噪声更小。VBAT 引脚接一个纽扣电池或者超级电容用于掉电时保持 RTC 和备份寄存器。如果不使用直接接到 VDD 也可以但要注意掉电时备份域的数据会丢失。实操心得PCB 布局的时候PCA9422 的 buck 输出电感和电容要尽量靠近芯片引脚回路面积越小越好。我试过把电感放远了 5mm结果纹波直接从 20mV 涨到 50mV后来改布局才压回去。2.3 I2C 通信的初始化和调试PCA9422 的 I2C 接口支持标准模式 100kHz 和快速模式 400kHz。我一般用 400kHz因为配置寄存器不多速度够用而且不会对总线造成太大负载。STM32F732IE 的 I2C 外设配置成 400kHz 的时候要注意上升时间寄存器 TRISE 的计算。如果 I2C 总线的上拉电阻是 4.7k总线电容大概 100pF上升时间大约是 0.847 * 4.7k * 100pF ≈ 40nsTRISE 寄存器要设置成 40ns 对应的值。初始化流程是这样的先配置 GPIO 为复用开漏模式使能 I2C 时钟然后配置 I2C 的时钟控制寄存器、TRISE 寄存器、自身地址寄存器最后使能 I2C 外设。写 PCA9422 寄存器的时候先发起始条件然后发从机地址加写位等 ACK再发寄存器地址等 ACK再发数据等 ACK最后发停止条件。读寄存器稍微麻烦一点需要先写寄存器地址然后重启起始条件发从机地址加读位然后读数据。我踩过的坑是忘记在写地址之后加重启条件直接发停止再发起始结果读出来的数据全是 0xFF。后来查了时序图才发现问题。// PCA9422 写寄存器示例 uint8_t PCA9422_WriteReg(uint8_t reg, uint8_t data) { I2C_Start(); I2C_SendByte(PCA9422_ADDR 1); // 写地址 if (I2C_WaitAck()) return 1; I2C_SendByte(reg); if (I2C_WaitAck()) return 1; I2C_SendByte(data); if (I2C_WaitAck()) return 1; I2C_Stop(); return 0; }2.4 低功耗模式下的电源切换策略STM32F732IE 支持 Sleep、Stop、Standby 三种低功耗模式。Sleep 模式下内核时钟停了但外设还在跑这时候电源不需要特别调整。Stop 模式下大部分时钟都停了这时候可以把 buck1 的输出从 1.2V 降到 1.0V因为内核不跑高频了低压也能维持 SRAM 和寄存器的数据。Standby 模式下除了备份域其他全断电这时候 PCA9422 可以把 buck2 和 LDO 都关掉只留 buck1 输出 0.9V 给备份域供电。切换策略是通过 I2C 写 PCA9422 的寄存器来实现的。进入 Stop 模式之前先写 buck1 电压寄存器降到 1.0V然后配置 STM32 的 PWR 寄存器进入 Stop 模式。唤醒的时候先恢复 buck1 到 1.2V等电压稳定后再恢复系统时钟。这里要注意降压之后不能马上进 Stop要等电压稳定一般延时 1ms 左右。注意降压幅度不要太大STM32F732IE 的 SRAM 在 1.0V 以下可能丢数据。我实测过 0.95V 的时候偶尔会出问题所以 1.0V 是比较稳妥的下限。3. 实操过程与核心环节实现3.1 硬件焊接与上电前检查板子回来之后先别急着上电。第一步是用万用表测各路电源对地的阻抗确认没有短路。PCA9422 的 buck 输出对地阻抗应该在几百欧到几千欧之间如果测出来是几欧或者零那肯定有焊接问题。LDO 输出对地阻抗会高一些因为负载比较轻。第二步是检查 PCA9422 的焊接特别是 QFN 封装的底部散热焊盘一定要确认回流焊之后没有虚焊。我遇到过一块板子散热焊盘没焊好结果芯片一上电就过热保护输出全部关断。后来用热风枪重新吹了一下就好了。第三步是确认 STM32F732IE 的电源引脚没有连锡特别是 LQFP176 这种密脚封装相邻引脚之间的锡桥用放大镜仔细看。如果发现连锡用助焊剂和吸锡线清理干净。上电的时候先用可调电源限流到 100mA电压设 3.7V 模拟锂电池。如果电流一下子冲到限流值马上断电检查。正常情况应该是空载电流在几毫安以内然后慢慢上升。3.2 PCA9422 的初始化配置流程上电之后PCA9422 会按照默认配置启动但默认配置不一定符合我们的需求。所以 STM32 启动之后第一件事就是通过 I2C 重新配置 PCA9422。配置顺序我一般是这样先配置充电参数设置充电电流和终止电压。充电电流根据电池容量来定比如 1000mAh 的电池充电电流设 0.5C 就是 500mA。终止电压设 4.2V。然后配置 buck1 和 buck2 的输出电压和上电顺序再配置 LDO1 和 LDO2。最后配置中断使能比如过温中断、过流中断这些。配置完之后读回所有寄存器确认写入成功。我写了一个简单的校验函数把关键寄存器的值读回来跟预期值对比不一致就报错。// 配置 buck1 输出 1.2V PCA9422_WriteReg(BUCK1_VOUT_REG, 0x18); // 配置 buck2 输出 3.3V PCA9422_WriteReg(BUCK2_VOUT_REG, 0x36); // 配置 LDO1 输出 1.8V PCA9422_WriteReg(LDO1_VOUT_REG, 0x0C); // 配置 LDO2 输出 2.5V PCA9422_WriteReg(LDO2_VOUT_REG, 0x0E);3.3 上电时序的实测与调整配置完上电顺序之后用示波器抓每一路输出的上电波形。我一般用四通道示波器通道一接 buck1通道二接 buck2通道三接 LDO1通道四接 LDO2。触发设置在 buck1 上升沿。实测下来buck1 从 0 到 1.2V 大概用了 1.5ms然后 buck2 和 LDO1 在 buck1 稳定后 2ms 启动LDO2 再晚 2ms。整个上电过程大概 6ms跟配置的延时基本吻合。但有一次我发现 buck2 启动的时候 buck1 有轻微跌落大概 50mV 左右持续时间很短。原因是 buck2 启动瞬间的浪涌电流把输入电压拉低了。解决办法是在 PCA9422 的输入端加一个 22uF 的陶瓷电容把输入储能加大跌落就降到 20mV 以内了。实操心得上电时序的调试一定要用示波器看不能只看寄存器配置。因为实际波形受负载、电容、PCB 布局影响很大寄存器配置只是理论值。3.4 低功耗模式的实测数据低功耗模式我实测了几组数据。正常运行的时候整机电流大概 120mA其中 STM32F732IE 跑 216MHz 大概占 80mA外设占 40mA。进入 Sleep 模式后电流降到 45mA 左右。进入 Stop 模式并且把 buck1 降到 1.0V电流降到 2.5mA。进入 Standby 模式关掉 buck2 和 LDO只留 buck1 给备份域供电电流降到 80uA 左右。这些数据跟数据手册的典型值有一定偏差主要是因为外围电路还有漏电流比如上拉电阻、LED 指示灯这些。如果要进一步降低功耗可以把这些外围电路也关掉但那样会影响唤醒后的响应速度。唤醒时间方面从 Stop 模式唤醒大概需要 10us 左右从 Standby 模式唤醒需要 100us 左右因为要重新配置时钟和电源。这个唤醒时间对大部分应用来说够用了但如果需要快速响应还是建议用 Stop 模式。4. 常见问题与排查技巧实录4.1 I2C 通信失败怎么查I2C 通信失败是最常见的问题表现是读回来的寄存器值全是 0xFF 或者 0x00。排查步骤我总结了一个顺序。先确认硬件连接用万用表测 SDA 和 SCL 对地的电压正常应该是上拉电压比如 3.3V。如果测出来是 0V那可能是上拉电阻没焊或者总线被拉死了。然后测 SDA 和 SCL 之间的电阻正常应该是无穷大如果有几欧或者几十欧那可能是连锡了。硬件没问题的话用示波器看波形。正常的 I2C 波形应该是干净的方波上升沿和下降沿都很陡。如果上升沿很缓可能是上拉电阻太大或者总线电容太大。如果波形上有毛刺可能是电源噪声耦合过来了。软件方面检查 I2C 的时钟配置是否正确特别是 TRISE 寄存器。还有从机地址是否写对了PCA9422 的地址是 7 位的写的时候要左移一位。我遇到过有人直接写 0x34 作为地址结果通信失败因为实际发送的地址字节应该是 0x68。4.2 buck 输出纹波过大怎么办buck 输出纹波过大一般有三个原因。一是输出电容不够或者 ESR 太高二是电感选型不对三是 PCB 布局不好。输出电容我一般用两个 22uF 的陶瓷电容并联再加一个 100nF 的小电容滤高频。如果纹波还是大可以再加一个 1uF 的钽电容。电感的感值要根据开关频率和输出电流来选PCA9422 的 buck 开关频率是 2MHz我一般选 1uH 到 2.2uH 的电感饱和电流要大于最大输出电流的 1.5 倍。PCB 布局方面输入电容要尽量靠近芯片的 VIN 引脚输出电容要尽量靠近电感和输出引脚。反馈走线要远离电感和开关节点避免噪声耦合。我试过把反馈走线走在电感下面结果纹波直接翻倍后来改到旁边就好了。4.3 上电顺序不对怎么调上电顺序不对表现是某一路电压先起来了或者几路同时起来。先检查寄存器配置确认顺序字段和延时字段写对了。然后检查每一路的负载如果某一路负载太重可能会把电压拉低导致芯片认为这一路还没起来从而影响后续顺序。还有一个可能的原因是 PCA9422 的默认配置和我们的配置冲突。PCA9422 上电后会先按照默认配置启动然后等 MCU 通过 I2C 重新配置。如果 MCU 启动太慢默认配置可能已经让某一路起来了。解决办法是在 PCA9422 的 EN 引脚上加一个 RC 延时让芯片晚一点启动等 MCU 准备好之后再使能。4.4 常见问题速查表问题现象可能原因排查方法解决办法I2C 读回全 0xFF从机地址错误用示波器看地址字节确认地址左移一位buck 输出纹波大输出电容不足测输出电容容值并联 22uF 陶瓷电容上电顺序不对负载太重测每一路负载电流减轻负载或调整延时芯片过热散热焊盘虚焊测芯片表面温度重新焊接散热焊盘低功耗电流偏大外围电路漏电逐个断开外设关掉不用的外设唤醒失败电压恢复太慢测唤醒时电压波形增加延时或提高电压4.5 几个容易忽略的细节第一个细节是 PCA9422 的看门狗功能。它内置了一个看门狗如果 MCU 不及时喂狗芯片会复位。这个功能在调试阶段很烦人因为经常忘记喂狗导致系统重启。我一般先在调试阶段把看门狗关掉等系统稳定了再打开。第二个细节是充电电流的设置。如果电池容量小充电电流设太大电池会发热甚至鼓包。我一般按照 0.5C 来设比如 500mAh 的电池充电电流设 250mA。如果电池支持快充可以设到 1C但要注意散热。第三个细节是 LDO 的压差。LDO1 输出 1.8V如果输入是 3.3V压差是 1.5V在 100mA 负载下功耗是 150mW芯片会有点热。如果负载电流大建议用 buck 而不是 LDO或者降低输入电压。第四个细节是 STM32F732IE 的复位引脚。PCA9422 有一路复位输出可以接到 STM32 的 NRST 引脚。这样当电源异常的时候PCA9422 可以主动复位 MCU避免 MCU 在电压不足的情况下跑飞。这个功能在工业应用中很有用建议接上。最后分享一个小技巧调试电源的时候我习惯在每一路输出上焊一个测试点方便示波器探头直接接触。如果没有测试点用探头的钩子去勾电容的引脚也行但要注意不要短路。另外示波器的地线要尽量短最好用弹簧地针避免引入额外噪声。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进