news 2026/10/24 5:09:35

从PMIC到8位MCU:低功耗便携设备完整电源管理方案解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从PMIC到8位MCU:低功耗便携设备完整电源管理方案解析

做低功耗便携设备的开发,越往后越绕不开一个问题:怎么把电池的电管明白。我最近在一个可穿戴设备原型上,用 PCA9422 作为电源管理芯片(PMIC)负责充电和多路电源轨输出,再用 PIC18LF45K42 这颗 8 位单片机做整套系统的控制核心,从电池充电、电源路径切换、多路稳压输出一路管到动态调压和故障保护,算是把“完整电源管理”这件事从头到尾走了一遍。这篇文章把从方案选型、硬件设计、固件实现到调试排障的完整过程整理出来,适合正在评估 PCA9422 这套 PMIC 组合、或者打算用低功耗 8 位机做电源管理的朋友做个参考。

1. 项目概述:这套电源管理方案到底在解决什么问题

1.1 拆解“完整电源管理”的需求

很多人一听到电源管理,第一反应就是“电池充电”,其实真正落到产品上,维度要多得多。以我这次做的可穿戴设备原型为例,掰开来看,至少包含六个子系统:电池充电与路径管理、多路电源轨输出、上电时序控制、运行状态监测、故障保护、以及和主控 MCU 的低功耗联动。

电池充电是最基础的一层,负责将适配器或充电底座输入的电压转换到电池充电所需的恒流/恒压曲线,还要处理预充、充满检测、充电温度保护。路径管理则要解决“适配器插入时系统由谁供电”的问题,好的 PMIC 会做成适配器优先供电,同时给电池充电,拔掉适配器后无缝切到电池供电。

多路电源轨输出是因为一个系统里不同模块的电压需求不一样:主控和传感器通常要 3.3V,无线模块可能需要 1.8V 或 3.0V,模拟前端要干净的 3.0V 甚至 2.5V。用独立的 LDO 和 DC-DC 当然可以搭出来,但板子面积和静态功耗都会失控。这时候集成多路输出的 PMIC 就很有必要了。

状态监测和故障保护则是容易被忽略的部分:电池电压是多少、当前充电电流多大、系统温度是否过高、输出是否过流,这些数据在做低功耗策略和保护逻辑时都得有来源。传统的做法是主控 MCU 用 ADC 去采电压电流,再配合分立器件做比较器保护,电路复杂度和校准工作量都不小,而一颗带 I2C 状态寄存器和中断输出的 PMIC 能把这些问题一次收拢。

最后是低功耗联动。便携设备的主控会频繁进入睡眠和唤醒,睡眠时系统电流降到了微安级别,此时 PMIC 自身能不能进入低功耗模式、不用的电源轨能不能关掉、电源轨在轻负载下是不是自动切换到了省电模式,都会直接决定整机待机功耗。

1.2 为什么是 PCA9422 负责功率通路,PIC18LF45K42 负责控制

方案里最核心的选型逻辑就是把“功率通路”和“控制逻辑”分开。PCA9422 是一颗高度集成的单节锂电池 PMIC,内部集成了充电管理、电源路径选择、两路 DC-DC 降压输出和 LDO,配合 I2C 接口可以做非常精细的配置。它解决的是功率层面的问题:输入电压转换、充电电流控制、各路电源轨的稳定性,这些如果用分立器件搭,光电感、MOS 管、二极管、采样电阻就能占掉半个板子。

控制层面交给 PIC18LF45K42 则有几个现实考虑。第一是这颗芯片本身就定位低功耗应用,工作电压可以做到 1.8V 到 3.6V,睡眠电流非常低,非常适合电池设备。第二是它自带 MSSP 串行外设,可以直接做主模式 I2C 和 PMIC 通信,不需要软件模拟 I2C,这在可靠性上有质的差别。第三点是它内部有丰富的可配置逻辑单元(CLC)之类的“内核独立外设”,可以做一些简单的信号处理而不占用 CPU,这在需要时刻响应异常状态的电源管理场景里是加分的。

