☰
基于PCA9422与PIC18F45K80的电池供电设备电源管理方案
2026/10/24 1:13:10 网站建设 项目流程

去年年底我在做一个电池供电的便携式数据采集设备,需要同时管理一个锂电池的充放电、多路电源输出和整机状态上报。一开始图省事,直接拿一颗DCDC加几颗LDO拼方案,结果画完板子才发现,光是充电管理、外接电源切换、过压保护这些功能就占掉了一堆外围器件,板子面积越做越大,调试时还要抱着万用表一个个量。后来我改成 PCA9422 配合 PIC18F45K80 的完整电源管理方案,才算把这块理顺。这篇文章把整个方案从选型、硬件连接、软件状态机到调试中踩过的坑完整记录下来,如果你也在做低功耗、电池供电、多路电源输出的设备,这篇应该能帮你省不少时间。

先说结论:PCA9422 负责把"电"这件事管住——充电、路径切换、多路输出、保护逻辑都在它内部完成;PIC18F45K80 负责把"策略"这件事管住——什么时候允许充电、什么时候切到低功耗、出了故障怎么上报。两者分工明确,整机电源系统就不再是散件拼凑,而是一个可配置、可监控的整体。

1. 这个方案的分工逻辑:为什么电源芯片和主控必须分开

1.1 全部分散器件自己做,刚开始省钱,后期全是债

很多做嵌入式的朋友一看到电源管理,第一反应是"用DCDC加LDO搭一个就行了"。方案本身没错,但当你做的产品需要锂电池供电、需要外接适配器充电、需要从同一个电池引出多路电压,事情就复杂了。

普通散件方案至少需要这些器件:一颗充电管理IC、一颗升压或降压芯片、几颗LDO、一个电源路径切换用的Load Switch、若干电压比较器做欠压告警。每增加一个器件,板子上就多几颗电阻电容,多一种失效模式,多一段调试时间。更要命的是,充电参数(比如恒流电流、充饱电压)基本靠外部电阻设定,产品量产时想微调一下,就得改电阻,很痛苦。

我上一版设计就是这么翻车的。充电、路径、输出、保护四条链路各自独立,测试时发现充电电流漂移、负载切换瞬间掉电、低压保护阈值不准,每个问题都得单独查。板子在打样回来后,大半精力都耗在电源链路的联调上。

1.2 PCA9422 把"电"的所有细节收进去

PCA9422 是一颗集成了充电管理、电源路径管理和多路输出控制的PMIC。所谓"完整电源管理",就是这颗芯片在硬件层面把传统散件方案中的充电控制、适配器/电池路径切换、DC-DC输出、LDO输出、电压电流检测、保护逻辑全部整合到一起。

这颗芯片最核心的几个能力:

  • 支持单节锂电池充电管理,恒流恒压流程自动完成,充电电流、充饱电压可以通过I2C寄存器配置。
  • 带电源路径管理,适配器接入时系统直接由适配器供电,同时给电池充电;适配器断开时自动切到电池供电,切换过程由内部逻辑完成,不需要外部MOS管和控制逻辑。
  • 内部集成多路输出,一路高频Buck、一路Bias-Buck加LDO,覆盖数字核心、模拟前端和外设供电需求。
  • 充电状态、电源状态、故障状态都有对应寄存器可以查询,还能通过中断引脚主动通知主控。

这些能力放在一年前,我得用三到四颗芯片外加上万用逻辑才能搭出来。现在一颗PMIC就解决了,而且大部分参数不是靠电阻硬配,而是软件可调,这对后期调优和量产维护非常友好。

1.3 PIC18F45K80 的任务在决策层

主控芯片我选定的是 PIC18F45K80,这颗8位MCU带一个硬件I2C模块和12位ADC,还有片内EEPROM可以存配置参数。这台设备需要采集多路传感器数据并上报,MCU本身就在现场,让它顺带管电源策略几乎是零成本。

PIC18F45K80 在这套方案里的任务非常明确:

  • 通过 I2C 访问 PCA9422 的所有寄存器和状态标志;
  • 通过 GPIO 控制 PMIC 的使能引脚,实现整机开关机时序;
  • 通过 ADC 采集电池电压、检测关键点温度,参与充放电策略判断;
  • 响应 PCA9422 的中断引脚,及时处理充电完成、适配器插拔、过流过压等事件;
  • 把电源事件记录到EEPROM,方便排障。

