做便携设备的朋友都有体会,电源管理这块儿看着简单,真正调起来全是坑。BUCK纹波、充电截止电流、低功耗唤醒、I2C地址对不上……随便一个问题都能让你在实验室蹲上一整天。最近我用 NXP 的 PCA9422 这颗 PMIC,配合 STM32F411RE 重新整理了一套完整的电源管理方案,从硬件选型、外围电路、寄存器配置,到软件状态机、功耗优化,完整地趟了一遍。整个过程踩了不少坑,也沉淀了不少可复用的经验。这篇博客就把这个项目从 0 到 1 完整拆解一次,包括每一处设计决策背后的理由,以及实测数据,希望对正在做电池供电产品的朋友有帮助。
1. 项目定位与整体架构:PCA9422和STM32F411RE怎么分工
1.1 便携产品电源设计面临的三个现实问题
做带电池的便携产品,比如智能手环、便携传感器、手持采集设备,电源设计绕不开三件事:充电管理、多路供电、低功耗。这三件事看着简单,却互相牵扯。充电要恒流恒压、要防过充、要NTC温度保护;供电要给MCU、传感器、屏幕分别供电,每路对纹波和动态响应的要求还不一样;低功耗更是要把每一毫安、每一微安都算清楚,主控睡眠时整个电源链路本身不能成为漏电大户。
如果全部用分立器件搭,充电子系统一个方案、DCDC一个方案、LDO一个方案,不仅BOM冗长,而且每一路都要单独调,调试工作量成倍增加。更重要的是,分立方案通常没有I2C接口,电压调整只能靠换电阻,产品要做动态功耗管理时束手束脚。所以我这个项目一开始就锁定带可编程接口的PMIC方案。
1.2 PCA9422能管哪些事
PCA9422是一颗面向低功耗便携设备的电源管理芯片,集成了线性电池充电管理、两路BUCK降压、一路LDO和完整的I2C可编程接口。它特别适合锂电池供电、对静态电流敏感、需要动态调整各路电压的场景。
具体来说,它的充电前端支持USB或适配器输入,内置充电电流配置和截止电流配置,能满足常见的4.2V锂电池充电需求。两路BUCK输出电压可以通过I2C在线调整,这意味着软件可以根据CPU负载动态调压,高负载时升压保证性能,低负载时降压省电。LDO则适合给对噪声敏感的模拟电路供电,比如音频、ADC参考等。此外还有NTC温度检测和中断输出,硬件保护逻辑并不需要主控实时参与,异常时PMIC自己会处理,主控只需要在中断里查明原因并响应。
这颗芯片还支持低功耗模式,系统待机时可以把不需要的DCDC关掉,只保留必要的LDO输出,把整条电源链路的静态电流压下来。
1.3 STM32F411RE在电源链路里的角色
STM32F411RE是一颗Cortex-M4内核的MCU,主频100MHz,带FPU,片上资源对这个项目来说非常充裕。它在这里主要干四件事:通过I2C配置PCA9422寄存器、读取充电和供电状态、根据系统负载动态调节BUCK输出电压、管理整个系统的开机和睡眠流程。
选它而不是选更低端的M0,原因有两点。一是项目后续还要跑一些轻量级的算法,比如电池电量估算、传感器数据融合,M4的算力余量更充足;二是它支持多种低功耗模式,STOP模式待机电流可以做到几十微安,再加上PCA9422的低功耗链路,系统整机待机才能压到百微安以内。如果选一颗没有低功耗模式的MCU,PMIC再省电也白搭。
1.4 整体信号链路与分工
整个系统的信号链路可以用一句话概括:电池经过PCA9422充电管理和多路输出,给主控及外设供电;STM32F411RE通过I2C总线读取PMIC状态并写入配置,通过一根中断线接收PMIC事件;NTC温度信号进入PMIC内部比较器,硬件层完成过温保护;静态电流测量、电池电压采样则分别走PMIC内部通道和MCU的ADC。
我建议把整套软件拆成两层。底层是驱动层,只负责I2C读写、寄存器封装、中断响应,不掺业务逻辑,换一颗PMIC时只需要替换这个层。上层是策略层,也就是电源管理状态机,管理充电、运行、待机、关机的迁移。我在实际项目中一直坚持这个分层,测试和移植都会省很多事。
2. 硬件设计:外围器件选型与PCB布局细节
2.1 关键引脚与信号路径梳理
拿到PCA9422的原理图封装,第一件事不是急着连线,而是把关键引脚梳理一遍。这个项目里我重点关注几组信号。
充电输入引脚接USB 5V或者适配器,输入路径上一定要加ESD保护器件,这没什么好商量的。I2C引脚是标准的SCL/SDA,按PMIC手册要求配上拉电阻。INT中断脚是开漏输出,需要外部上拉到MCU供电轨,这个上拉电阻我选了10k,实测没有问题。NTC引脚接电池内部的负温度系数热敏电阻,分压网络的电阻值要按PMIC手册给出的参考曲线选,不能随手配。BUCK输出引脚则需要接外围电感、电容,然后连到对应负载。
电源路径上还有一个容易忽略的问题:PMIC的输入电压检测和电池电压采样都有内部比较器,如果电池引线过长、内阻偏大,在大电流充电时会产生明显的压降,导致PMIC误判电池电压。所以电池正负极到PMIC的走线要尽量短粗,必要时在电池端并联一个100nF小电容来吸收瞬态。
2.2 DCDC电感电容怎么选,纹波才不会失控
两路BUCK是系统供电主力,外围选型直接影响纹波和效率。电感值的计算公式是 L = (Vin - Vout) * Vout / (Vin * f * ΔI),ΔI通常取负载电流的20%到30%。以3.7V电池电压、输出1.8V、开关频率2MHz、负载500mA为例,算下来电感大约在2.2uH到3.3uH之间。我最终选的是2.2uH/1A的功率电感,饱和电流余量留了接近一倍。
电感选型有几个坑。第一,只看直流电阻和饱和电流不够,要重点看额定电流下的电感衰减,廉价的铁氧体电感在大电流下电感量可能掉到标称值的一半以下,纹波会肉眼可见地变大。第二,DCDC的补偿网络是内部集成的,对输出电容的ESR窗口有要求,必须按照手册给出的推荐容值和ESR范围选电容,不能为了追求低ESR盲目上钽电容或者大容量MLCC。第三,电感的铺地要独立,不能跟其他信号共享回流路径。
输出电容我用了两颗22uF的X5R陶瓷电容并联,等效ESR落在手册推荐区间。这个组合在实测中纹波大概在10mV以内,完全满足给MCU和传感器供电的要求。
2.3 充电回路的电流采样与NTC布点
PCA9422的充电电流是通过内部检测完成的,用户需要配置的是预充电流、恒流充电电流、截止电流这几个参数。我需要提醒的是,充电回路中电池端到PMIC的路径电阻要尽可能小,因为恒压阶段PMIC是以电池端电压为反馈基准的,如果路径电阻太大,实际到达电池的电压偏低,会导致充电提前进入恒压阶段,充不满。
NTC布点方面,热敏电阻应该贴近电池本体,但又不能直接贴在电池钢壳上影响温度响应速度。我习惯把NTC放在电池支架的侧面开窗处,用导热胶固定。分压电阻的精度建议选1%的,否则温度阈值偏差会比较大。
2.4 PCB布局中值得注意的细节
这类PMIC的PCB布局有几个细节直接决定能不能一次点亮。一是BUCK的电感要靠近SW引脚,SW节点走线要短而宽,这个节点高频开关噪声最强,回路面积越小,辐射越少。二是PMIC的散热焊盘必须打足够多的过孔接到地平面,这颗芯片虽然功率不大,但线性充电时压差带来的热耗散不可忽视,我在第一版PCB上就因为散热焊盘过孔太少,充电时芯片温度明显偏高。三是I2C和中断线不要跟SW节点平行走线,否则开关噪声耦合进信号线,轻则通信误码,重则中断误触发。
还有一点是我自己反复踩过的:PMIC输入端的去耦电容要靠近输入引脚,而且电容地端要直接回到PMIC的地焊盘,不要绕远路。绕远路的结果是输入电压在开关动作时有明显振铃,严重时会把PMIC的输入检测电路干扰到误判。
3. 驱动层实现:STM32F411RE通过I2C读写PCA9422
3.1 I2C外设初始化必须确认的三件事
我用的STM32F411RE的I2C1作为控制总线,硬件上接了1.8k上拉电阻,工作模式配成400kHz快速模式。初始化代码用的是标准HAL库风格的写法。
void MX_I2C1_Init(void) { hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } }这里有三件事必须确认清楚。第一件事是I2C地址。PCA9422的7位从机地址由SM引脚电平决定,不同接法对应不同地址,我用的参考设计SM接地,枚举出来的地址是0x48。如果地址不对,直接表现就是HAL_I2C_Mem_Read永远返回超时。第二件事是上拉电阻的值,400kHz下如果是5V电平总线,上拉一般用2.2k到4.7k,3.3V系统用1.8k到4.7k都可以,关键是上升沿要满足快速模式时序,示波器上实测SCL/SDA上升时间不要超过300ns。第三件事是时钟延展,PMIC在内部处理时可能拉低SCL,如果MCU侧把NoStretchMode设为使能,就违反了I2C协议,通信会偶发失败。
3.2 寄存器封装:单字节读写与批量读写
PCA9422的寄存器都是单字节宽度,读写接口用ST的HAL_I2C_Mem_Read和HAL_I2C_Mem_Write封装一下就够了。我习惯在驱动层加一层带参数的函数,避免业务代码里到处出现裸的HAL调用。
#define PCA9422_ADDR 0x48 uint8_t PCA9422_ReadReg(uint8_t reg) { uint8_t val = 0; HAL_I2C_Mem_Read(&hi2c1, PCA9422_ADDR << 1, reg, I2C_MEMADD_SIZE_8BIT, &val, 1, 100); return val; } void PCA9422_WriteReg(uint8_t reg, uint8_t val) { HAL_I2C_Mem_Write(&hi2c1, PCA9422_ADDR << 1, reg, I2C_MEMADD_SIZE_8BIT, &val, 1, 100); } void PCA9422_UpdateBits(uint8_t reg, uint8_t mask, uint8_t val) { uint8_t tmp = PCA9422_ReadReg(reg); tmp &= ~mask; tmp |= (val & mask); PCA9422_WriteReg(reg, tmp); }这里有个细节值得单独说:写寄存器之前,尤其是写BUCK电压和充电电流这种关键参数之前,我强烈建议先读回当前值,只改需要改的位,不要整个字节覆盖。原因在于很多控制寄存器里既有你想改的电压位,也有电源模式位、使能位,直接覆盖大概率会把其他配置冲掉,导致输出莫名其妙关断。我在这上面吃过亏,改充电电流时把充电使能位清了,现场症状是电池电压往下掉,排查到PMIC才发现充电根本没工作。
批量读写场景不多,但读取状态寄存器组时有用。比如开机自检时要一次性读回设备ID、BUCK状态、充电状态等多个寄存器,用一个批量读函数可以减少I2C重复起始的开销。
3.3 中断与事件处理
PCA9422的INT引脚是开漏输出,低电平有效,接到STM32F411RE的一个EXTI引脚上。中断源包括充电完成、输入插入/拔出、NTC温度告警、欠压关断等。中断处理有个关键点:PMIC的中断状态寄存器是读后自动清零的,所以MCU侧必须在中断服务函数里把所有有效中断位读完,否则中断引脚不会释放,就会一直触发。
我的中断处理代码框架大致是这样:
void EXTI9_5_IRQHandler(void) { if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_6) != RESET) { __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_6); uint8_t status = PCA9422_ReadReg(REG_INT_STATUS); if (status & INT_CHARGE_DONE) { PowerState_SetChargeDone(); } if (status & INT_NTC_ALARM) { PowerState_SetNTCAlarm(); } } }在调试初期,我犯过一个错误,在中断服务函数里直接调用HAL_I2C_Mem_Read。HAL库的I2C读操作是阻塞式的,如果在中断里打断了一个正在进行的I2C写操作,总线状态就乱了。后来我把中断处理改成“置标志位+主循环处理”的模式,I2C操作全部放在主循环上下文里。这个改动之后,通信稳定性明显提升。
3.4 裸机快速验证Demo
硬件到手之后,别急着写完整逻辑,先用一个裸机Demo验证三件事:设备ID能读出来、BUCK能正常输出、充电能启动。这个Demo越简单越好。
void Power_QuickVerification(void) { uint8_t id = PCA9422_ReadReg(REG_DEVICE_ID); printf("Device ID: 0x%02X\r\n", id); // 使能一路BUCK输出 1.8V PCA9422_WriteReg(REG_BUCK1_CFG, 0x40 | 0x0A); // 使能充电,预充电流100mA,恒流500mA PCA9422_WriteReg(REG_CHARGE_CFG, 0x80 | 0x31); }设备ID读出来之后,先拿示波器看BUCK输出波形,确认电压和纹波正常,再测充电电流。这个顺序可以帮你把问题域隔离清楚,先排除数字通信问题,再验证模拟电源是否正确,如果第一步设备ID都读不到,后面一切都是空的。
4. 软件状态机:充电、运行、低功耗全流程管理
4.1 四个核心状态和迁移条件
电源管理逻辑我用一个状态机来组织,而不是散落在各个函数里的if判断。状态机的好处是迁移路径清晰,每个状态下能干的事和不能干的事都很明确,出问题也好定位。这个项目里我定义了四个核心状态,外加一个初始化特殊路径。
各状态定义如下表所示:
| 状态 | 含义 | 主要动作 |
|---|---|---|
| POWER_OFF | 关机 | 关闭全部输出,PMIC进入低功耗,MCU待机 |
| POWER_BOOT | 开机自检 | 读PMIC设备ID,初始化寄存器,检查电池电压 |
| POWER_RUN | 正常运行 | 根据负载动态调压,监控充电,响应事件 |
| POWER_CHARGE | 充电管理 | 配置充电参数,监测充电状态直到充满或拔出 |
由于文稿要求不使用流程图,这里用文字描述关键迁移路径:上电瞬间,电池电压只要高于PMIC的UVLO阈值且系统使能有效,PMIC默认输出保持电压先给MCU供电,MCU启动后进入POWER_BOOT。自检通过后,如果插入USB则进入POWER_CHARGE,否则进入POWER_RUN。POWER_RUN中检测到插入USB,迁移到POWER_CHARGE;检测到电源键长按关机事件,先保存上下文,然后配置PMIC关闭输出,进入POWER_OFF。POWER_CHARGE中检测到充满且USB已拔出,回到POWER_RUN。
这里面最容易被忽视的是“低电量保护”路径。我在POWER_RUN里加了一个电池电压监测任务,当电压低于3.3V时先触发告警,低于3.0V时直接进入POWER_OFF。这个阈值不是随手拍的,而是根据电池放电曲线和系统最小工作电压倒推的,算的时候要留出负载瞬态压降的余量。
4.2 充电参数配置,算清楚再写寄存器
充电参数的配置是整个PMIC驱动里最需要细心的地方。PCA9422的充电寄存器里包含预充电流、恒流电流、截止电流、充电安全时间等多个字段,每个字段的步进和范围手册里都有明确表格。我的习惯是先写一个配置表,把每个想设的目标值、寄存器字段、十六进制值都列出来,再往驱动里填,绝不现场心算。
以一块1000mAh的电池为例,我最终配置是这样的:预充电流取80mA,约为0.08C,预充阶段电压低于2.9V时以这个电流缓慢充电;恒流阶段取500mA,也就是0.5C,这是电池规格书推荐的室温最大充电倍率;恒压阶段4.2V;截止电流取50mA,约为0.05C;安全充电时间设为5小时。这样配置的目的是:既不过度保守导致充电时间过长,又不激进到影响电池寿命。
充电阶段切换的判断由PMIC硬件完成,但主控侧要定时读回充电状态寄存器,在日志里打点。实际调试中我见过一种情况:充电电流设置成800mA,但当电池电压比较低时,输入电压会被拉低,PMIC进入输入限流保护,实际充电电流上不去。这时候不一定是寄存器配置错了,而是输入源功率不足,需要降低充电电流设定值或者换更大功率的适配器。
4.3 BUCK动态调压:按负载调整电压
PCA9422的两路BUCK可以通过I2C在线调整输出电压,这是它相对于固定电压DCDC最大的优势。动态调压的收益在低功耗系统里非常明显:CPU跑满负荷时需要1.1V核心电压,空闲时降到0.9V,光是这一项就能省下不少动态功耗;射频PA或传感器需要供电时,电压在需要时再升上去,平时保持最低工作电压即可。
项目中我在两个场景里用了动态调压。第一路BUCK供给MCU主供电,根据MCU当前的运行模式和负载,在正常电压与高性能电压之间切换。第二路BUCK供给传感器,正常工作时1.8V,传感器关断时直接把BUCK关掉,把静态电流降到零。
实现上就是读自己的运行状态,然后调用驱动层的电压设置函数:
void Power_SetBuck1Voltage(POWER_VOLTAGE_LEVEL level) { switch (level) { case VOLTAGE_LOW: PCA9422_UpdateBits(REG_BUCK1_CFG, 0x3F, 0x0A); // 1.8V 示例 break; case VOLTAGE_HIGH: PCA9422_UpdateBits(REG_BUCK1_CFG, 0x3F, 0x14); // 2.2V 示例 break; default: break; } }这里有个细节需要特别提醒:切换电压时,PMIC内部BUCK输出端有一个软启动/软停止过程,输出电压是渐变过去的,不是突变。但如果在切换瞬间恰好有大电流负载,输出电压下降可能会让敏感的负载复位。所以动态调压前,最好先确认负载不会在切换瞬间拉大电流,或者在切换完成后加一个短暂的延时再跑高负载任务。
4.4 状态检测与日志输出
状态机跑起来之后,日志系统是排查问题的重要依赖。我习惯每个状态迁移都打印一条带时间戳的记录,格式类似“87 [POWER_RUN]->[POWER_CHARGE] reason=input_plugged”,同时在固定周期打印PMIC的关键寄存器快照。这样回看日志的时候,能很清楚地看到系统是何时、因为什么原因进入异常状态的。
日志输出在调试时用串口,量产时把日志关掉。不过有一个小建议:即使量产固件,也可以保留一个“诊断模式”的隐藏开关,通过特殊按键组合进入,把PMIC寄存器组、电池电压、充电状态打印出来。现场遇到问题的时候,没有这个开关会非常被动。
5. 低功耗优化:待机电流从毫安级压到微安级
5.1 先把功耗链路拉出来盘一遍
低功耗设计最忌讳的是“感觉应该省”而不去量。我做这个项目的时候,第一版待机电流实测有3.8mA,跟目标值差了快两个数量级。后来老老实实把功耗路径全部盘了一遍,才找到问题。
完整的待机电流路径是这样拆的:电池输出到PMIC的静态电流、PMIC各路BUCK/LDO的空载电流、MCU待机时的电流、I2C上拉电阻漏电流、NTC分压电阻漏电流、其他外围器件的静态电流,以及PCB上的漏电流。每一路都要测,不能跳。
5.2 PCA9422低功耗模式配置
PCA9422进入低功耗模式的关键,是在软件里先把不需要的输出关掉,再把PMIC切换到低静态电流模式。我的做法是:系统待机时,BUCK1维持给MCU的待机供电电压,BUCK2直接关闭,LDO关闭,充电和NTC检测保持工作。
具体的寄存器配置在项目中是通过PCA9422_UpdateBits完成的,比如关BUCK2时把对应使能位清零,再把PMIC模式寄存器切到低功耗位。这里特别注意一点,低功耗模式的配置顺序是先关外部负载,再关输出,最后切模式;恢复时顺序反过来。顺序搞反的话,关断瞬间的电压跌落可能会让系统在待机过程中意外复位。
5.3 STM32待机模式与外设电源域管理
STM32F411RE的待机电流本身可以做到很低,但前提是所有外设时钟、GPIO、以及外部器件都要配合好。我的经验是这几点必须逐一排查:GPIO引脚全部配置成模拟输入或者固定电平输出,不能有浮空引脚;I2C外设时钟在进待机前关掉;调试器的SWD引脚在量产板上要处理成不耗电的状态。
进待机前还有一个很容易漏的步骤:PCA9422的INT引脚在待机期间如果有事件触发(比如NTC温度漂移),会唤醒MCU,如果这个中断在待机期间不需要响应,需要在PCA9422侧屏蔽对应的中断源,否则设备会频繁被唤醒又误判为异常。
5.4 实测数据参考
经过第二轮优化之后,我测到的数据如下:
| 项目 | 优化前 | 优化后 |
|---|---|---|
| 系统待机电流(整机) | 3.8mA | 85uA |
| BUCK2关闭后节省 | - | 约0.6mA |
| MCU待机 | 1.2mA | 15uA |
| 正常运行(无线开启) | 42mA | 42mA |
85uA这个数据距离顶尖的低功耗产品还有差距,但对于这个项目来说已经够用。如果想继续往下压,可以考虑在待机期间把PCA9422的LDO和BUCK1都关掉,让MCU由一颗极低功耗的RTC或外部唤醒源来管理,不过那对系统可靠性要求会更高,需要权衡。
6. 实际调试中的问题与解决实录
6.1 I2C通信偶发失败
现象是系统运行几分钟后,某一次读PMIC寄存器返回超时,之后通信恢复。排查时我先看波形,发现SCL/SDA的上升沿比较缓,接近快速模式极限。原因是I2C上拉电阻用了4.7k且走线较长,分布电容偏大。把上拉改成1.8k之后问题消失。这个问题的隐蔽之处在于它不是必然失败,而是低温、高温、走线分布电容差异等条件下概率性出现,非常难以复现。建议硬件设计时I2C线路总电容控制在100pF以内。
6.2 BUCK输出电压纹波偏大
示波器测量BUCK1输出,纹波有30mV,超过预期。检查发现电感是淘宝买的标称2.2uH,实际在1A电流下电感量衰减得很厉害,属于饱和特性比较差的一类。换成了额定电流更高的功率电感之后,纹波降到8mV。这提醒我一件事:电感的核心参数不只是标称感值,还有“叠加直流偏置后的实际电感量”,选型时一定要看电感值-电流曲线。
6.3 充电电流一直上不去
配置了500mA充电电流,实测只有200mA左右。排查过程从PMIC寄存器确认配置没错,再测输入电压发现USB接入之后电压被拉到4.6V,PMIC进入了输入限压模式。原因是USB线缆电阻偏大,加上输入端接触电阻,导致大电流下压降过大。换了一根粗线,同时把充电电流降到300mA后恢复正常。这个问题在原型阶段很常见,根本解决办法是输入端走线加粗、连接器选低阻抗类型。
6.4 系统唤醒后状态错乱
设备从待机态唤醒后,PMIC状态和MCU侧记录的软件状态对不上,比如BUCK2的寄存器值显示关闭但MCU认为它在工作。原因是在进待机前,MCU侧的电源状态变量没有同步刷新。后来把所有电源状态都以“读PMIC寄存器”为准,MCU侧变量只作为缓存,并加上每次唤醒后的强制刷新逻辑,问题解决。
6.5 NTC温度保护误触发
表现为刚插上充电没多久,PMIC就报告NTC温度告警。实际用测温枪测电池只有二十几度,根本没到阈值。检查硬件才发现,NTC分压电阻的精度不够,而且PCB走线到PMIC引脚之间有一个额外的寄生电容,导致比较器输入在边缘状态抖动。换成1%精度电阻,在NTC引脚侧加了一个小电容滤波后,误触发消失。
6.6 调试问题速查表
最后整理一个排查速查表,我在调试那几天反复用,非常管用:
| 现象 | 优先检查项 | 常见原因 |
|---|---|---|
| I2C超时 | 地址、上拉、电平、时钟延展 | SM引脚地址不对,上拉过大 |
| I2C偶发失败 | 上升沿、走线长度、总线电容 | 分布电容过大,上拉阻值过高 |
| BUCK无输出 | 使能位、电感、输入电压 | 寄存器覆盖写清除了使能位 |
| 纹波偏大 | 电感特性、输出电容、SW走线 | 电感饱和电流不够,SW回路太大 |
| 充电电流偏低 | 输入电压、线缆电阻、充电配置 | 输入源限压,路径电阻偏高 |
| 待机电流偏高 | GPIO浮空、PMIC模式、外围漏电 | 输出没全关、GPIO浮空 |
| NTC误触发 | 分压精度、布线寄生 | 电阻精度差、引脚受扰 |
我在实际调试中最深的体会是:电源管理项目里,90%的问题都出在“想当然”的地方。以为寄存器没问题,结果是被别的代码覆盖了;以为电感没问题,结果饱和电流根本不够;以为待机就省电,结果一个浮空GPIO漏了几百微安。所以这篇博客写到最后,最想给同行提的建议就是两件事:一是所有关键参数都先用表格列清楚再动手,二是任何一次改动都先读回寄存器确认生效,不要相信代码里的变量值,以硬件的真实状态为准。
最后再分享一个小技巧:调试这类PMIC项目时,尽量在你的测试板上留出一组测试点,把BUCK输出、电感前端SW节点、电池端电压、I2C的SCL/SDA全部引到测试点。测量纹波、抓取时序、排查问题的时候,这对测试点是救命的存在。我这张板子就是因为预留了这些测试点,后面几乎所有调试工作都变得高效了很多。