在项目早期我也考虑过两个方向:一个是把电源管理功能直接塞进系统主控,少一颗芯片;另一个是用更高端的带 PMIC 的无线 SoC。前者的问题是系统主控经常要跑无线协议栈和业务逻辑,电源管理的实时响应会被抢占,尤其是充电异常或者过温保护这类需要快速处理的事件,一旦被调度延迟后果比较严重。后者的问题是成本和灵活性,SoC 内集成的 PMIC 配置项通常固定,未来换电池容量或者改充电电流都要重新选型,而独立的 PCA9422 加 MCU 组合随时可以通过 I2C 改参数,至少不用改硬件。

1.3 这颗 8 位单片机凭什么能胜任电源管理主控

提到 8 位单片机,很多人会觉得性能弱,但电源管理这个场景恰恰不是单纯比拼算力。它更需要的是确定性和丰富的外设资源。PIC18LF45K42 在 64MHz 主频下执行一条指令只需要一个周期,处理 I2C 中断、读取状态寄存器、切换电源轨使能这些操作,实际上只需要几百微秒的时间预算,性能完全够用。

真正让我觉得它适合这个方案的是几个细节。第一,它的 I2C 模块支持 7 位地址掩码匹配,可以在硬件层面过滤 PMIC 的广播消息或者多设备寻址,减少 CPU 打断;第二,它的中断控制器支持多种优先级,可以把 PMIC 的 INTB 引脚作为一个高优先级外部中断源,保证故障事件第一时间被响应;第三,它有足够多的定时器通道,可以建立一个低功耗的周期性状态巡检机制,比如每 100ms 唤醒一次读取一次电池电压,而不需要外部 RTC。

从软件维护角度讲,用 8 位机做电源管理还有一个隐性优势:代码逻辑简单清晰,状态机一目了然,不会有操作系统的调度干扰,出了问题翻代码非常快。这在产品调试阶段简直太重要了,我后面在排查充电问题和低功耗问题的时候,正是靠着这种确定性把根因一个个挖出来的。

2. 硬件设计:电源树搭建、关键电路与上电时序

2.1 PCA9422 外围电路:充电、降压、温度检测

PCA9422 的外围电路设计是整个硬件设计的基础。它的输入侧有两个关键引脚,一个接适配器的 VBUS,一个接电池的 VBAT。VBUS 输入侧我加了 10uF 陶瓷电容作为输入去耦,位置尽量靠近 VBUS 引脚。有人会问为什么不放电解电容,因为 PMIC 的输入纹波主要是高频开关噪声,陶瓷电容的低 ESR 特性更适合吸收这种纹波,而且 X5R/X7R 材质在 DC 偏压下容值变化可以接受。

电池侧的 VBAT 也放了 10uF 电容,同时并联了一个 100nF 高频退耦电容。电池线如果比较长,还应该在电池连接器附近再放一个 100uF 钽电容来应对瞬间大电流抽载,这是我在调试无线模块发射瞬间电压跌落时总结出来的,最初板子上没放,一发射就掉电复位,后来补上就好了。

PCA9422 的两路 DC-DC 降压输出需要外配电感和输出电容。电感选型我用了 2.2uH 的功率电感,饱和电流按最大输出电流的 1.5 倍以上选。电感值太小会导致纹波电流大,输出纹波不好看;太大则暂态响应变慢,负载突变时电压跌落明显。输出电容选择上,每路输出我放了两颗 22uF 的 X7R 陶瓷电容,并了一颗 1uF 高频电容,实际纹波大约能控制在 20mV 以内。

充电回路的电流路径不需要外部采样电阻,PCA9422 的充电电流是通过 I2C 寄存器配置的,这一点对缩小板子面积帮助很大。但要注意它的充电电流精度毕竟有限,设计电池容量和充电电流时不要卡着上限选,比如电池容量 1000mAh,充电电流设 500mA 就已经很稳妥。温度检测方面,我在电池包附近接了一个 10k 的 NTC,接到 PMIC 的 TS 引脚,配合寄存器配置,可以在电池过温时自动降低充电电流或者停止充电。

2.2 给 PIC18LF45K42 分配电源轨与信号连接

