☰
无线充电电源管理:PCA9422+PIC18F4685实战解析
2026/10/24 3:23:07 网站建设 项目流程

做带无线充电的便携设备,电源管理往往比无线协议本身更加费时。我前段时间做了一款手环类产品的电源模块,主控选了 PIC18F4685,无线充电接收与输出稳压部分选了 PCA9422,整个项目从原理图到量产测试跑完后,发现这套组合很值得单独拿出来分享。它特别适合中小团队:PCA9422 把整流、稳压、协议通信这些模拟电源的脏活累活全部收掉,PIC18F4685 只通过 I2C 去读状态、写配置、做策略,不用自己去搭充电环路,也不用处理无线充电的调制解调细节。

这篇文章我会按照“选型思路、硬件链路、I2C 固件、电源状态机、实测踩坑”这条线来讲,包含了完整代码片段和可复现的排查过程。如果你正在做类似的便携设备,或者只是想把一个带 I2C 的电源芯片接入 PIC 系列 MCU,这里的内容可以直接参考。

1. 为什么把模拟电源和高层策略拆给两颗芯片

1.1 两个芯片的分工边界

一开始我并没有直接认定 PCA9422 加 PIC18F4685 这个组合。先看需求:手环类设备体积小、电池容量低,既要有无线充电接收能力,又要在运行、休眠、关机充电几种模式下切换,整机 MCU 还要顺便管屏幕、传感器和通信。如果所有电源功能都堆在 MCU 周边自己搭,电路会非常复杂。

PCA9422 在系统里的定位是“电源前端”。它接收线圈过来的交流波形,在内部完成整流和稳压,然后输出一路可调的直流电压。这路电压不是固定的,MCU 可以通过 I2C 随时调整。它还自己处理 Qi 协议相关的通信握手、异物检测、温度监测,这些本来是需要单独控制的环节,现在我完全不需要关心。我只需要在初始化时写几个寄存器,运行中定时读状态。

PIC18F4685 在系统里的定位是“电源策略大脑”。它的 ADC 采集电池电压和系统电流,它的 GPIO 控制负载通断,它的外部中断接收 PCA9422 的输出状态变化,I2C 则负责跟 PCA9422 通信。PIC18F4685 不需要知道桥式整流器的压降是多少,也不需要理解线圈谐振频率,它只关心一件事:当前系统处在什么状态,VOUT 应该设定为多少伏。

这个分工的本质是把“模拟控制”和“数字策略”彻底分开。模拟电源工程师扣的那些环路补偿、纹波抑制、整流效率问题,被 PCA9422 封装在了芯片内部;而数字侧的逻辑复杂度,则靠 PIC18F4685 的 I2C、中断、ADC 资源来消化。两者之间只有一个接口,就是 I2C 寄存器,这给固件开发和后期调试都省了大量时间。

1.2 与另外两种常见方案对比

我在选型阶段其实画过三个方案对比,这里直接摊开说。

第一方案是最常见的“两颗专用芯片”:一颗独立的无线充电接收芯片加一颗带 I2C 的电池充电管理芯片。这个方案每个芯片的单一功能都很成熟,但问题在于两套 I2C 寄存器要分别配置,充电状态和无线接收状态是两个独立状态机,MCU 需要频繁同步它们的关系,稍不注意就会出现“无线接收已就绪但充电芯片还在等待”这种尴尬状态。

第二方案是用一颗更高端的 MCU,内部直接集成 DCDC 和充电管理。这个方向的集成度最高,但成本也高,而且很多高端 MCU 的电源部分并不针对无线充电接收场景设计,线圈输入的整流路径我仍然要外接,等于只集成了一半。

最终选择了 PCA9422 加 PIC18F4685,理由很务实。PCA9422 一颗芯片就覆盖了无线接收、稳压输出和可调电压三个核心能力,非常适合电池供电的小型产品。PIC18F4685 虽然只是 8 位 MCU,但它的 I2C 模块、12 位 ADC、外部中断、ECAN 接口这些外设在这个项目里全都派上了用场。最关键的是,这两颗芯片在软件层面只需要维护一套 I2C 通信协议,状态同步逻辑简单很多。