为什么不让PCA9422直接自动干活、MCU什么都不管?因为不同产品的充放电策略差异太大。有的设备需要充电优先,有的设备需要电池保电优先,有的设备在电量低于20%就必须自动关机。这些策略PMIC做不了,必须由主控根据产品需求写逻辑。所以这套方案我强烈建议采用"PMIC管硬件、MCU管策略"的分工。

2. 供电链路拆解:电池、适配器、多路负载各自怎么走

2.1 电源路径管理的价值:省掉一颗Load Switch

理解 PCA9422,建议先理解它的电源路径管理。传统方案里,电池和适配器两路电源要同时接到系统电源轨,必须用Load Switch加控制逻辑防止两路互相灌电。如果系统还用电池充电,适配器一方面要给系统供电,一方面还要给电池充电,这里面的优先级关系很容易搞出问题。

PCA9422 内部已经把路径切换做掉了。适配器插入时,它自动让适配器供电给系统负载,同时用适配器剩余能量给电池充电;适配器拔出瞬间,内部开关自动切到电池路径,系统不会掉电。这套机制对外表现非常接近一个"无缝供电电源",不需要主控参与切换。

我实测印象比较深的一点是,拔插适配器的瞬间,系统电压能够保持稳定。换成以前的散件方案,电压会先掉到电池电压以下再恢复,很多对电压敏感的外围器件就会直接复位。

2.2 多路输出的分配方案

PCA9422 内部有多路输出,我在项目里这样分配:

电源轨由哪一路提供电压设置负载
VDD_MCU主Buck输出3.3VPIC18F45K80及数字部分
VDD_SENSOR辅助Buck输出3.0V传感器、信号调理
VDD_ANA内部LDO输出2.8V模拟前端、基准源
VDD_IO与VDD_MCU同轨3.3VI2C上拉、外部接口电平

这里有个经验:数字核心和模拟链路尽量分开供电。如果传感器和MCU共用同一路输出,传感器采集到的信号会有明显的纹波耦合。我一开始把传感器挂在MCU同一轨上,采样数据的方差偏大,后来单独用一路Buck给传感器供电,量化噪声立刻降了一个数量级。

各路输出电压我在初始化时通过I2C写入,不需要改电阻。这样后期如果某个传感器的供电要求从3.0V调整到2.8V,只需要改一个寄存器的值,重新烧录固件就行,比改BOM快太多。

2.3 状态反馈通道怎么用

PCA9422 对外有一个中断输出引脚,我接到 PIC18F45K80 的外部中断输入。凡是适配器插入、适配器拔出、充电完成、电池欠压、过温、过流这类事件,PMIC都会在这根引脚上产生一个有效电平。具体的故障类型,主控再通过I2C读取状态寄存器确认。

除了中断引脚,PMIC 内部的许多工作参数也是可以实时回读的。比如当前充电电流、电池电压、适配器电压、芯片温度,都对应有寄存器。主控可以在主循环里定时读取,一旦发现充电电流异常、电池电压掉得异常快,就能提前上报,而不是等保护动作才算完。

我用这套状态反馈机制做过一次很实用的功能:当充电完成中断触发后,MCU通过I2C确认状态寄存器,再通过一个GPIO点亮指示灯,告诉用户"充满了"。整个判断逻辑不涉及任何外部比较器,代码量不超过三十行。

3. 硬件连接细节:每一根线都值得确认一遍

3.1 PCA9422 与 PIC18F45K80 的引脚映射

我在原理图里最基本的连接关系如下表:

信号名称PCA9422引脚PIC18F45K80引脚说明
SDASDARC4注意上拉,且电平必须匹配
SCLSCLRC3注意上拉,且电平必须匹配
INTBINTBRB0外部中断输入,建议加RC滤波
EN_MAINENRA2主控输出,控制PMIC总使能
VBAT_SENSE—AN0直接采样电池电压
PGOODPGRC5电源正常标志

SDA和SCL的I2C总线必须接上拉电阻,我用的4.7kΩ,总线速率跑在100kHz,波形干净。如果你要跑400kHz,建议把上拉电阻改到2.2kΩ左右,并尽量缩短走线。

INTB接到RB0,我利用的是RB0的外部中断功能。这里提醒一句,PCA9422的中断输出往往是开漏结构,需要外部上拉电阻。我一开始忽略了这一点,INTB引脚悬空,结果中断事件发生时主控一个信号都收不到。