PIC18LF45K42 的供电从 PCA9422 的一路 Buck 输出取 3.3V,这个电压范围完全在它的工作范围内。在它的 VDD 和 VSS 之间,我放了 4.7uF 和 100nF 两颗去耦电容,位置紧贴电源引脚。很多低功耗设备最终待机电流降不下去,问题就出在 MCU 的去耦电容漏电以及 VDD 引脚没有按数据手册要求接全,所以我这里严格要求两颗电容都有,且地回路尽量短。

PCA9422 和 PIC18LF45K42 之间的信号连接,最核心的是三条线:I2C 的 SDA 和 SCL,以及 PMIC 的中断输出 INTB。I2C 是开漏结构,必须外加上拉电阻。我用了 2.2k 上拉到 3.3V,这是因为 I2C 总线工作在 400kbps 时,上拉电阻太大会导致上升沿过缓,影响通信稳定性;而如果上拉电阻太小,总线低电平的驱动能力又可能不够。实际测试下来 2.2k 在 3.3V 系统、总线电容不大时是很好的起点,如果总线挂了多个设备导致电容变大,可以考虑降到 1.5k 甚至 1k,但最好用示波器看波形再调。

INTB 接的是 PIC18LF45K42 的 RA2 引脚,配置为输入并启用内部弱上拉。虽然 PMIC 的 INTB 本身是开漏输出,内部可能已经带上拉,我仍然在板级加了一个 47k 的上拉到 VDD,保证噪声环境下不会误触发。INTB 是低有效,也就是说 PMIC 检测到充电状态变化、故障事件时,会把这个引脚拉低来通知 MCU。这个信号我用的是下降沿触发的外部中断,响应速度比轮询高一个量级。

除了这三条线,我还从 PIC 的 GPIO 引了几根控制线。一根控制 LDO 输出的使能端,用于在睡眠时彻底关断模拟部分的供电;一根控制无线模块的电源,通过 PMIC 的负载开关或 LDO 使能实现模块级断电;另外预留了一个 ADC 通道监测电池电压分压点,虽然 PMIC 内部也有电压监测,但用独立 ADC 通道做交叉验证会更稳妥。

2.3 上电时序与复位信号设计

电源系统设计里,上电时序经常被低估。多个电源轨同时上电,如果其中一个模块在另一个模块没有稳定时提前启动,可能造成 IO 冲突、总线锁死甚至芯片损坏。PCA9422 提供多个电源轨的独立使能控制,这就让时序设计变得很灵活。

我采用的时序逻辑是:适配器或电池接入后,PCA9422 内部基准建立,随后最先使能的 Buck 输出 3.3V 给整个数字系统,这路电只要处于有效状态,PIC18LF45K42 就开始正常复位执行代码。PIC 初始化完成后,由软件通过 I2C 依次使能第二路 Buck 和 LDO,给传感器和无线模块供电。这样做的原因很简单:先保证大脑(MCU)活过来,才有能力去按顺序唤醒身体的各个部分。

如果 PMIC 支持通过 GPIO 或者寄存器配置上电延迟,也可以把所有电源轨的使能都做成硬件控制,但那样灵活度不够。我最终选择了软启动的方式,在 PIC 的固件里做一个简单的序列数组,依次执行“配置电压、使能输出、延时、校验反馈”,这样每一路电源轨从启动到确认稳定都有据可查,调试时也容易定位是哪一步出了问题。

复位信号方面,PIC18LF45K42 的 MCLR 引脚接了标准的 10k 上拉加 100nF 电容到地。需要注意的是,如果使用 PMIC 提供的复位输出信号来复位 MCU,要确认复位信号的极性、延迟时间以及电压阈值是否和 MCU 匹配,尤其要留意复位释放时间不能和电源轨建立时间冲突,否则 MCU 可能在 VDD 没有完全稳定的情况下就开始运行,出现莫名其妙的不稳定问题。

3. 固件实现:I2C 通信、初始化流程、动态调压与低功耗

3.1 打通 I2C:配置 PIC18LF45K42 的 MSSP 主模式

固件实现的第一步,是把 PIC18LF45K42 的 MSSP 模块配置成 I2C 主模式。MSSP 这个外设可以工作在 SPI 模式也可以工作在 I2C 模式,它的 I2C 主模式配置主要涉及工作模式设置、时钟速率设置、以及引脚复用功能。