对比维度双专用芯片方案高集成 MCU 方案PCA9422 + PIC18F4685
模拟电路复杂度中高,两套外围中,仍需外置接收低,一颗芯片搞定接收与输出
软件工作量高,两套寄存器与状态机中,依赖厂商库低,一套 I2C 寄存器
BOM 成本中高中低
扩展能力一般取决于 MCU强,PIC18F4685 外设充足且带 CAN

2. 硬件链路设计:从线圈到电池再到整机供电

2.1 PCA9422 输出的三种应用形态

PCA9422 的 VOUT 引脚是整条电源链路的中间节点。按产品是否需要电池,可以把输出侧的电路设计成三种形态。

第一种是纯外接电源形态,不需要电池,PCA9422 的 VOUT 直接给系统负载供电。这种形态最简单,适合桌面小设备。它的问题在于一旦无线充电中断,系统立刻掉电,所以必须在软件里处理“输入掉电检测”,防止写到一半的数据丢失。

第二种是电池充电路径形态,PCA9422 的 VOUT 接到电池充电前端,由系统里的电池充电线路负责限流和恒压,PCA9422 只作为一个可调电源。手环类产品大多采用这种方案。要注意的是,PCA9422 的输出电压必须留出充电芯片工作需要的压差,比如充电芯片要求输入至少 4.3V,那么 VOUT 就不能设成 4.2V。

第三种是双电源自动切换形态,PCA9422 的 VOUT 和电池通过一个切换开关共同给系统供电。这种电路需要在 VOUT 和电池之间加隔离二极管或专用负载开关,防止电池反向灌入 PCA9422。因为这个切换逻辑涉及 MOSFET 方向、体二极管泄漏这些问题,我最终没有在量产板上使用,而是采用了第二种形态,稳定性优先。

我做选择时考虑很简单:手环开机电流峰值接近 80mA,充电时整机同时工作,如果切换逻辑有一瞬间的衔接漏洞,系统就会掉电复位。第二种形态下,负载始终挂在 PCA9422 输出和充电回路之间,路径简单,不会出现切换中断。

2.2 PIC18F4685 与 PCA9422 的接口连接

接口连接说起来非常直接,PCA9422 是一颗 I2C 从机,PIC18F4685 是主机,两边就是 SCL、SDA、中断、地线四个连接。我把引脚关系列在下面。

PIN 功能PCA9422 引脚PIC18F4685 引脚连接说明
I2C 时钟 SCLSCLRC3需上拉电阻
I2C 数据 SDASDARC4需上拉电阻
中断输出 INTINTRD0配置为输入,触发外部中断
共地GNDVSS单点接地

上拉电阻我用的是 4.7kΩ,这个值在 100kHz I2C 速率和短距离走线下表现稳定,具体踩坑过程后面会专门说。INT 引脚是开漏输出还是推挽输出,不同芯片批次可能有差异,我在原理图上加了 100kΩ 下拉电阻,防止 MCU 复位期间该引脚浮空引起误触发。

PCA9422 的 VOUT 输出端需要靠近放一组去耦电容,我放了 1uF 加 0.1uF,位置尽量贴近芯片引脚。这个电容不光是稳压需求,还关系到无线充电接收的瞬态响应。如果 VOUT 走线到负载之间有一段较长的 PCB 走线,我会在这段走线末端再补一颗 1uF 电容,实测纹波有明显改善。

2.3 电路板布局的实操经验

第一版 PCB 我踩过一个布局坑:无线充电线圈的输入走线绕了大半块板子,结果电磁干扰串到 SCL/SDA 线上,I2C 偶发通信失败。后来把线圈输入走线改成短而宽的路径,并且让 I2C 两根线尽量与线圈输入线保持垂直关系,问题基本消失。

另一个经验是 VOUT 去耦电容不要离线圈太近。第一版验证板把大电容放在线圈接收区域旁边,金属外壳涡流导致无线充电效率掉了 3% 左右。后来把电容挪到 VOUT 引脚附近、远离线圈的位置,效率才恢复正常。

