首页 / 资讯中心 / 文章详情

PCA9422 PMIC与PIC32MX664F064L电源管理方案设计与实战

PCA9422 PMIC与PIC32MX664F064L电源管理方案设计与实战 ★ FEATURED ARTICLE
1. 从一颗PMIC说起为什么电源管理不能靠LDO硬扛做过嵌入式项目的人大概都有过这种经历板子焊好上电屏幕亮了跑一会儿发现某颗芯片烫得手指按不住或者电池供电的设备续航远低于预期再或者系统在低电量时突然复位数据全丢。这些问题追到根上十有八九是电源架构没设计好。我这次要聊的是一个比较典型的场景用一颗PCA9422电源管理芯片搭配PIC32MX664F064L这颗MCU搭一套完整的电源管理方案。PCA9422是NXP家的一颗高度集成的PMIC专门为低功耗、电池供电的便携设备设计内部集成了多个降压转换器、LDO、电池充电器、电量计还有I2C接口可以动态配置电压和读取状态。PIC32MX664F064L则是Microchip的一款MIPS架构MCU带USB、以太网、CAN外设丰富适合做中低端的工业控制和消费类设备主控。把这两颗芯片凑到一起核心要解决的问题是如何让MCU通过I2C去配置和管理PMIC实现多路电源的时序控制、动态电压调节、电池充放电管理、低功耗模式切换以及异常状态下的保护。这套方案适合谁看适合正在做便携设备、手持终端、电池供电的工业采集器或者任何需要一颗芯片管好整板电源的开发者。不管你是刚接触PMIC的新手还是已经用过其他电源方案的老手这篇内容都会把从选型理由到寄存器配置、从时序设计到踩坑排查的完整链路讲清楚。先说一个反直觉的结论很多人觉得电源管理就是选个LDO把电压降下来但在电池供电、多电压域、低功耗要求的系统里LDO的效率劣势会被放大到无法接受。LDO的本质是线性调整输入输出压差全部变成热量耗散掉。比如电池3.7V降到1.8V给MCU核心供电压差1.9V如果负载电流200mA光LDO上就耗掉0.38W封装小一点直接过热保护。而PCA9422内部的降压转换器效率能做到90%以上同样条件下损耗只有几十毫瓦。这就是为什么现代便携设备几乎都用PMIC而不是一堆LDO堆叠。2. PCA9422的电源域划分与PIC32MX664F064L的供电需求对齐2.1 先搞清楚MCU到底要几路电PIC32MX664F064L这颗芯片的供电需求不算复杂但也不能随便糊弄。它主要有这几组电源引脚VDD/VSS核心和IO供电典型范围2.3V到3.6V通常跑3.3V。AVDD/AVSS模拟部分供电给ADC用要求比较干净一般也是3.3V但建议单独滤波。VBUSUSB模块的VBUS检测引脚5V容忍。VUSB3V3USB内部稳压器的输出需要外接电容。VCAP/VDDCORE核心电压内部LDO输出需要外接电容稳定。关键点在于PIC32MX664F064L的核心电压是内部LDO产生的不需要外部单独供一路核心电。这一点和很多ARM Cortex-M芯片不同后者往往需要外部提供1.2V或1.8V核心电。所以从PMIC的角度看MCU这边主要就是一路3.3V的数字电和一路3.3V的模拟电外加USB相关的5V检测。但整板不止MCU。一个典型的便携设备还会有传感器可能1.8V或3.3V、显示屏3.3V或5V背光、无线模块3.3V峰值电流可能很大、存储卡3.3V、外设接口5V或3.3V。这些电压域如果各自用LDO板子面积和功耗都受不了。2.2 PCA9422能提供什么PCA9422的电源资源大致是这样电源类型数量输出范围最大电流典型用途Buck转换器2路0.5V-3.3V可调各1A核心电、系统3.3VLDO3路0.8V-3.3V可调各300mA模拟电、传感器、外设电池充电器1路支持单节锂电可编程电池充电电量计1路--电池电量监测这个配置对于PIC32MX664F064L系统来说绰绰有余。我的分配方案是Buck1输出3.3V给MCU的VDD、大部分数字外设供电。这路电流需求最大用Buck效率高。Buck2输出1.8V给需要低电压的传感器或外设。如果整板没有1.8V需求这路可以关掉省电。LDO1输出3.3V专门给MCU的AVDD模拟部分供电。用LDO是因为模拟电对纹波敏感Buck的开关噪声可能影响ADC精度。LDO2输出3.3V给无线模块或显示屏背光。LDO3输出2.5V或3.0V给特定传感器。这里有个经验点模拟电和数字电一定要分开供。我见过有人图省事AVDD直接和VDD接一起结果ADC采样值跳得厉害加了滤波电容也只能改善一点。后来单独用一路LDO供AVDD问题立刻消失。PCA9422有3路LDO拿出其中一路专门供模拟电成本增加很少效果立竿见影。2.3 上电时序的硬性要求PIC32MX664F064L对上电时序没有特别苛刻的要求但有几个原则核心电先于IO电虽然这颗MCU核心电是内部产生的但VDD上升太快可能导致内部LDO还没稳定所以VDD的上升斜率建议控制在合理范围。模拟电跟随数字电或稍后AVDD最好不要早于VDD否则可能出现闩锁风险。USB VBUS检测如果用到USBVBUS引脚要在VDD稳定后再有信号。PCA9422支持通过I2C配置每路输出的启动顺序和延迟。具体做法是在初始化时写对应的时序控制寄存器设定Buck1先启动延迟几毫秒后LDO1启动再延迟后其他路启动。这个延迟时间不是随便定的要根据每路输出的软启动时间和负载电容来算。比如Buck1输出3.3V负载电容10uF软启动时间1ms那么它大概1ms后稳定。LDO1的输入如果来自Buck1那必须等Buck1稳定后才能开LDO1否则LDO输入不足会输出异常。3. I2C通信链路MCU如何跟PMIC对话3.1 硬件连接与地址确认PCA9422的I2C接口是标准的两线制SDA和SCL。PIC32MX664F064L有多个I2C外设我一般用I2C1因为它的引脚布局通常比较方便。连接时注意上拉电阻I2C总线必须加上拉典型值4.7kΩ。如果总线电容大或者速率高可以降到2.2kΩ。我实测在100kHz速率下4.7kΩ配10cm走线很稳。电平匹配PCA9422的I2C电平跟它的IO电压有关如果MCU是3.3VPMIC的IO也是3.3V直接连就行。如果电压不同需要电平转换。地址PCA9422的I2C从机地址是7位的具体值看数据手册。一般有ADDR引脚可以配置低位地址方便同一总线上挂多颗PMIC。这里有个容易忽略的点PMIC的I2C接口在电池供电时可能由内部LDO供电如果这路LDO没使能I2C根本不通。所以第一次调试时如果发现MCU发I2C命令没响应先确认PMIC的I2C供电域是否已经上电。我踩过这个坑查了半天以为是地址错了结果是PMIC的通信电源没开。3.2 PIC32MX664F064L的I2C初始化PIC32的I2C外设配置比STM32稍微繁琐一点因为要手动算波特率。假设系统时钟是80MHz外设总线时钟是40MHz要得到100kHz的I2C速率I2CBRG (FSCL / (2 * FSCL)) - 2实际计算40MHz / (2 * 100kHz) 200再减2得198。但PIC32的I2CBRG寄存器有范围限制需要根据具体时钟分支来调。我一般直接用Microchip的Harmony框架或者PLIB库来配置省得算错。初始化步骤大致是配置I2C引脚为数字功能关闭模拟。使能I2C外设时钟。设置I2CBRG寄存器。使能I2C模块。等待总线空闲。发送数据的流程是发Start条件 - 发从机地址写位 - 等ACK - 发寄存器地址 - 等ACK - 发数据 - 等ACK - 发Stop条件。读数据则是发Start - 发地址写 - 等ACK - 发寄存器地址 - 等ACK - 发Restart - 发地址读 - 等ACK - 读数据 - 发NACK - 发Stop。PIC32的I2C状态机需要轮询或者用中断处理。我建议用中断因为轮询在等待ACK时会阻塞影响系统实时性。中断里根据状态码判断下一步动作代码会清晰很多。3.3 寄存器读写封装直接操作I2C寄存器很繁琐我一般封装两个函数uint8_t PMIC_ReadReg(uint8_t regAddr); void PMIC_WriteReg(uint8_t regAddr, uint8_t data);然后在上面再封装一层语义化的函数比如void PMIC_SetBuck1Voltage(uint16_t mV); void PMIC_EnableLDO(uint8_t ldoNum, bool enable); uint8_t PMIC_GetBatteryLevel(void);这样上层业务代码不用关心寄存器细节。封装时注意PCA9422的电压设置通常是步进式的比如每25mV一档写寄存器时要先算出档位值。比如要设3.3V寄存器值 (3300 - 基准电压) / 步进。具体基准和步进看数据手册不同型号可能不同。4. 动态电压调节与低功耗模式实战4.1 为什么需要动态调压PIC32MX664F064L支持多种低功耗模式比如Idle、Sleep、Deep Sleep。在Deep Sleep下核心电压可以降低到维持RAM和寄存器的最低水平从而大幅降低功耗。如果PMIC的Buck1输出固定3.3V那MCU在低功耗模式下仍然消耗较多静态电流。通过I2C动态把Buck1降到2.5V甚至更低可以进一步省电。具体操作流程MCU准备进入低功耗模式先保存关键状态到RAM。通过I2C通知PMIC把Buck1电压从3.3V降到2.5V。等待电压稳定查PMIC的Power Good状态位。MCU进入Deep Sleep。唤醒源触发后MCU先通过I2C把Buck1恢复到3.3V。等待稳定继续执行。这里有个坑降压后MCU的IO电平也会跟着变。如果MCU的IO电压从3.3V降到2.5V那连接的外设如果还是3.3V逻辑可能出现通信异常。所以动态调压一般只调核心电IO电保持3.3V。但PIC32MX664F064L的VDD和IO是同一路电这就矛盾了。解决办法是如果系统有外设在低功耗模式下仍需通信就不要降VDD如果低功耗模式下所有外设都关闭只留MCU自己那可以降。4.2 低功耗模式下的PMIC配置除了调压PMIC本身也有低功耗模式。PCA9422支持通过I2C命令进入Standby或Ship Mode。Standby下部分电路关闭I2C可能不可用Ship Mode下几乎全部关闭只留极小的漏电流。我的做法是MCU进入Deep Sleep前先把不需要的电源域关掉。比如无线模块的LDO2关掉传感器的LDO3关掉只留Buck1给MCU。然后MCU进入Sleep。如果系统需要长时间待机可以进一步让PMIC进入Standby但这样MCU就没法通过I2C唤醒了需要外部中断引脚来触发PMIC唤醒。唤醒流程要设计好外部按键或RTC中断 - PMIC唤醒 - 电源域恢复 - MCU复位或中断唤醒 - 重新初始化。这个链路里PMIC的唤醒时间很关键。PCA9422从Standby到所有电源稳定的时间大概是几毫秒MCU的启动时间也要算进去。如果系统要求快速响应就不能进太深的低功耗模式。4.3 实测功耗数据我在一个实际项目里测过几组数据供参考工作模式Buck1电压MCU状态整板电流全速运行3.3V80MHz120mA空闲3.3VIdle45mA睡眠3.3VSleep12mA深睡2.5VDeep Sleep3.5mA深睡PMIC Standby2.5VDeep Sleep0.8mA可以看到动态调压加PMIC低功耗模式能把待机电流从12mA压到0.8mA对于电池设备来说这是数量级的提升。当然0.8mA下唤醒时间会变长大概需要20ms才能恢复到全速运行。5. 电池充电与电量计别等电池鼓包了才后悔5.1 充电参数配置PCA9422内置的充电器支持单节锂离子电池充电电流和终止电压都可以通过I2C配置。典型配置充电电流根据电池容量定一般0.5C。比如1000mAh电池充电流设500mA。终止电压4.2V标准锂电或4.35V高压锂电看电池规格。预充电流电池电压低于3.0V时用小电流预充一般设充电电流的10%。终止电流充电电流的10%左右达到后判定充满。这些参数写进PMIC的充电控制寄存器。配置时注意充电电流不能超过PMIC和电池的最大允许值。PCA9422的充电电流最大大概1A但实际要看散热条件。如果板子小散热差设500mA以上可能触发过热降流。5.2 电量计的使用PCA9422的电量计通过监测电池电压和电流来估算剩余电量。它输出的是百分比或者电压值MCU通过I2C读取。但电量计的精度受电池老化、温度影响不能完全依赖。我的经验是电量计读数用来做粗略显示精确的低电量保护还是靠电压阈值。比如设3.4V为低电量警告3.2V为强制关机。电量计显示20%的时候实际可能还有30%或者只剩10%但电压阈值是实打实的。读取电量计的代码很简单uint8_t batteryLevel PMIC_ReadReg(PMIC_REG_BATTERY_SOC); if (batteryLevel 10) { // 触发低电量处理 }但要注意电量计寄存器可能需要定期刷新或者PMIC内部有采样周期。如果读得太频繁可能读到旧值。我一般1秒读一次足够用。5.3 充电状态监测与异常处理充电过程中要监测几个状态是否在充电、是否充满、是否故障。PCA9422有对应的状态寄存器。故障包括电池过温、充电超时、输入过压等。一旦检测到故障MCU应该采取动作比如关闭充电、点亮故障灯、记录日志。这里有个实际踩过的坑充电时如果系统同时在大电流放电充电电流可能被拉低导致充电时间变长甚至充不满。比如设备边充边用无线模块峰值电流500mA充电器设500mA那电池实际得到的充电电流可能只有几十mA。解决办法是充电时限制系统功耗或者提高充电电流。但提高充电电流又受限于PMIC和电池规格所以最好在系统设计时就考虑这个场景。6. 调试过程中最容易卡住的几个地方6.1 I2C通信失败排查链路I2C不通是最常见的问题。我的排查顺序是量电压PMIC的VDD和I2C上拉电压是否正常。如果PMIC没上电I2C肯定不通。查地址用逻辑分析仪抓波形看MCU发的地址和PMIC期望的是否一致。PCA9422的地址可能因ADDR引脚不同而不同。看ACK如果地址发出去没有ACK说明PMIC没响应。可能是PMIC没使能I2C接口或者地址错了。查时序用逻辑分析仪看SCL和SDA的时序是否符合I2C规范。上升沿太慢、时钟频率太高都可能导致通信失败。试低速把I2C速率降到10kHz试试如果低速能通说明是时序或上拉问题。我遇到过一种情况I2C波形看起来完全正常但就是没ACK。查了半天发现是PMIC的I2C供电域由另一路LDO供电而那路LDO没使能。所以第1步量电压的时候不仅要量PMIC的主供电还要量I2C接口的供电。6.2 电源时序导致的MCU复位如果MCU在上电过程中反复复位很可能是电源时序有问题。比如Buck1还没稳定LDO1就启动了而LDO1的输出又反馈到MCU的某个引脚导致MCU进入异常状态。用示波器同时抓Buck1和LDO1的输出看上升沿。正常情况下Buck1应该先达到稳定值然后LDO1才开始上升。如果两者同时上升或者LDO1先动就要调整PMIC的时序寄存器。另外MCU的复位引脚MCLR上如果电容太大可能导致复位释放太慢MCU在电源还没稳定时就开始运行。一般MCLR上接10k上拉和0.1uF电容到地这个RC时间常数要小于电源上升时间。6.3 动态调压时的通信中断前面提到动态调压如果调的是MCU自己的VDD那调压过程中I2C可能出错。因为VDD变化时I2C的电平也跟着变如果PMIC的I2C阈值没跟着变通信就可能失败。解决办法调压命令发出去后不要立即发下一条命令等PMIC的Power Good状态位确认电压稳定后再继续。或者调压时先把I2C速率降到很低增加容错。我实际的做法是如果必须调MCU的VDD就在调压前把I2C切到GPIO模拟模式用软件延时确保时序宽松。调压完成后再切回硬件I2C。这样虽然麻烦但稳定。6.4 电池充电时的噪声干扰充电器工作时开关噪声可能耦合到I2C总线上导致通信误码。我在一个项目里遇到过充电时I2C偶尔读写失败拔掉电池用适配器供电就正常。排查后发现是充电电流的开关频率和I2C的通信频率产生了某种耦合。解决办法I2C走线远离充电电感。在I2C线上加小电容滤波比如100pF。充电时降低I2C速率。在软件里加重试机制读写失败就重试几次。重试机制是最实用的因为硬件改板成本高。我一般在I2C读写函数里加3次重试每次失败后延时1ms再试。实测能解决大部分偶发失败。7. 从寄存器到产品一些设计上的取舍7.1 要不要用PMIC的中断引脚PCA9422有中断输出引脚可以在故障、电量低、充电完成等事件时通知MCU。用中断的好处是MCU不用轮询省电且响应快。坏处是增加一根走线和MCU的一个中断引脚。我的建议是如果系统对低电量响应要求高或者需要快速处理故障就用中断。如果只是定期读状态轮询也行。但轮询要注意频率太频繁浪费CPU太慢可能错过事件。7.2 电压裕量的取舍PMIC的输出电压可以精确配置但实际给MCU供电时要考虑线路压降和负载调整率。比如设3.3V到了MCU引脚可能只有3.2V。如果MCU要求最低3.0V那3.2V没问题。但如果设3.0V到了MCU可能只有2.9V就低于规格了。所以一般设电压时留50mV到100mV裕量。比如MCU要3.3VPMIC设3.35V或3.4V。但也不能太高太高增加功耗还可能超过外设的绝对最大额定值。7.3 外围元件的选择PMIC的Buck输出需要电感LDO输出需要电容。电感的选择影响效率和纹波一般选1uH到2.2uH饱和电流要大于最大负载电流的1.5倍。电容选低ESR的陶瓷电容10uF到22uF。这里有个细节Buck的输出电容不能太小否则负载突变时电压跌落大。比如MCU从Sleep唤醒瞬间电流从1mA跳到100mA如果输出电容只有1uF电压可能跌几百mV导致MCU复位。我一般用22uF实测负载突变时电压跌落控制在50mV以内。7.4 热设计PMIC在充电和大电流输出时会发热。如果板子空间小散热不好可能触发过热保护。我的做法是PMIC底部焊盘一定要接地并且打过孔到地平面帮助散热。充电电流不要设太大够用就行。如果空间允许PMIC周围铺铜增加散热面积。在软件里监测PMIC温度寄存器过热时降低充电电流或关闭部分输出。8. 代码框架与初始化流程8.1 初始化顺序整个系统的初始化顺序很重要我一般这样安排上电后PMIC先输出默认电压由硬件配置或OTP决定。MCU启动初始化系统时钟。初始化I2C外设。通过I2C读取PMIC的ID确认通信正常。配置PMIC的各路输出电压和时序。配置充电参数。使能需要的电源域。初始化MCU外设UART、SPI、ADC等。进入主循环。注意第4步读ID是确认I2C通信是否正常的最快方法。如果ID读不到后面都白搭。8.2 主循环中的电源管理任务主循环里可以放一个电源管理任务定期执行void PowerManagementTask(void) { // 读取电池电量 uint8_t soc PMIC_GetBatterySOC(); // 读取充电状态 uint8_t chgStat PMIC_GetChargingStatus(); // 检查故障 uint8_t fault PMIC_GetFaultStatus(); if (fault) { PMIC_HandleFault(fault); } // 根据电量调整系统行为 if (soc 10) { System_EnterLowPowerMode(); } }这个任务可以1秒执行一次不会占用太多CPU。8.3 低功耗模式的进入与退出进入低功耗模式前要保存状态、关闭外设、配置唤醒源。退出后要恢复外设、重新初始化。这部分代码要仔细测试确保不会丢数据或死机。我一般用一个状态机来管理Normal全速运行。PreSleep准备进入睡眠关闭外设。SleepMCU睡眠PMIC低功耗。Wakeup唤醒中恢复电源和外设。Normal恢复完成。每个状态之间的转换都有明确的进入条件和退出条件避免状态混乱。9. 写在最后的一些个人体会这套PCA9422加PIC32MX664F064L的电源管理方案我从选型到调试走了一遍最大的感受是电源管理不是孤立的它跟系统的每一个部分都有关。MCU的功耗模式、外设的供电需求、电池的特性、甚至PCB的布局都会影响最终效果。如果让我给正在做类似项目的朋友几条建议我会说第一先画电源树。把整板所有器件的供电需求列出来电压、电流、噪声要求、上电时序画成一张树状图。这张图清楚了PMIC的配置就清楚了一半。第二I2C通信一定要留调试手段。不管是逻辑分析仪还是示波器或者至少留个UART打印能让你在通信失败时快速定位。第三低功耗是测出来的不是算出来的。数据手册的功耗数据是理想值实际板子上的漏电流、外设静态功耗、电源效率都会影响。老老实实拿电流表测逐项排查。第四充电和电量计要留安全余量。电池是很娇贵的东西过充过放都可能出问题。电压阈值、电流限制、温度保护一个都不能少。这套方案我目前用在一个手持采集设备上连续工作续航大概8小时待机可以到一周以上。中间也踩了不少坑但每次解决问题后对电源管理的理解就更深一层。希望这些经验对你有用。
阅读完成 · 觉得有帮助?
咨询建站