以下是用 MPLAB X IDE + XC8 编译器的初始化代码,由于不同型号的寄存器位名称略有差异,实际使用时建议对照具体数据手册核对寄存器定义:

// I2C 主模式初始化,时钟 400kHz void i2c_init(void) { // 设置引脚复用:SCL1 和 SDA1 TRISAbits.TRISA4 = 1; // SCL1 输入方向 TRISAbits.TRISA5 = 1; // SDA1 输入方向 ANSELAbits.ANSA4 = 0; // 关闭模拟功能 ANSELAbits.ANSA5 = 0; // 配置 MSSP1 为主模式,FOSC/4,启用 I2C SSP1CON1 = 0b10001000; // SSPEN=1, SSPM=1000 主模式 // 设置 400kHz 波特率:BRG = FOSC/(4*FSCK) - 1 SSP1ADD = (unsigned char)((64000000UL / (4 * 400000UL)) - 1); // 如果使用 SMBus 特性,可以设置 INLVL 等寄存器 }

很多人第一次配置 I2C 会忽略引脚模拟功能的关闭。PIC18 系列很多引脚默认是模拟输入模式,如果不把 ANSEL 对应的位置 0,引脚的数字输入缓冲器是不工作的,I2C 通信必然失败。这个坑在项目初期几乎必踩,我在调试时一度以为是 PMIC 没焊好,查了半天才发现是引脚模拟功能没关。

波特率寄存器的计算比较直接:I2C 时钟频率由系统时钟经分频后产生,计算公式是FSCK = FOSC / (4 * (SSP1ADD + 1)),所以反过来就是SSP1ADD = FOSC / (4 * FSCK) - 1。我用的系统时钟是 64MHz,目标频率 400kHz,算出来加上取整就是 39。实际测试中,这个配置下的 I2C 时序用示波器看是标准的 400kHz Wave,没有任何问题。

写寄存器操作函数时,我习惯把“发送起始、逐字节发送、检查 ACK、发送停止”封装成底层原语,再在上层封装写寄存器、读寄存器这样带地址和寄存器偏移的接口。ACK 检查非常关键,每次发送字节后都要确认从设备是否返回了应答位,否则通信会错位,后续所有操作全部乱掉。

// 向 PMIC 寄存器写入一个字节 // addr:7 位器件地址;reg:寄存器偏移;val:要写入的值 bool i2c_write_reg(uint8_t addr, uint8_t reg, uint8_t val) { uint8_t retry = 0; while (retry < 3) { // 发送起始 SSP1CON2bits.SEN = 1; while (SSP1CON2bits.SEN); if (SSP1STATbits.SSP1IF == 1) break; // 总线冲突检查 // 发送设备地址 + 写位 PIR1bits.SSP1IF = 0; SSP1BUF = (addr << 1) & 0xFE; while (!PIR1bits.SSP1IF); if (SSP1CON2bits.ACKSTAT) { // 无 ACK,发送停止并重试 SSP1CON2bits.PEN = 1; while (SSP1CON2bits.PEN); retry++; continue; } // 发送寄存器地址 ... // 发送数据 ... // 发送停止 SSP1CON2bits.PEN = 1; while (SSP1CON2bits.PEN); return true; } return false; }

这段代码里我加了重试机制,最多重试 3 次。电源系统里引入重试是因为 PMIC 在内部进行转换或者充电电流切换时,偶尔 NAK 是正常的,硬件上重试一次就能成功。但这个重试次数也不能太多,否则在初始化阶段会拖慢整个上电流程。实际项目里,重试 3 次加上每 100ms 的巡检机制,没有对系统产生任何可见的延迟。

3.2 PMIC 初始化序列:从读 ID 到使能电源轨

PCA9422 上电后并不会自动按你想要的电压和电流输出,它先从默认寄存器值启动,然后等待主控通过 I2C 来配置。所以 PIC 侧的上电初始化程序里,PMIC 配置是重头戏。我的初始化序列大致是:读器件 ID 确认通信正常、配置充电电压和电流、配置两路 Buck 输出电压、使能对应电源轨、配置中断使能。

