1. 从一颗芯片到一套供电系统:这个项目到底在解决什么问题
如果你做过带锂电池的便携设备,大概率经历过这样的场景:主控芯片选好了,传感器也定了,结果到了画电源部分,发现光是给各个模块配LDO和充电管理就要占掉小半张板子。更头疼的是,锂电池电压从4.2V掉到3.0V的过程中,如果直接用LDO降压,效率低得可怜,发热还严重。这时候如果有一颗芯片能把充电管理、多路降压、电量计、I2C控制全都塞进去,事情就简单多了。
PCA9422就是干这个的。它是一颗面向低功耗应用的电源管理芯片,内部集成了线性充电器、多路降压转换器(Buck)、LDO,以及一个可以通过I2C读写寄存器的控制接口。而PIC18F55K42是Microchip的一款8位单片机,带I2C外设,成本低、资源够用,非常适合做电源管理的主控。把这两颗芯片组合起来,就能搭出一套完整的电源管理方案:单片机通过I2C配置PCA9422的充电参数、输出电压、工作模式,同时读取芯片的状态寄存器,实现充电状态监控、故障检测、动态电压调节等功能。
这个项目的核心价值在于:用一颗PMIC加一颗低成本的8位MCU,替代传统分立式电源方案,减少BOM数量、缩小PCB面积、提升系统可靠性。适合做便携医疗设备、手持仪器、IoT终端、电池供电的数据采集器等场景的开发者参考。如果你正在纠结电源部分怎么设计,或者想从分立方案迁移到PMIC方案,这篇内容会把整个链路拆开讲清楚。
我下面会从芯片选型逻辑、硬件连接、I2C通信实现、寄存器配置、充电管理、动态调压、故障处理这几个维度展开,尽量把每个环节的“为什么”和“怎么做”都说明白。文中涉及的寄存器地址和参数值,我会给出典型值,但具体项目一定要以数据手册为准,因为不同批次的芯片可能有细微差异。
2. 为什么选PCA9422加PIC18F55K42这个组合
2.1 PCA9422的电源管理能力拆解
PCA9422是一颗高度集成的PMIC,内部结构大致可以分成几个模块:线性充电器、降压转换器、LDO、I2C控制逻辑、以及各种保护电路。充电器部分支持锂电池的恒流恒压充电,充电电流和终止电压都可以通过寄存器配置。降压转换器通常有两路或三路,输出电压可以通过I2C动态调节,适合给MCU核心、传感器、射频模块分别供电。LDO一般用于给低噪声模拟电路供电,比如ADC参考电压或者传感器模拟前端。
这颗芯片的关键优势在于集成度高。传统方案里,充电管理用一颗芯片,降压用另一颗,LDO再单独配,每颗芯片都要外围电容电阻,加起来占的面积和成本都不低。PCA9422把这些都集成到一颗芯片里,外围只需要几个电感和电容,PCB面积能省下不少。另外,它支持I2C接口,意味着MCU可以实时读取芯片状态,比如充电是否完成、是否发生过温保护、输入电压是否正常等,这对于需要做电池管理的设备来说非常实用。
还有一个容易被忽略的点:PCA9422的降压转换器支持动态电压调节。也就是说,MCU可以在运行过程中通过I2C修改输出电压。比如设备在待机时把核心电压降到1.8V省电,需要跑高性能任务时再升到3.3V。这种灵活性是分立方案很难做到的,因为分立方案的输出电压通常由电阻分压固定,改起来要动硬件。
2.2 PIC18F55K42作为主控的合理性
PIC18F55K42是Microchip的8位单片机,核心是PIC18架构,主频可以跑到64MHz,带I2C、SPI、UART等外设,Flash和RAM对于电源管理任务来说绰绰有余。选它做电源管理主控,主要考虑几个因素:成本低、I2C外设稳定、开发工具成熟。
有人可能会问,为什么不用更便宜的STM8或者国产MCU?原因在于PIC18F55K42的I2C外设支持多主模式和从模式,而且有独立的波特率发生器,配置灵活。另外,Microchip的MCC(MPLAB Code Configurator)工具可以图形化配置I2C参数,生成初始化代码,省去手动计算寄存器的麻烦。对于电源管理这种对时序要求不算极端苛刻、但对可靠性要求高的场景,PIC18F55K42是一个很平衡的选择。
还有一点:PIC18F55K42的工作电压范围宽,支持1.8V到5.5V,可以直接由PCA9422的某一路降压输出供电,不需要额外的电平转换。这在系统设计上简化了不少。
2.3 两颗芯片的协同工作模式
整个系统的供电架构是这样的:锂电池接入PCA9422的充电输入端,PCA9422负责给电池充电,同时把电池电压降压后输出给PIC18F55K42和其他负载。PIC18F55K42通过I2C总线连接PCA9422,上电后先初始化I2C外设,然后读取PCA9422的器件ID确认通信正常,接着配置充电参数和输出电压,最后进入主循环,定期轮询PCA9422的状态寄存器。
这里有一个设计要点:PIC18F55K42的供电必须来自PCA9422的某一路输出,而且这一路输出要在上电时默认使能。PCA9422的降压转换器通常有默认输出电压(比如3.3V),不需要MCU配置就能工作。这样MCU上电后才有电跑代码,再去配置其他路输出。如果所有输出都需要MCU配置才使能,那就成了“鸡生蛋蛋生鸡”的问题。所以硬件设计时一定要确认哪一路是默认开启的,把MCU挂在这一路上。
3. 硬件连接与I2C总线的物理层设计
3.1 电源输入与电池接口的走线要点
锂电池通过连接器接入PCA9422的VBAT引脚,充电输入通常来自USB或者DC插座,接到VIN引脚。这两个引脚的走线要尽量短粗,因为充电电流可能达到几百毫安甚至1A以上。如果走线太细太长,压降会很明显,导致充电效率下降甚至充电异常。
VBAT和VIN附近要放足够的去耦电容,典型值是10uF加0.1uF的组合。10uF负责滤低频纹波,0.1uF负责滤高频噪声。电容要尽量靠近芯片引脚,否则滤波效果打折扣。我见过一些设计把电容放在板子另一头,结果充电时纹波大得离谱,芯片频繁触发保护。
电池连接器建议用带极性的插座,防止反接。虽然PCA9422内部有防反接保护,但反接时电流会流过保护电路,发热严重。如果产品面向普通用户,反接保护是必须的。
3.2 I2C上拉电阻的取值计算
I2C总线需要上拉电阻,这是老生常谈但经常被忽略细节的地方。上拉电阻的取值取决于总线电容和通信速率。PCA9422支持标准模式(100kHz)和快速模式(400kHz),PIC18F55K42的I2C外设也支持这些速率。
假设总线电容Cb是100pF,通信速率是400kHz,上升时间tr要求小于300ns。根据公式Rp(max) = tr / (0.8473 × Cb),算出来Rp(max)大约是3.5kΩ。所以上拉电阻不能大于3.5kΩ,否则上升沿太慢,通信会出错。但也不能太小,太小会导致灌电流过大,增加功耗。典型值取2.2kΩ到4.7kΩ之间。
实际项目中,如果总线上挂了多个从机,总线电容会增大,上拉电阻要相应减小。但减小到1kΩ以下就要注意了,因为PCA9422的I2C引脚灌电流能力有限,太小可能拉不低。我一般先用2.2kΩ试,用示波器看上升沿,如果太慢就换1.5kΩ,如果波形有振铃就适当增大。
注意:上拉电阻要接到MCU的IO电压域,不是接到电池电压。如果MCU是3.3V供电,上拉就接3.3V,不要接5V,否则可能损坏PCA9422的I2C引脚。
3.3 中断引脚的利用与GPIO分配
PCA9422通常有一个中断输出引脚,可以在充电状态变化、故障发生时拉低,通知MCU。这个引脚接到PIC18F55K42的外部中断引脚上,可以避免MCU频繁轮询I2C,降低功耗。比如充电完成时,PCA9422拉低中断,MCU在中断服务程序里读取状态寄存器,确认后关闭充电指示灯或者进入下一步逻辑。
如果不用中断,MCU就得定期轮询,比如每100ms读一次状态寄存器。轮询的好处是逻辑简单,坏处是功耗略高,而且响应有延迟。对于电池供电的设备,建议用中断方式,让MCU大部分时间处于休眠,中断来了再唤醒。
PIC18F55K42的GPIO资源丰富,除了I2C和中断引脚,还可以分配几个IO做LED指示、按键输入、或者控制其他外设。建议在PCB上预留测试点,方便调试时用逻辑分析仪抓I2C波形。
4. I2C通信协议的软件实现细节
4.1 PIC18F55K42的I2C外设初始化
PIC18F55K42的I2C外设配置涉及几个关键寄存器:波特率寄存器、控制寄存器、状态寄存器。用MCC工具可以图形化配置,但了解底层寄存器有助于排查问题。
初始化步骤大致如下:先设置I2C引脚为输入方向(开漏输出),然后配置波特率。假设系统时钟是64MHz,I2C时钟是400kHz,波特率分频值计算为:Fosc / (4 × Fscl) - 1 = 64M / (4 × 400k) - 1 = 39。所以波特率寄存器写39。然后使能I2C模块,等待总线空闲。
初始化完成后,不要急着发数据,先做一个总线恢复操作。如果上次通信异常导致从机把SDA拉低,总线会一直忙。恢复方法是:把SCL配置为普通IO,手动发9个时钟脉冲,然后发一个停止条件。这个技巧在实际调试中非常有用,能解决很多“I2C突然不工作”的问题。
4.2 写寄存器的完整时序与代码示例
写PCA9422寄存器的流程是:发启动条件,发从机地址加写位,等ACK,发寄存器地址,等ACK,发数据,等ACK,发停止条件。每一步都要检查ACK,如果从机没应答,说明地址错了或者从机没准备好。
下面是一段简化的写寄存器函数,基于PIC18F55K42的I2C外设:
uint8_t PCA9422_WriteReg(uint8_t reg, uint8_t data) { I2C_Start(); if (I2C_WriteByte(PCA9422_ADDR << 1 | 0) != ACK) { I2C_Stop(); return 1; // 地址无应答 } if (I2C_WriteByte(reg) != ACK) { I2C_Stop(); return 2; // 寄存器地址无应答 } if (I2C_WriteByte(data) != ACK) { I2C_Stop(); return 3; // 数据无应答 } I2C_Stop(); return 0; // 成功 }这段代码里,I2C_WriteByte函数负责发送一个字节并返回ACK状态。实际项目中,每次写操作后建议加一个小延时,比如10us,让PCA9422有时间处理。虽然数据手册说芯片响应很快,但实测中不加延时偶尔会出现连续写失败的情况。
4.3 读寄存器的重复启动与数据解析
读寄存器比写多一个步骤:先写寄存器地址(告诉从机要读哪个寄存器),然后发重复启动条件,再发从机地址加读位,接着读数据,最后发NACK和停止条件。
uint8_t PCA9422_ReadReg(uint8_t reg, uint8_t *data) { I2C_Start(); if (I2C_WriteByte(PCA9422_ADDR << 1 | 0) != ACK) { I2C_Stop(); return 1; } if (I2C_WriteByte(reg) != ACK) { I2C_Stop(); return 2; } I2C_Start(); // 重复启动 if (I2C_WriteByte(PCA9422_ADDR << 1 | 1) != ACK) { I2C_Stop(); return 3; } *data = I2C_ReadByte(); I2C_SendNACK(); I2C_Stop(); return 0; }读回来的数据要根据寄存器定义解析。比如状态寄存器里某一位表示“充电完成”,另一位表示“输入过压”,还有几位表示当前充电阶段。解析时要用位掩码,不要直接比较整个字节,否则其他位变化会导致误判。
5. 充电参数配置与电池管理策略
5.1 充电电流与终止电压的寄存器设置
PCA9422的充电电流和终止电压通过寄存器配置。充电电流通常有一个计算公式,比如Icharge = (寄存器值 / 某系数) × 基准电流。具体系数要查数据手册。假设基准是10mA,寄存器值范围是0到31,那么最大充电电流是310mA。实际设置时,要根据电池容量来定,一般充电电流不超过电池容量的1C。比如1000mAh的电池,充电电流设500mA到1000mA之间比较合适。
终止电压通常是4.2V,但有些电池是4.35V或4.4V。设置错了会导致电池充不满或者过充。过充会损坏电池甚至引发安全问题,所以这个参数一定要按电池规格书来。如果不确定,先用4.2V保守设置。
充电电流和终止电压的寄存器通常有写保护,需要先解锁某个寄存器才能修改。解锁序列一般是向特定寄存器写特定值,具体参考数据手册。我建议在初始化代码里把解锁、配置、锁定写成一个函数,避免每次修改都手动操作。
5.2 充电状态机的轮询与中断处理
PCA9422内部有一个充电状态机,状态包括:未充电、预充电、恒流充电、恒压充电、充电完成、故障。MCU可以通过读取状态寄存器获取当前状态。
如果用轮询方式,主循环里每100ms读一次状态寄存器,根据状态更新LED指示或者上报给上位机。轮询的缺点是功耗高,因为MCU要定期唤醒。如果用中断方式,PCA9422状态变化时拉低中断引脚,MCU在中断里读状态寄存器,处理完再清除中断标志。
中断方式的代码结构大致是:中断服务程序里读状态寄存器,判断是哪种事件,设置一个全局标志,主循环根据标志做后续处理。注意中断服务程序要尽量短,不要在里面做I2C读写之外的重活,否则可能影响其他中断响应。
5.3 温度监测与充电安全保护
锂电池充电时温度过高或过低都有风险。PCA9422通常支持外接热敏电阻,通过内部ADC读取温度,在温度超出范围时暂停充电。热敏电阻一般贴在电池表面,阻值随温度变化,PCA9422根据阻值判断温度。
配置温度保护需要设置几个阈值:低温阈值、高温阈值、恢复阈值。比如低温低于0度暂停充电,高温高于45度暂停充电,温度回到5到40度之间恢复充电。这些阈值通过寄存器设置,具体值参考电池规格书。
如果不用外接热敏电阻,也可以用MCU内部的温度传感器做粗略监测,但精度不够,不建议用于安全保护。安全相关的功能一定要用独立的热敏电阻,而且要做好冗余设计。
6. 动态电压调节与低功耗模式切换
6.1 降压转换器输出电压的实时调整
PCA9422的降压转换器输出电压可以通过I2C实时修改。比如设备在待机时把MCU核心电压从3.3V降到1.8V,功耗能降低不少。调整步骤是:先读当前输出电压寄存器,计算出目标值对应的寄存器值,写入,然后等待电压稳定(通常几十微秒),再让MCU切换到低压运行。
这里有一个坑:降压转换器的输出电压不能突变太大。如果从3.3V直接跳到1.8V,输出电容上的电荷会通过负载放电,可能导致电压跌落过大,MCU复位。正确的做法是分步调整,比如先降到2.5V,延时,再降到1.8V。或者用转换器的软启动功能,让电压缓慢变化。
另外,修改输出电压前要确认MCU的工作电压范围。PIC18F55K42支持1.8V到5.5V,所以降到1.8V没问题。但如果系统里有其他器件只支持3.3V,就不能随便降。
6.2 休眠模式下的电源域管理
设备进入休眠时,可以把不用的电源域关掉。PCA9422的每一路降压和LDO通常都有使能位,通过I2C可以单独关闭。比如传感器只在采集时供电,采集完就关掉,待机电流能降到微安级。
关闭电源域的顺序要注意:先关负载,再关电源。如果先关电源,负载上的电容可能通过负载放电,产生反向电流,影响芯片寿命。正确顺序是:MCU先通知负载进入休眠,延时,然后关闭对应的电源输出。
唤醒时顺序相反:先开电源,延时等待电压稳定,再唤醒负载。这个延时不能省,否则负载可能在电压没稳时就启动,导致初始化失败。
6.3 唤醒源配置与快速恢复
PIC18F55K42支持多种唤醒源:外部中断、定时器、串口接收等。在电源管理场景下,常用的是外部中断(比如按键唤醒)和定时器(定期采集)。唤醒后,MCU要快速恢复I2C通信,重新配置PCA9422的输出电压和电源域。
快速恢复的关键是保存上下文。在进入休眠前,把当前的电源配置参数保存在RAM里,唤醒后直接根据保存的参数恢复,不需要重新计算。这样能缩短唤醒时间,提升用户体验。
如果唤醒后需要立即通信,比如上报数据,要确保PCA9422的输出电压已经稳定。可以在唤醒后加一个几毫秒的延时,或者读PCA9422的状态寄存器确认电源正常。
7. 调试过程中容易踩的坑与排查思路
7.1 I2C通信失败的常见原因
I2C通信失败是最常见的问题,表现是MCU发地址后收不到ACK。排查思路如下:
第一,检查硬件连接。用万用表测SDA和SCL对地电阻,正常应该是上拉电阻的阻值。如果接近0,说明有短路。如果无穷大,说明断路。
第二,检查上拉电阻。如果上拉电阻太大,上升沿太慢,高速通信会失败。用示波器看波形,上升时间超过1us就要减小上拉电阻。
第三,检查从机地址。PCA9422的I2C地址可能是7位,发的时候要左移一位再加读写位。地址错了肯定没ACK。
第四,检查电源。PCA9422的VIN和VBAT都要有电,如果只有VBAT没VIN,芯片可能不工作。用万用表测各引脚电压,确认在正常范围。
第五,检查总线电容。如果总线上挂了多个从机,电容太大,上拉电阻要相应减小。但减小到1kΩ以下就要注意灌电流问题。
我遇到过一次,I2C死活不通,最后发现是PCB上SDA和SCL走线交叉了,飞线解决。所以画板子的时候一定要仔细检查。
7.2 充电异常的诊断流程
充电异常的表现有:充不进电、充电电流不对、充电指示灯不亮等。诊断流程如下:
先读PCA9422的状态寄存器,看充电状态机在哪个状态。如果是“未充电”,检查VIN是否有电,电池是否接好。如果是“故障”,读故障寄存器,看是过温、过压还是其他问题。
如果状态正常但电流不对,检查充电电流寄存器的设置。用电流表串在电池回路里测实际电流,和设置值对比。如果差太多,可能是寄存器值算错了,或者电池电压太低进入了预充电模式。
如果充电指示灯不亮,检查LED的驱动电路。有些设计用PCA9422的GPIO直接驱动LED,有些用MCU的IO驱动。如果是MCU驱动,检查MCU是否在读状态寄存器后正确控制了IO。
7.3 动态调压导致系统复位的排查
动态调压时系统复位,通常是电压跌落太大导致的。排查方法:用示波器看降压输出波形,在调压瞬间是否有大的跌落。如果有,说明输出电容不够或者调压步进太大。
解决办法:增加输出电容,比如从10uF增加到22uF。或者分步调压,每次降0.3V,延时后再降。还可以启用降压转换器的软启动功能,让电压缓慢变化。
另外,检查MCU的复位阈值。PIC18F55K42的复位电压通常在1.6V左右,如果降压输出跌到1.6V以下,MCU就会复位。所以调压时最低电压不能低于MCU的最低工作电压。
8. 从原型到产品的工程化建议
8.1 PCB布局中的电源完整性考虑
电源管理芯片的PCB布局直接影响性能。PCA9422的输入电容、输出电容、电感都要尽量靠近芯片引脚。电感下面不要走信号线,避免耦合噪声。I2C走线要远离电感和开关节点,防止干扰。
地平面要完整,不要被走线割裂。模拟地和数字地可以单点连接,但电源管理芯片的地要接到主地平面,不要单独走细线。散热焊盘要打足够多的过孔,帮助芯片散热。
如果充电电流较大,VBAT和VIN的走线要加宽,比如1A电流至少要走40mil宽。过孔也要多打几个,降低阻抗。
8.2 固件中的异常恢复机制
固件要有异常恢复机制。比如I2C通信连续失败3次,就重新初始化I2C外设,再试。如果还是失败,可以尝试复位PCA9422(如果有复位引脚),或者进入安全模式,只保持基本供电。
看门狗定时器要启用,防止MCU死机。看门狗超时时间根据任务周期设置,比如主循环100ms一次,看门狗设500ms。在中断服务程序里也要喂狗,但要注意不要喂太频繁,否则失去意义。
关键参数要保存在EEPROM里,比如充电电流、输出电压。这样即使断电重启,也能恢复到之前的配置。保存时要注意写平衡,不要频繁写同一个地址。
8.3 量产测试与参数校准
量产时要测试每块板的充电功能和I2C通信。测试项目包括:充电电流是否在范围内、终止电压是否准确、I2C读写是否正常、各路输出电压是否正确。
如果发现参数偏差,可以在固件里做校准。比如充电电流实测偏小,可以在寄存器值上加一个补偿量。校准值存在EEPROM里,每块板单独校准。
测试工装可以用一块带MCU的板子做主机,通过I2C连接被测板,自动跑测试流程,记录结果。这样能提高测试效率,减少人为误差。
9. 个人经验总结与后续扩展方向
这套方案我在几个便携设备项目里用过,整体稳定性不错。最大的体会是:电源管理芯片的寄存器配置一定要仔细核对数据手册,尤其是充电电流和终止电压,设错了轻则充不满,重则损坏电池。另外,I2C总线的上拉电阻和走线布局比想象中重要,很多通信问题都是硬件引起的,软件再怎么调也没用。
后续如果想扩展,可以考虑几个方向:一是增加电量计功能,PCA9422本身可能不带库仑计,但可以通过MCU的ADC读取电池电压,结合放电曲线估算电量。二是增加USB PD协商功能,如果充电输入支持PD,可以用MCU控制PD控制器,实现快充。三是把电源管理逻辑做成状态机,用RTOS的任务来管理,代码结构会更清晰。
最后分享一个小技巧:调试I2C时,如果手头没有逻辑分析仪,可以用MCU的IO口模拟I2C,在关键步骤翻转一个IO,用示波器看时序。虽然麻烦,但能解决大部分问题。