3.2 输入电源与电池端的器件选型

电池VBAT的引脚上一定要就近放一组储能电容。我用了10uF陶瓷电容加0.1uF高频去耦电容的组合,全部贴着芯片引脚放。不要只放一个大电容,因为PMIC内部高频开关产生的电流纹波需要低阻抗的0.1uF来完成滤除。

电感选型方面,Buck输出电感我选了饱和电流大于负载峰值1.5倍、直流电阻尽量低的型号。如果电感饱和电流不够,负载突变时会出现电感饱和,输出电压跌落,严重时会让MCU复位。PCB布局时电感底下尽量不要走信号线,防止磁场耦合干扰。

手工焊接这颗PMIC的时候,它采用了类似QFN的封装,焊盘在底部,比较考验手工。我建议先刷锡膏,用热风枪低温焊接,再用烙铁补焊周边脚位。焊完后一定要用万用表确认相邻引脚无桥连,特别是电源和地之间。我焊第一块板时就因为底部焊盘虚焊,导致芯片发热严重,整机工作电流异常偏大。

3.3 电平匹配是很容易被忽略的坑

PCA9422 的I2C引脚电平跟它的VIO电源有关,如果它的VIO接1.8V,而PIC18F45K80工作电压是3.3V,那I2C引脚直接对接肯定不能满足两个器件的高低电平阈值要求。

我这个项目里PCA9422的VIO直接用的3.3V,和PIC18F45K80一致,所以SDA、SCL、INTB、EN全部直连,不需要电平转换。如果你手头芯片的VIO电平是1.8V,就必须在I2C线上加电平转换芯片,或者用两个MOS管搭简单的双向电平转换电路。

另外还要注意,PIC18F45K80的I/O口如果是5V兼容的,但PMIC的引脚不是,稍不留意就会把PMIC的I2C引脚拉坏。接插件和测试点上明确标识电压等级,这在调试阶段能避免很多误操作。

3.4 电池采样和保护

PCA9422 在做充电电流检测时需要一个外部采样电阻。这个电阻我选的是1毫欧,精度0.5%,温漂系数要低。采样电阻阻值选大了会多耗散功率,选小了充放电流检测精度不够。具体阻值选择,要按照系统最大充放电流和PMIC内部电流检测放大器的增益来算,不能拍脑袋。

锂电池本身的安全不能只依赖PMIC。我强烈建议电池组外面再加一块电池保护板,负责过充、过放、过流、短路保护。PMIC的管理逻辑和电池保护板的分工不一样,PMIC负责充电流程控制,保护板负责极端情况下的最后一道安全防线。调试阶段我用的都是带保护板的电池组,同时给输入电源加了限流,最大限流设为1A。这样即使PMIC配置写错,也不至于把电池充炸。

4. 软件侧骨架:从I2C读写到完整电源状态机

4.1 I2C 底层:先把读写函数写稳

PCA9422 的寄存器读写是这套方案的底盘,我直接使用 PIC18F45K80 的硬件 MSSP 模块。初始化代码我放在系统上电最前面:

#define _XTAL_FREQ 16000000UL void I2C_Init(unsigned long busClock) { SSPCON1 = 0x28; // 使能I2C,主模式 SSPCON2 = 0x00; SSPADD = (unsigned char)((_XTAL_FREQ / (4 * busClock)) - 1); SSPSTAT = 0x80; // 关闭SMBus,标准I2C TRISCbits.TRISC3 = 1; // SCL TRISCbits.TRISC4 = 1; // SDA }

读写寄存器的函数是基础工具,所有业务逻辑都建立在这两个函数上。值得注意的是一次写操作要包含:起始信号、写入器件地址和写标志、写入寄存器地址、写入数据、停止信号。