读器件 ID 这一步不是为了耍帅,而是确认 I2C 总线上挂的确实是目标 PMIC,而且通信链路是通的。试过板子焊错芯片的情况,虽然引脚兼容但寄存器行为完全不同,读 ID 能第一时间发现问题。初始化代码示意如下:

void pmic_init(void) { uint8_t id = 0; // 读取 PMIC ID 寄存器,确认总线通信 i2c_read_reg(PCA9422_ADDR, PMIC_REG_ID, &id); if (id != PMIC_EXPECTED_ID) { // 处理异常:可能是地址错误、总线错误或芯片不对 while (1); } // 配置充电电压:4.2V 浮充 i2c_write_reg(PCA9422_ADDR, PMIC_REG_CHG_VREG, 0x1B); // 配置充电电流:500mA i2c_write_reg(PCA9422_ADDR, PMIC_REG_CHG_ICTRL, 0x32); // 配置 Buck1 输出 3.3V i2c_write_reg(PCA9422_ADDR, PMIC_REG_BUCK1_VOUT, 0x30); // 配置 Buck2 输出 1.8V i2c_write_reg(PCA9422_ADDR, PMIC_REG_BUCK2_VOUT, 0x18); // 使能 Buck1、Buck2、LDO i2c_write_reg(PCA9422_ADDR, PMIC_REG_ENABLE, 0x07); // 配置中断屏蔽,仅使能充电完成、充电故障、电池欠压、过温 i2c_write_reg(PCA9422_ADDR, PMIC_REG_INT_MASK, 0x0E); }

上面的寄存器地址和值只是示意,不同的 PMIC 版本会不一样,拿到芯片后的第一件事就是对照数据手册把寄存器表吃透,尤其是那些带保留位的寄存器,每个字节的每一位都要确认清楚。初始化顺序也很重要。先配置电压再使能输出,是为了避免使能瞬间输出一个不正确的电压;先配置中断屏蔽再使能中断,是为了防止在学校参数的过程中 PMIC 产生一堆没有意义的故障中断,把 MCU 的现场打断得乱七八糟。

实现中我强烈建议加一步“写入后回读校验”。I2C 写操作只会保证总线层面字节传输成功,不能保证 PMIC 内部真的接受了这个值。回读校验每个关键寄存器,虽然多花几十微秒,但能第一时间发现 PMIC 进入保护状态、或者因为某种原因寄存器被复位的问题。我在实际调试中遇到过一次 PMIC 意外进入安全模式,就是靠回读校验发现的。

3.3 动态电压调节与 MCU 睡眠联动

动态电压调节(DVS)是这套方案中真正体现“完整电源管理”价值的地方。PCA9422 的电源轨电压可以通过 I2C 在运行中直接修改,这让系统可以在不同负载状态下动态调整电压,实现性能和功耗的平衡。

我的实现思路是这样的:当系统处于正常运行状态,无线模块要发射时,Buck2 保持 1.8V 以保证射频性能;当无线模块进入接收状态或者索性关闭时,把 Buck2 降到 1.5V,减少数字电路的动态功耗。对于 Buck1 带动的主控也一样,在系统进入轻负载时把电压从 3.3V 降到 3.0V,只要主控和传感器能在 3.0V 下工作就没有问题。切换时用 200us 的延时,分批修改寄存器,确保 PMIC 的内部环路有时间完成过渡。

void pmic_set_buck1_voltage(uint8_t mv) { uint8_t reg_value = (uint8_t)((mv - 600) / 25); // 假设步进 25mV i2c_write_reg(PCA9422_ADDR, PMIC_REG_BUCK1_VOUT, reg_value); delay_us(200); // 等待内部环路稳定 }

动态调压有个必须注意的细节:修改输出电压时会瞬间在输出电容上产生充电或者放电电流,如果负载电流很大,电压跌落或者过冲会比较明显。我实测过,从 3.3V 降到 3.0V 的过程大约有 40mV 的过冲,持续时间不到 200us,对大多数数字电路来说完全没问题,但如果后端接了比较敏感的模拟器件,最好在切换电压前先切换到 LDO 供电,或者降低切换步进。

低功耗联动则是把 MCU 睡眠策略和 PMIC 的功能模式结合起来。PIC18LF45K42 在进入 Sleep 模式之前,我把 PMIC 里不需要的 LDO 关闭,将 Buck 的工作模式配置为轻载省电模式,并让 MCU 自己关掉所有不用的外设。之所以留一个定时器在中速运行,是为了能周期性唤醒巡检电池状态,这个定时器的功耗大概 2uA 左右,对于一个电池容量 1000mAh 的设备来说可以忽略不计。

进睡眠前还有一个容易忽略的细节,就是 I2C 总线的状态。如果 MCU 在 I2C 通信进行到一半时直接 Sleep,总线可能被拉死,PMIC 也会失去响应。我的做法是在进睡眠前做完所有 PMIC 配置,然后把 I2C 模块关闭,将 SDA 和 SCL 引脚配置成高电平输出,再进入睡眠。这样总线处于确定空闲状态,等醒来后重新初始化 I2C,再继续和 PMIC 通信,整套流程非常稳定。

3.4 中断与状态轮询:把故障信息变成可处理的事件

PCA9422 的 INTB 引脚是低有效的中断输出,PMIC 内部的电量状态、充电状态、故障事件都会通过这个引脚通知 MCU。我在 PIC 侧把这个引脚配置成高优先级外部中断,这样 PMIC 一拉低,CPU 就能立刻响应,不需要轮询消耗 CPU 资源。

中断服务程序里第一步不是直接读寄存器,而是先清除中断标志,避免在读取过程中重复触发。然后读取 PMIC 的中断状态寄存器,判断是哪个事件触发了中断。这一步相当于把“有人敲门”变成“知道谁在敲门”。读取之后,我必须分类处理:对于充电完成、电池充满这类状态事件,记录状态并更新系统标志;对于充电故障、过温、欠压这类严重事件,则进入对应的保护流程,比如关断无线模块、降低充电电流、或者要求系统进入低功耗模式。

void __interrupt(high_priority) pmic_isr(void) { if (INTFLAG) { uint8_t status = 0; // 读取中断状态寄存器,同时会清除中断状态 i2c_read_reg(PCA9422_ADDR, PMIC_REG_INT_STATUS, &status); // 根据状态位执行对应动作 if (status & PMIC_FLAG_CHG_DONE) { battery_flag_full = 1; } if (status & PMIC_FLAG_CHG_FAULT) { battery_flag_charge_error = 1; // 进入故障处理流程 } if (status & PMIC_FLAG_BAT_LOW) { battery_flag_low = 1; // 降低系统功能,进入省电模式 } if (status & PMIC_FLAG_OVERTEMP) { // 关闭大功耗外设,必要时停机 } } }

单独依赖中断并不够,我还保留了一个低频率的状态轮询任务,每 100ms 通过 I2C 读取一次充电电流、电池电压和电源轨状态。这有两个目的:一是中断可能因为硬件瞬态问题而丢失,轮询可以兜底;二是有些状态量比如电池电压是连续变化的,中断只在阈值跳变时触发,而轮询能拿到连续的趋势数据,为低功耗策略提供决策依据。

中断处理这里有一个非常重要的经验:PMIC 的中断状态寄存器通常分为“状态锁存寄存器”和“实时状态寄存器”。锁存寄存器只要有事件发生就会被锁住,直到主控读取后才清除;实时寄存器则反映当前状态。如果只读锁存寄存器却不理解清除时序,可能读到的都是旧状态,导致误判。我在调试中把这两类寄存器都加了回读,否则很容易出现 PMIC 反复报同一个故障但实际上已经恢复的情况。

4. 调试实录:常见问题、排查方法与关键经验

4.1 I2C 通信不稳定的几个源头

I2C 通信不稳定是这套方案里最容易被归因于“芯片坏了”的问题,实际上绝大多数都是硬件或者初始化配置的问题。我排过的案例中,最常见的就是引脚模拟功能未关闭,这个问题前置提到过,这里再强调一次:PIC18 的引脚上电默认可能是模拟模式,必须将对应引脚的 ANSEL 位清零才能作为数字 IO 使用。

其次是上拉电阻。I2C 是开漏结构,没有上拉电阻就不会有高电平,总线拉死或者波形不完整都是这个原因。上拉电阻的选择要看总线速率和总线电容,400kbps 下 2.2k 到 4.7k 是比较合理的区间,总线挂的设备多或者走线长,要适当减小电阻。如果发现 SCL 或 SDA 的高电平没有被拉到 VDD,先检查上拉电阻有没有焊对位置,再看走线有没有和别的网络短路。

第三是时钟频率过高。有些人为了追求吞吐量把 I2C 频率配置到 1MHz,但 PCA9422 很可能只支持最高 400kHz 或者 1MHz,具体要查数据手册。而且 1MHz 下总线波形对上下拉和寄生电容的要求更高,一旦波形不达标就会出现偶发 NAK、数据错位。稳妥起见,电源管理这种低频应用跑 100k 或者 400k 就足够了,没必要追求高速。

还有一个是器件地址的 7 位和 8 位问题。PCA9422 数据手册里如果给的是 8 位地址,那在代码里写 7 位地址时要把 LSB 的读写位去掉并右移一位;如果手册给的是 7 位地址,那直接左移一位加上读写位。很多初学者第一次写 I2C 驱动时会在这里出错。我的验证方法是:拿逻辑分析仪抓一次起始后的第一个字节,和手册给的目标地址比对,大于一看便知。

4.2 充电不启动,先别急着换芯片

“插上适配器,电池电压没上升”是我调试过程中遇到最多的现象之一,很多人第一反应是 PMIC 坏了,但经过排查,绝大多数都是配置和外围条件不满足。

首先确认充电使能位有没有置 1。有些 PMIC 的充电器在上电复位后默认是关闭的,必须由主控通过 I2C 明确使能。如果不使能,即使 VBUS 供电正常,也不会有充电电流。这是配置问题,不是硬件问题。

其次要看电池电压是否在预充范围内。当电池电压低于某个阈值(比如 3.0V)时,PMIC 会进入预充电模式,充电电流只有正常充电的 1/10 左右。如果你用万用表测试只看到很小的电流,以为是异常,实际上这是芯片在保护过放的电池。此时继续等待或者加大电流只会触发保护。正确做法是让预充阶段慢慢把电池电压抬起来,等超过阈值后会自动切到恒流充电。

温度检测也可能阻止充电启动。如果电池包的 NTC 没有正确连接,或者 NTC 阻值类型和 PMIC 配置的不匹配,PMIC 会认为自己处于过温状态,直接禁止充电。这种情况在调试时表现为“电池电压正常、VBUS 正常、充电使能已打开”,但芯片就是不走充电流程。排查方法是直接量 TS 引脚的电压,和 PMIC 数据手册里的正常工作范围对比。

还有一种比较隐蔽的情况是适配器功率不足。接了一个虚标的适配器,空载电压正常,一带负载电压就跌落,PMIC 检测到 VBUS 异常会降低充电电流甚至停止充电。这种问题用万用表很难看出端倪,用示波器挂 VBUS 波形会更直观。

4.3 电源轨纹波偏大,大多是布局问题

电源轨纹波问题在原型阶段最多,因为很多人会用洞洞板或者飞线的方式验证 PMIC。一旦发现纹波偏大,不要急着调整电感参数或者输出电压,先从布局找原因。

DC-DC 降压电路的开关节点走线是最大的辐射源和噪声源。开关节点应该尽可能短,而且输出电感和开关节点之间不能绕线;输出电容的地端要尽量靠近芯片的功率地引脚。如果地回路太长,开关电流在回路上产生的压降就会转化为纹波和噪声。我见过一个案例,芯片明明选型没错、电感电容参数也合理,纹波却有 80mV,最后发现是输出电容的地和 PMIC 的功率地分开铺铜,中间走了一小段细线,改成同一块地平面后纹波直接降到 15mV 以内。

电感选型也会影响纹波表现。相同电感值下,电感饱和电流不够会引发非线性,输出纹波会明显变大。另外,电感的内阻(DCR)不能太大,否则重载时压降明显,电源轨的负载调整率会变差。测量纹波时务必用示波器的短接地弹簧或同轴电缆,直接夹地线会把空间耦合的噪声一并测进来,结果严重偏大。

对后级负载的走线设计同样重要。电源轨的远端负载如果离 PMIC 比较远,在负载突变时会产生额外的压降,这个不是纹波,但是表现出来的现象和纹波类似。解决办法是给距离远的模块单独再放一颗 10uF 的本地去耦电容,而不是一味加 PMIC 侧的输出电容。

4.4 整机待机电流降不下去的排查顺序

做便携设备,整机待机电流是硬指标,我这次的目标是 20uA 以下。调低功耗的过程其实就是“做减法”的过程,把每一路不需要的电流逐个关掉。

第一步是先看 MCU。把 PIC18LF45K42 放到睡眠模式,确认它的睡眠电流符合数据手册标称值。如果在 MCU 睡眠时整机电流还很高,把 MCU 的 VDD 电流单独量出来,如果仍然大,就检查是不是没有正确关闭所有外设,比如 ADC 没有关、比较器还在跑、或者是看门狗时钟没有停。PIC18 系列进入睡眠时,默认是除了唤醒源以外的所有外设都会停止,但前提是各外设没有单独被使能保持运行。

第二步看 PMIC 自身。PCA9422 在无负载时自身会有静态电流,数据手册会有不同模式下的标称值。如果它处于 PWM 模式而不是省电模式,内部功率管切换的损耗就会导致静态电流明显偏高。需要主动把 Buck 或 LDO 配置为轻载省电模式,牺牲一些纹波性能换待机功耗。

第三步查外设电源。传感器、无线模块这些外设如果没有通过 PMIC 的输出使能或者负载开关彻底切断供电,而是在 MCU 的 GPIO 控制下“软件关断”,就可能存在漏电通路由 VDD 经过 GPIO 内部保护二极管流到地。用“GPIO 接 PMIC 使能端”而不是直接给模块供电,可以从物理上隔离漏电路径。

第四步是排查板级漏电。去耦电容的漏电流、I2C 上拉电阻在没有通信时的空闲电流、分压电阻在电池电压监测回路上的持续耗电,这些看起来每路只有几微安,但叠加起来就非常可观。我在电池电压监测分压电路上用的电阻总阻值是 1.2M 欧姆,空闲电流不到 3uA,这样既能每 100ms 采样一次,又不至于拖累待机指标。实际调试时,可以用热成像仪找发热点,所有应该有电流的地方都会在热像图上亮起来。

最后分享一个工具技巧:测待机电流时不要用普通万用表的电流档,先用电子负载或者示波器的电流探头大致看一下波形,再用具备高分辨率的微安表确认。低功耗设备上电瞬间会有很大的浪涌电流,普通万用表可能直接烧保险丝。我习惯在电源输入线上串一个 10 欧姆采样电阻,用示波器看上面的压降来估算动态电流,等系统稳定后,再用微安表串联电池端测量静态电流。

我在实际项目中最大的体会是,用 PCA9422 搭配 PIC18LF45K42 做电源管理,最值钱的部分不是把充电和降压模块集成起来,而是让整个电源系统变得“可见、可配置、可动态调整”。硬件搭完之后,软件里每一个寄存器配置都是可控的状态,电池电压、充电电流、故障事件全部有据可查,这种确定性让后续调低功耗和优化性能都变得非常高效。如果你也在评估这套组合,我的建议是先花半天把 PMIC 数据手册的寄存器表完整过一遍,然后在最小系统上把 I2C 调通、把状态寄存器的读回验证做好,剩下的事情就会顺理成章。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/24 5:09:29

从MOG2到BackgroundMatting:运动目标检测技术路线全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:08:02

时区划分的底层逻辑:从UTC、夏令时到跨时区协作与编程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:07:44

STC芯片命名规则全解析:从丝印到选型避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:35

MATLAB航空航天工具箱R2023b核心用法:坐标系、DATCOM与卫星场景

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:31

tftpd64 实战指南:TFTP 协议原理、服务端配置与排错技巧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/24 5:05:26

分辨率真相:不是像素越多越清晰,而是全链路匹配

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华