走线层面还有一条容易被忽略的规则:SCL 和 SDA 属于低速数字信号,表层布线即可,但不要在它们下面铺大块完整地平面,否则走线对地电容增大,I2C 信号上升沿会被拖慢。我一般在信号层留出空隙,让两根线走在比较干净的区域。

3. 固件层核心:MSSP1 初始化与 PCA9422 寄存器配置

3.1 MSSP1 主机模式初始化细节

PIC18F4685 的 MSSP1 模块可以配置成 I2C 主机模式,对应引脚是 RC3 和 RC4。我先说初始化代码,再说几个容易写错的细节。

// PIC18F4685 主频 4MHz,I2C 速率 100kHz // SCL = RC3,SDA = RC4 void i2c1_init(void) { TRISC3 = 1; // SCL 输入 TRISC4 = 1; // SDA 输入 SSP1STAT = 0x00; // 标准速度模式 SSP1CON1 = 0x28; // I2C Master 模式 + SSPEN SSP1ADD = 9; // 4MHz / (4 * (9+1)) = 100kHz }

SSP1CON1 = 0x28这一步我最初是从旧项目里直接复制的,后来换到 4MHz 主频时忘了同步修改SSP1ADD,结果 I2C 速率变成了 44kHz,能工作但效率很低。建议每次新建工程都先算一遍:SSPADD = Fosc / (4 * FSck) - 1,主频 4MHz、目标 100kHz 时代入就是4MHz / (4 * 100kHz) - 1 = 9。

如果系统使用了 PLL 把主频提高到 48MHz,SSPADD就要改成 119。不要以为 I2C 速率越高越好,PCA9422 的手册里很多寄存器是普通寄存器,400kHz 虽然在规格内,但实际板子上如果布线质量一般,高速率很容易在长走线上翻车。我的原则是 100kHz 起步,把功能调通之后再决定要不要提速。

初始化里还有一个容易忽略的点:TRISC3和TRISC4必须配置为输入。很多人习惯把 SCL、SDA 设成输出,这在 SPI 模式下是对的,但 I2C 是开漏协议,引脚方向本来就由硬件自动切换,初始化时设成输入才能让模块正确接管引脚。

3.2 I2C 读写函数与 PCA9422 从机地址

PCA9422 的 I2C 从机地址默认值,不同丝印批次存在差异,我这里以实际项目中使用的 7 位地址 0x56 为例。7 位地址左移一位后,写地址是 0xAC,读地址是 0xAD。

#define PCA9422_ADDR_W 0xAC #define PCA9422_ADDR_R 0xAD void i2c1_start(void) { SSP1CON2bits.SEN = 1; while (SSP1CON2bits.SEN); // 等待 START 完成 } void i2c1_stop(void) { SSP1CON2bits.PEN = 1; while (SSP1CON2bits.PEN); } void i2c1_write(uint8_t data) { SSP1BUF = data; while (!PIR1bits.SSP1IF); // 等待发送完成 PIR1bits.SSP1IF = 0; } uint8_t i2c1_read(uint8_t ack) { SSP1CON2bits.RCEN = 1; while (!PIR1bits.SSP1IF); PIR1bits.SSP1IF = 0; uint8_t data = SSP1BUF; SSP1CON2bits.ACKDT = ack; SSP1CON2bits.ACKEN = 1; while (SSP1CON2bits.ACKEN); return data; }

这里有个细节值得提醒:发送完地址或数据后,一定要检查从机是否回复了 ACK。如果 PCA9422 还没有完成上电复位,或者 I2C 总线上有其他设备冲突,它不会回复 ACK。我的做法是在i2c1_write之后立刻检查 ACKSTAT,不要等到整包数据发完才发现失败。