void PCA9422_WriteReg(unsigned char regAddr, unsigned char data) { I2C_Start(); I2C_Write(0x10); // 7位地址0x08,左移一位加写标志,实际以手册为准 I2C_Write(regAddr); I2C_Write(data); I2C_Stop(); } unsigned char PCA9422_ReadReg(unsigned char regAddr) { unsigned char data; I2C_Start(); I2C_Write(0x10); I2C_Write(regAddr); I2C_ReStart(); I2C_Write(0x11); // 读标志 data = I2C_Read(0); // 最后一个字节回NACK I2C_Stop(); return data; }

I2C 会有总线错误、仲裁失败的场景。实际项目里我在每个函数内部加了重试机制,连续失败三次之后置一个故障标志。初始化阶段I2C通不过,就直接让设备进入掉电保护状态,不往下走。

4.2 开机初始化:把PMIC配置成我们要的样子

PIC18F45K80 上电后首先要做的是等待PCA9422稳定,然后通过I2C完成初始配置。我按下面顺序配置:

  • 配置充电电流和充饱电压;
  • 配置各路输出电压;
  • 配置各路的使能位和限流保护阈值;
  • 写回INTB中断掩码寄存器,只开启需要上报的事件;
  • 使能整机输出。

一个最简单的初始化流程大致如下:

void PMIC_Init(void) { I2C_Init(100000); PCA9422_WriteReg(0x01, 0x1F); // 配置充电电流相关位域 PCA9422_WriteReg(0x02, 0x2C); // 配置充饱电压相关位域 PCA9422_WriteReg(0x10, 0x10); // 配置主Buck输出 PCA9422_WriteReg(0x11, 0x0A); // 配置辅助Buck输出 PCA9422_WriteReg(0x12, 0x1E); // 配置LDO输出 PCA9422_WriteReg(0x20, 0x80); // 使能输出 }

每个寄存器具体每一位的含义,一定要对照官方数据手册核对。不同批次的PMIC可能有个别寄存器的默认值不一样,我把初始化后的寄存器再读回来跟期望值比较,不一致就报"PMIC配置失败"。

这套做法的好处是,将来换电池或者改充电参数,只需要改寄存器值,不用动硬件和PCB。我们工程团队后来调整过一次充电恒流值,就是从0.5A改成0.8A,我只是改了一行代码,半天就完成整机验证。

4.3 主循环状态机:正常、充电、低电量、故障

电源管理的核心逻辑我写成状态机,PIC18F45K80 主循环每隔一段时间执行一次。状态定义如下:

typedef enum { SM_POWER_ON_INIT, SM_NORMAL_RUN, SM_CHARGING, SM_BATTERY_LOW, SM_FAULT_HANDLE } PowerState;

各状态的转换逻辑我这样设计:

  • 系统上电搞完配置后进入 SM_NORMAL_RUN。该状态下如果读到适配器在位且电池没满,切到 SM_CHARGING。
  • SM_CHARGING 状态下如果充电完成,则回到 SM_NORMAL_RUN。
  • 不管在哪个状态,只要电池电压低于欠压阈值,立刻进入 SM_BATTERY_LOW,降低外设功耗,所有非必要输出关闭。
  • 如果 PMIC 上报过温、过流、短路等故障,直接切到 SM_FAULT_HANDLE,记录事件并关机等待人工干预。

电池电压采集我用PIC18F45K80的12位ADC完成,采样脚直接连到电池正极经过分压电阻后的节点。ADC采样的代码要注意参考电压和分压比例,我习惯同时采一个基准电压通道来修正偏差。

unsigned int ADC_ReadChannel(unsigned char channel) { ADCON0 = 0x00; ADCON1 = 0x02; // 参考电压选择,根据实际电路配置 ADCON0 = (channel << 2) | 0x01; __delay_us(20); GO_nDONE = 1; while (GO_nDONE); return ((unsigned int)ADRESH << 8) | ADRESL; }

中断处理方面,PCA9422 的 INTB 触发 RB0 中断后,我在中断服务程序里只做一件事:把全局标志位置1,然后在主循环里通过I2C读取具体的状态寄存器并执行应对逻辑,绝不在中断服务程序里做I2C通信。I2C通信带延时,在中断里做容易拖垮整个系统的实时性。

5. 调试实录:五个值得记录的经验

5.1 充电电流总比设定值小,问题出在采样电阻

第一版样机调试时,我把充电电流设成500mA,实测却只有大约170mA。一开始以为PMIC寄存器配置错了,反复读寄存器,发现值都对。后来测采样电阻两端电压,发现电压比预期超出很多。查下来才发现,原理图里采样电阻用的是1毫欧,实际焊接时板子上被我换成了3毫欧的备件。充电电流检测值偏大,PMIC 以为已经达到设定电流,提前进入了电压环控制。

这也提醒我,这种靠外部电阻反馈的检测链路,电阻精度直接影响系统行为。量产清单里必须写明采样电阻的精度、封装和温漂等级,而且换料必须走工程变更流程。不要小看这一颗电阻,它是充电电流、放电电流所有闭环控制的源头。

5.2 插上适配器之后系统反复重启

出现这个问题时,现象是USB一插进去,MCU就在启动、掉电、再启动之间反复循环。用示波器看系统电压,发现适配器接入的瞬间会有一个比较大的电流尖峰,把系统电压短暂拉低,MCU低压复位,而PMIC还在重新启动,于是进入循环。

排查到最后,原因是两个:一是适配器输入的储能电容偏小,插拔瞬间电压跌落严重;二是初始化代码把PMIC各路输出同时使能,启动瞬间多个大电容同时充电,浪涌电流过大。解决办法是在适配器输入端加了一个33uF的储能电容,同时软件上把各路输出的启动时间错开,先使能MCU主供电轨,延时50ms再使能其他输出轨。

如果你也遇到类似问题,可以关注PMIC是否有输出软启动配置寄存器。合理利用软启动,能显著降低热插拔瞬间的电流冲击。

5.3 INTB 中断在插拔瞬间乱跳

PCA9422 的中断引脚在适配器刚插入和拔出的几百毫秒内会出现多次抖动。我最初只在RB0的外部中断里置了一个标志位,结果主循环去读状态寄存器时,读取到的故障类型每次都不一样。

这个问题的本质是,路径切换瞬间多个事件同时发生,PMIC 的状态位变化需要时间稳定。我在硬件上给INTB引脚加了一个100毫秒左右的RC消抖,同时软件上在中断标志置位之后,延时200毫秒再读取寄存器。经过这两步处理,误判彻底消失。

建议所有使用INTB这类中断引脚的朋友,不要对它产生的每个边沿都过度响应。这类引脚的设计目的是"告诉主控有变化",具体变化是什么、是否需要处理,应该由主控通过寄存器去确认,而不是靠边沿计数。

5.4 睡眠模式电流偏高,原是限流电阻和输出没关干净

测量整机待机电流的时候,我发现即使MCU进了睡眠模式,整机电流还有接近1mA的底数。查了一圈,首先怀疑PMIC没有进入低功耗模式。后来发现,I2C 上拉电阻在系统睡眠时仍然从3.3V轨分电流,这两颗4.7kΩ电阻理论上就有大约0.7mA的电流;再加上辅助Buck输出虽然负载在睡眠时几乎不用,但PMIC还在维持开关,空载损耗也挂着。

解决办法是:睡眠之前主控通过I2C把用不到的输出轨关掉,只保留RTC和MCU供电轨;同时I2C上拉电阻改由GPIO控制供电,睡眠时切断。改完之后整机待机电流降到了50uA以下。测待机电流的正确姿势也分享一下:用万用表串联测量会因为量程切换造成压降,更推荐用精密采样电阻加差分探头测电流波形,或者用带波形记录功能的电流探针。

5.5 高温环境下充电电流自动变小,这不是故障,是策略

我的设备在40℃环境里跑温升测试时,发现充电电流从500mA慢慢掉到了250mA左右。起初以为是热保护误触发,但读温度寄存器发现芯片温度只有60℃左右,并没有触发过温保护。

后来查数据手册才明白,PMIC 内部有温控降额策略,当芯片或电池温度偏高时,会自动降低充电电流。这个功能对锂电池来说其实是保护措施,高温下大电流充电会加速电池老化,甚至引发安全问题。所以这个"异常"其实是正常行为。只要在整机设计时做好散热,或者给PMIC留出足够的热过孔,让它不要轻易进入降额状态,就不会影响量产充电时间。

如果产品对充电时间特别敏感,可以从两方面优化:一是增加局部散热铜皮和导热垫,把热量导到外壳;二是重新评估充电电流设定,不要顶着上限跑,留出降额空间。

回到整体,这套 PCA9422 和 PIC18F45K80 的组合方案已经跑完整个验证流程,量产之后电源异常发生率比之前的散件方案低了很多。最后分享一个实用习惯:量产前把PMIC所有寄存器的最终配置值做成快照存在PIC18F45K80的EEPROM里,机器出问题时,引导程序可以把当前寄存器全部抓出来跟快照比对。做完整套电源管理,这可能是最值钱的十分钟代码,因为它在现场排查时能救你一命。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询