uint8_t i2c1_write_check(uint8_t data) { SSP1BUF = data; while (!PIR1bits.SSP1IF); PIR1bits.SSP1IF = 0; if (SSP1CON2bits.ACKSTAT) { i2c1_stop(); return 1; // 从机无 ACK } return 0; }

3.3 PCA9422 关键寄存器配置顺序

PCA9422 的寄存器具体映射要按你手里的数据手册来,但配置顺序是有共性的。我的经验是先复位、再配中断、再设输出电压,最后使能输出,不要在芯片还没就绪时就写电压寄存器。

// 以实际项目的寄存器映射为例,地址请按手册核对 #define PCA9422_REG_RESET 0x00 #define PCA9422_REG_MODE 0x01 #define PCA9422_REG_VOUT 0x02 #define PCA9422_REG_INTENA 0x03 #define PCA9422_REG_STATUS 0x04 void PCA9422_init(void) { // 1. 软复位 PCA9422_write_reg(PCA9422_REG_RESET, 0x80); __delay_ms(10); // 2. 使能需要的中断 PCA9422_write_reg(PCA9422_REG_INTENA, 0x03); // 3. 设目标输出电压为 4.2V PCA9422_write_reg(PCA9422_REG_VOUT, 0x28); // 4. 切到正常接收模式并使能输出 PCA9422_write_reg(PCA9422_REG_MODE, 0x01); }

所有写寄存器操作,我都在最后加了一个读回校验。步骤很简单:写完一个寄存器,立刻读回来比对。如果读回值和写入值不一致,说明 I2C 线上存在干扰或者寄存器写入时序有问题。这个习惯帮我省了很多排查时间。

读回校验有一个注意点:有些寄存器是只读的状态寄存器,写入后读回本来就会不一样,所以校验只针对可写寄存器。我把所有可写寄存器的默认值和预期值做成一个表,在初始化阶段批量检查,产测时也复用这组代码。

3.4 电压动态调节的实际逻辑

PCA9422 的 VOUT 可以通过 I2C 在线调整,这是做动态功耗管理的基础。手环的处理器在运行、休眠、唤醒三种功耗档位下,对输入电压的需求是不同的。

void set_system_power_voltage(uint8_t vout_code) { PCA9422_write_reg(PCA9422_REG_VOUT, vout_code); // 等待 VOUT 稳定,读状态寄存器里的 VOUT_RDY 标志 uint8_t status = 0; for (uint8_t i = 0; i < 10; i++) { status = PCA9422_read_reg(PCA9422_REG_STATUS); if (status & 0x01) break; __delay_ms(2); } if ((status & 0x01) == 0) { // 电压切换超时,进入故障处理 enter_fault_state(); } }

电压切换不是瞬间完成的,PCA9422 内部需要一点时间建立新的输出。如果写完寄存器立刻去跑高负载程序,可能触发欠压复位。我的做法是每次切换后都等 VOUT_RDY 标志位,确认就绪再继续,这个细节在快速切换电压的场景下非常重要。

4. 电源管理状态机的设计与实现

4.1 状态划分与迁移条件

电源管理本质是一个状态机。我把整个系统划分成六个状态:上电初始化、无线充电中、充满保持、电池供电运行、低功耗休眠、故障保护。每个状态之间的迁移条件必须明确,不能有双条件同时成立的分支。

typedef enum { ST_BOOT = 0, ST_CHARGING, ST_CHARGED, ST_RUNNING, ST_LOWPOWER, ST_FAULT } SystemState_t;

上电初始化之后,系统要判断两件事:有没有无线充电输入,电池电压是否够用。如果 PCA9422 的状态寄存器显示线圈已经收到稳定能量,系统进入充电状态。如果没有充电输入但电池电压正常,直接进入电池供电运行状态。

充电状态里每 500ms 读一次 PCA9422 的状态寄存器,如果充电电流降到阈值以下并且持续 3 次采样,判定为充满,进入充满保持状态。充满保持状态下,PCA9422 继续维持输出,但系统负载切到低功耗模式。

一个容易漏掉的迁移条件是“充电输入断开”。手环放在充电盘上时不会突然断开,但用户可能中途拿走。如果只盯着充满标志,忽略线圈能量消失,系统可能会在充电状态下消耗电池,直到电池保护板切断。我的实现里,充电状态下如果连续两次读到线圈无能量,立即迁移到 RUNNING 状态。

4.2 低功耗模式下的处理策略

低功耗休眠状态是整个状态机里最需要打磨的部分。PIC18F4685 进入休眠前,我做了三件事:关闭 ADC、关闭 EUSART、把未用的 GPIO 全部设成输出低电平,避免引脚悬空造成的漏电。

PCA9422 在低功耗状态下也要处理。我把它切到待机模式,VOUT 输出关闭,只保留基本状态监测。这个模式下整板功耗大约能降到 30uA 左右,比运行模式低了好几个数量级。数据如下表。

工作模式整板实测电流说明
运行模式,无线充电接收中45mA手环点亮屏幕
运行模式,电池供电38mA蓝牙连接,无屏幕
低功耗休眠4uAMCU 睡,PCA9422 待机
充满待机12uAPCA9422 输出保持,负载关闭

休眠状态下,唤醒源有两个:RD0 上 PCA9422 的 INT 中断,以及 PIC18F4685 的定时唤醒。当充电盘重新放上来或者用户按键唤醒时,系统先读 PCA9422 的状态寄存器,再决定回到充电状态还是运行状态。

4.3 异常保护与错误恢复流程

异常保护不能只靠硬件,软件侧也要有一套降级策略。我先列一下处理过的异常场景。

过压保护:电池电压或 VOUT 超过安全阈值时,立即把 PCA9422 输出电压切到最低档,同时关闭负载输出。我用的是 ADC 轮询,每 100ms 采样一次,阈值设为 4.5V,迟滞 0.1V,防止在阈值附近抖动导致反复切换。

过温保护:PCA9422 内部有温度监测寄存器,MCU 每 1 秒读一次。温度超过 55 度时降低充电电流,超过 70 度时直接关闭充电,保持电池供电运行。这个策略能有效延长充电盘上连续充电时的安全性。

I2C 通信超时是最容易误判的异常。刚开始我把任何一次通信失败都当成故障,结果上电瞬间因为 PCA9422 还没准备好,系统频繁误入故障状态。后来改成连续 3 次失败且间隔 100ms 才认定故障,并加了一个恢复尝试:故障状态下每 5 秒尝试重新初始化 PCA9422,连续 3 次恢复成功就自动回充电状态。

void fault_recovery_handler(void) { for (uint8_t retry = 0; retry < 3; retry++) { PCA9422_init(); if (read_status() == STATUS_NORMAL) { system_state = ST_CHARGING; return; } __delay_ms(1000); } // 三次恢复失败,保持故障状态并通知用户 }

5. 实测踩坑:上拉电阻、超时重试与功耗调优

5.1 I2C 上拉电阻的取值问题

调试阶段最让我头疼的就是 I2C 上拉电阻。第一版验证板用了 10kΩ 上拉,总线电容在长走线下偏大,400kHz 速率下通信经常失败,表现为读取 PCA9422 状态时会时不时返回 0xFF。

排查过程比较经典。先用示波器抓 SCL 和 SDA,发现 SCL 和 SDA 的上升沿明显变缓,接近 1us 级别。这基本上就是上拉电阻太大、总线电容太大导致的。我从 10kΩ 直接换成 2.2kΩ,问题立刻消失。

但 2.2kΩ 也有副作用:当 PCA9422 输出驱动的低电平电流较大时,总线空闲电流变高,整板待机功耗增加了大概 10uA。这个数值对一般系统可能无所谓,但手环这种对功耗敏感的产品就不可接受。最终我把 I2C 速率降到 100kHz,上拉电阻改用 4.7kΩ,可靠性、待机功耗都满足要求。

注意:I2C 上拉电阻的取值不是越大越好,也不是越小越好。总线空闲时电流由它决定,信号上升沿时间也由它决定。我的经验是 100kHz 速率、总线长度小于 5cm 时,4.7kΩ 是一个不容易出错的起点。

5.2 通信超时误判与重试逻辑

上电瞬间通信超时的问题,我在初版固件里处理得不好。系统初始化时,PIC18F4685 复位比 PCA9422 快,MCU 立刻去读 PCA9422 寄存器,此时 PCA9422 还处于内部复位状态,从机不响应,MCU 报 I2C 无 ACK 错误。

一开始我以为 PCA9422 硬件有问题,换了几颗芯片都一样。后来在初始化序列前面加了 50ms 延时,让 PCA9422 先完成内部启动,之后第一次读取就稳定通过了。

这个延时不算浪费。PCA9422 上电后需要加载配置寄存器、初始化内部状态,过早写寄存器可能被它后续的复位覆盖。我实测下来,上电后 50ms 写入的电压值能保持,10ms 内写入的则可能丢失。

在初始化函数里,我增加了一个统一的wait_pcatimeout()函数,凡是系统冷启动、软复位、故障恢复三种场景都会调用,避免不同入口漏掉延时。

5.3 功耗实测数据与优化结果

功耗测试是整个系统做完之后最值得看的一张表。我在电池供电模式下,分别在未优化固件和最终固件各测了一轮。

场景未优化功耗最终功耗主要优化手段
运行,蓝牙连接,无屏幕42mA38mA动态调低 VOUT
运行,屏幕点亮49mA45mA屏幕供电开关控制
休眠待机18uA4uAPCA9422 切待机,GPIO 全输出低电平
无线充电中60mA55mA充电电流限流档位调整

第一版休眠功耗 18uA,明显偏高。逐项排查后发现,PCA9422 的 VOUT 在休眠状态下依然维持输出,这路电流直接流到负载侧被白白消耗了。把 PCA9422 切到待机模式后,休眠功耗降到 7uA。随后又把三颗未使用的 GPIO 从悬空改成输出低电平,再降了 3uA。

运行功耗方面,动态调压效果最明显。屏幕点亮时我把 VOUT 从 3.3V 提到 3.6V,因为屏幕背光在高亮度下需要更高输入才能稳定工作;屏幕关闭时降回 3.3V。这个动态调整配合 PCA9422 的 VOUT_RDY 等待机制,没有引入任何稳定性的问题。

5.4 量产阶段才暴露的 PCB 问题

开发板阶段一切正常,到了小批量试产时,出现了几块板子 I2C 完全不通、PCA9422 无法识别的现象。拿万用表量 SCL、SDA 对地电压,发现 SDA 始终是 0V,也就是说总线一直被拉低。

用放大镜看焊盘,发现试产板 PCA9422 的 SDA 焊盘和相邻的电源焊盘之间出现了锡桥,导致 SDA 被直接拉到地。这个问题在开发板手工焊接时不会出现,因为手工焊接每颗都会检查,但贴片产线的焊锡量控制不好就容易短接。

这件事给我的教训是:量产前必须在固件里加一个 I2C 设备扫描步骤,上电后读一次 PCA9422 的 ID 寄存器,如果读取失败就报错并停在自检状态。这样产线能快速挑出焊接不良的板子,而不是把问题留到整机测试阶段。

产测阶段的 I2C 扫描代码其实就是初始化后读一次 ID:

uint8_t check_pca9422_presence(void) { uint8_t id = PCA9422_read_reg(PCA9422_REG_ID); return (id == PCA9422_EXPECT_ID); }

如果生产线上有烧录器,可以直接在烧录流程后运行这段自检,节省人工目检时间。

最后分享一个我自己的经验:这套方案最值钱的地方,是把模拟电源的不确定性隔离在了 PCA9422 芯片内部,MCU 侧只需要管理 I2C 寄存器和状态策略。如果你也要做类似的产品,我建议在原理图阶段就留出 I2C 测试点,并且把“上电延时 + 重试机制 + 读回校验”这三个基础函数先写好,再开始碰具体的充电逻辑。后续如果要扩展能力,PIC18F4685 的 ECAN 模块还能用来跑整机通信或故障上报,这套电源管理的骨架基本不用动,只要在上层加策略就行。

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

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

立即咨询