PIC18F87J11与PCA9422电源管理设计实战
1. 为什么一个8位机项目反而需要配套PMIC
1.1 从一次供电事故说起
有段时间我在做一套便携式采集终端,主控用的就是PIC18F87J11,传感器前端、无线模块、显示屏全挤在一块四层板上。一开始图省事,整个系统直接用一颗低压差线性稳压器(LDO)从电池降压到3.3V完事,PCB面积小、物料成本低,看起来没有任何理由去碰电源管理芯片。
结果联调的时候出了个很隐蔽的问题:无线模块发射瞬间电流能拉到200mA以上,LDO在这种瞬态下压降掉得很厉害,3.3V轨出现明显的塌陷。主控每次都在无线模块发射的那几百毫秒里复位,日志里看不出任何规律,最后用示波器挂在电源轨上才看清楚。那一次之后我把整个供电方案推翻重做,换成了PCA9422和PIC18F87J11的组合,才彻底解决了这类问题。
这篇内容就围绕这个组合展开:PCA9422担任系统里所有电源轨的生成与监视,PIC18F87J11通过I2C协议做电源管理逻辑控制,包括电压切换、状态查询、异常复位。读完你会发现,独立PMIC不是高配M核项目的专利,对很多8位机系统来说,它反而是一种省心的供电架构。
1.2 独立PMIC与板上LDO方案的取舍
很多人有疑问:用LDO不也能给PIC18F87J11供电吗?为什么非要兴师动众上一颗PMIC?
先看PIC18F87J11这类的MCU本身特点:工作电压范围很宽,2.0V到3.6V都能跑,内部还有多种时钟源,功耗可以压得比较低。真正的问题从来不在主控这颗芯片上,而在于系统其他负载。采集终端里有模拟前端、无线模块、存储、显示屏,每一路对电压和纹波的要求都不一样。LDO方案很难同时满足三件事:
- 给所有负载提供不同类型的电压轨;
- 在负载瞬态变化时维持稳定的电压;
- 让系统在待机和工作两种状态之间快速切换功耗。
PCA9422这种PMIC的优势在这里就很明显:内部集成了多路DCDC转换器和LDO,各自负责不同的电压轨,DCDC负责大电流、高效率的数字部分,LDO负责纹波要求高的模拟部分。PIC18F87J11只需要通过I2C读写寄存器,就能控制各路输出的开关、电压值、转换速率,这在纯LDO方案里基本无法实现。
1.3 这个组合实际适合的三种场景
我后来复盘过,PCA9422和PIC18F87J11这个组合最适合下面三类应用:
第一类是电池供电的便携设备,待机功耗和动态调压是刚需。待机时把CPU核心乃至外设电压调低,运行时再恢复到正常值,延长电池续航效果非常直接。
第二类是负载瞬态变化剧烈的数据采集终端,比如包含无线模块、电机驱动、加热器等单元的设备。这类设备最大的问题就是瞬态压降,独立PMIC的大电流DCDC路径能扛住突发电流,稳压效果比LDO好得多。
第三类是可靠性要求较高的工业现场仪表,需要实时监视电压跌落、实现掉电预警和有序复位。PCA9422的电源状态指示引脚可以告诉MCU“电压出问题了”,PIC18F87J11据此进入安全处理流程,避免把半写状态的数据落进Flash里。
2. 系统电源架构:先画清楚"谁给谁供电"
2.1 总体电源树设计
先不急着写驱动,第一步永远是搞清楚系统里有哪几条电压轨、每条轨给谁供电、最大电流是多少。我那套采集终端最后确定的电源树是这样的:
| 电源轨 | 电压 | 来源 | 主要负载 | 最大电流 |
|---|---|---|---|---|
| VDD_DIG | 1.2V | PCA9422 DCDC1 | MCU内核及I/O | 1.0A |
| VDD_MEM | 3.3V | PCA9422 DCDC2 | Flash、传感器、数字接口 | 0.8A |
| VDD_ANA | 3.0V | PCA9422 LDO | 模拟前端、参考电压 | 150mA |
| VDD_IO | 3.3V | DCDC2经过滤波后供电 | 显示屏、电平转换 | 0.5A |
有人可能会问,为什么不让DCDC直接给模拟前端供电?因为DCDC开关噪声经过电感电容后仍有较大纹波,模拟前端对电源噪声很敏感,直接供会影响采集精度。所以模拟部分我坚持从LDO走,哪怕效率低一点,换来的是干净得多的电源。
2.2 工作模式的电压电流预算表
系统不止一种工作状态,电源设计必须把每个状态的预算都算清楚,否则就会出现“待机正常、满载崩溃”这种状况。我习惯先列一张模式预算表:
| 工作模式 | DCDC1电压 | DCDC2电压 | LDO状态 | 总电流估算 |
|---|---|---|---|---|
| 深度休眠 | 0.9V | 关闭 | 关闭 | 约3mA |
| 正常运行 | 1.2V | 3.3V | 开启 | 约450mA |
| 无线发送 | 1.2V | 3.3V | 开启 | 约700mA |
| 异常保护 | 1.0V | 3.3V | 开启 | 约100mA |
这张表不是拍脑袋写的,每个数字背后都是实际测量。我建议读者在硬件阶段就给每个电源轨留电流采样电阻或者至少留出测试点,否则后期想测量各路电流根根麻烦。
2.3 上电时序为什么要单独设计
真正让我吃教训的是上电时序。第一次流片回来,我把MCU、Flash、无线模块都挂在同一路3.3V上,上电时三个器件同时被供电,结果偶尔出现Flash初始化失败。分析下来是MCU比Flash先完成复位,在Flash还没就绪时就发起了读操作。
用PCA9422之后,这种问题可以用它内部的电源控制逻辑解决。我给DCDC2(3.3V轨)设置了较长的软启动时间,同时用MCU的I/O引脚等Flash主控就绪后再释放复位,问题才彻底消失。
这里有个通用原则:多负载系统里,谁先谁后必须明确。通常的顺序是模拟基准先稳定,然后数字内核就位,最后再给外设和外设接口供电。PCA9422的DCDC多路输出天然支持这种分时上电,用寄存器就能控制每一路的启动延时。
3. PCA9422配置:寄存器图不长,但每一项都要较真
3.1 I2C基地址与配置顺序
PCA9422和主控之间走的是标准I2C,这点对PIC18F87J11特别友好,因为MSSP模块本身就支持I2C主模式。要注意的是基地址里通常包含硬件引脚电平决定的位,也就是说你在原理图阶段就要确定地址设置脚怎么接,硬件改动后软件地址也得跟着改。
我的建议是配置顺序固定成几步:先让PCA9422处于待机状态,再设置各DCDC输出电压和电流限制,接着配置LDO输出电压,最后使能各路输出。顺序反了,比如先使能负载再配电压,中间会出现一段不受控的电压爬升,极端情况下会把负载打坏。
下面是我在PIC18F87J11上实际使用的一套I2C写入函数骨架:
#define PCA9422_ADDR_W 0xA0 // 根据硬件地址码确定 uint8_t pmic_write_reg(uint8_t reg, uint8_t val) { I2C1_Start(); if (I2C1_MasterWrite( PCA9422_ADDR_W | 0 , ®, 1 ) != 0) { I2C1_Stop(); return 1; } if (I2C1_MasterWrite( PCA9422_ADDR_W | 0 , &val, 1 ) != 0) { I2C1_Stop(); return 1; } I2C1_Stop(); return 0; }3.2 动态调压与系统跑飞时的恢复逻辑
PCA9422最实用的功能之一就是动态调压,运行中通过修改寄存器让某一路DCDC的输出电压按步进变化。我在采集终端里用得很勤:传感器扫描阶段MCU跑48MHz,DCDC1输出1.2V;扫描间隔进入低功耗模式,DCDC1降到0.9V,同时关闭LDO,整板功耗能从几百mA降到几个mA。
动态调压过程中有个必须注意的细节:电压切换需要一点时间,不能连续狂写寄存器。我实测过,每步调整间隔至少留1ms以上,否则转换速率不够,输出会出现短时过冲。稳妥做法是在切换前先读回当前值,再按步进写入目标值,写完做一次回读校验。
系统跑飞也是实际会遇到的问题。I2C的时序一旦被中断干扰,寄存器可能被写进半截数据。我在代码里加了看门狗定时器,一旦发现PMIC回报的状态和预期不符,就强制复位PCA9422的配置区,重新加载默认配置。这比在主控里反复排查运行状态要可靠得多。
3.3 LDO的用途:数字内核之外的模拟轨
很多人一看到PCA9422有LDO,就习惯性地把它当作给MCU数字内核用的。实际上LDO更适合给模拟电路,它的纹波抑制特性比DCDC好得多。模拟前端、模数转换参考电压、传感器激励源,这些负载对输入电压噪声极其敏感,用DCDC直供往往会导致采集数据在频谱上出现开关频率的杂散尖刺。
我在实际项目里把LDO输出拉到3.0V,专门给模拟部分使用。DCDC给数字部分,虽然效率高,但我额外加了一级LC滤波后,再引到模拟参考电压缓冲器前面。这一点值得强调:PMIC内部的隔离做得再好,外部PCB布局上的数字电源与模拟电源也要尽量物理分隔,地平面要单点汇聚,否则仍然会耦合噪声。
4. PIC18F87J11侧的控制与监测实现
4.1 I2C主模式初始化的坑
PIC18F87J11的MSSP模块配置成I2C主模式本身不复杂,但有几个坑必须提前知道。第一是时钟频率的选择,标准模式100kHz和快速模式400kHz都能跑,但如果PCB上I2C走线较长或者上拉电阻取值偏大,强行跑400kHz会出现时钟沿变缓导致的误码。
我项目里的I2C总线长度大约有8cm,加上两个上拉电阻和滤波电容,实测跑400kHz时每1000次读操作会偶尔错一两次。后来降到250kHz,连续跑几万次都没出过错。经验是:除非确认布局非常紧凑,否则主控和PMIC之间的I2C用快速模式要三思。
下面是MSSP初始化时我常用的配置片段:
void i2c_init_master(uint8_t uc_fosc_mhz) { // 设置I2C时钟频率,以4MHz时钟、100kHz为例 SSPCON1 = 0x08; // I2C主模式 SSPCON2 = 0x00; SSPADD = (uc_fosc_mhz * 1000000UL) / (4UL * 100000UL) - 1; SSPSTAT = 0x80; // 标准模式非SMBus SSPEN = 1; }4.2 电压切换协议:从寄存器到引脚配合
动态调压不能只在I2C里写一个寄存器就完事,我习惯把整个过程封装成“切换协议”。原因是只有MCU知道当前处于什么工作模式,PMIC不知道;电压切换的前置条件,比如先把外设关掉、先把数据落盘,只能由主控来执行。
我的切换流程大致是这么走的:
- 关闭对电压敏感的外设,或者让外设进入待机模式;
- 通过I2C读取当前DCDC输出状态,确认真实电压等级;
- 按步进把目标电压写入PCA9422电压寄存器;
- 回读目标寄存器,校验写入成功;
- 等待输出电压稳定,这个时间至少按数据手册建议值预留;
- 重新开启需要高电压才能工作的外设。
这套流程写进一个函数,所有工作模式切换统一调用,就不会出现“某个模式漏了某一步”的问题。
4.3 掉电预警与复位机制
掉电预警是这次设计里我认为最有价值的机制。PCA9422的电源监视功能可以配置成当输入电压低于某个阈值时产生中断信号,这个信号直接连到PIC18F87J11的外部中断引脚。
实际使用中,我在中断服务函数里只干三件事:把当前传感器数据缓冲区的状态标记写成“无效”,把关键配置参数尽快写到EEPROM暂存区,然后停止一切非必要外设的再写入动作。等掉电恢复后,主控上电复位时先检查这个标记,决定是从暂存区恢复还是重新初始化。
这个流程比单纯靠主控内部的BOD电压检测可靠得多,因为PMIC能监视的是整个系统的输入电源,而不是MCU自己的VDD。很多设备出现数据损坏,并不是因为MCU电压不够,而是外设或者前端电路已经先乱了。
5. 实测数据与波形里暴露的问题
5.1 纹波超标的根因:底层布局而非芯片本身
第一版PCB打样回来,我用示波器测DCDC2的纹波,峰值竟然有60mV,超出了设计预期。一开始怀疑是PCA9422本身性能不行,但仔细看布局才发现,输出电容离芯片引脚太远,高频开关电流的回路太长,导致寄生电感把纹波放大了。
调整方法很朴素:把输入电容、输出电容尽可能贴近芯片引脚,开关节点下面不要铺大块地平面,反馈走线避开电感。改完再测,纹波降到20mV以内。这说明电源芯片的性能上限很多时候是外围电路和PCB布局决定的,芯片只占了设计的一半。
5.2 上电瞬间的过冲处理
另一处实测暴露的问题是上电瞬间电压过冲。DCDC1在使能瞬间,输出电压会先冲到1.4V左右再回落,这个过冲在低压数字电路上很危险。分析下来是软启动时间设置太长导致的启动补偿异常。
把软启动时间调短一些后,过冲明显下降。但也不能无脑调到最低,否则大容性负载充电时DCDC会进入电流限制。我的做法是先用100mV/格的示波器逐档观察过冲幅度,同时结合负载电容大小确定一个折中值。这个值记录下来,以后同类型项目可以直接参考。
5.3 长距离I2C通信的稳定化处理
采集终端里面板控制和主板之间用FPC排线连接,I2C信号走了10cm左右,结果读PMIC状态时经常出现随机错误。用逻辑分析仪抓波形发现,是上拉电阻值在某些边沿上不足以快速拉高。
处理方案是我后来在多个项目里都用到的:在远端增加一个额外的上拉电阻,同时把通信速率降到100kHz。虽然慢了点,但稳定性和成本都得到了保证。PMIC这类设备的寄存器操作不频繁,降速对性能影响微乎其微。
6. 硬件调试与产线验证的几项检查清单
6.1 硬件调试时务必确认的节点
以下清单是我每次拿到新板子都会过一遍的项目,配合这套电源方案尤其值得保留:
- 各路DCDC的输出电压是否和配置寄存器一致,测量点尽量选在负载端而不是PMIC引脚附近;
- 各路输出的纹波是否在设计范围内,特别是模拟LDO输出不能和DCDC输出混在一起测;
- I2C上拉电阻阻值是否合适,用示波器看SDA和SCL的低电平是否低于VIL阈值;
- 掉电预警触发时,主控中断服务函数是否能在一个合理时间窗内完成保存操作;
- 动态调压切换过程中是否有过冲记录,必要时用示波器单次捕获模式观察;
- 各工作模式下的整机功耗是否和预算表基本吻合。
6.2 几个值得继续扩展的方向
这套电源管理架构其实还能继续延伸。比如增加一个外部电流采样电阻和PIC18F87J11的ADC结合,就能实时监控系统电流;再把关键运行参数通过日志记录到Flash,后续分析整机寿命很有帮助;甚至可以把PMIC的中断输出扩展成多个事件源,在产线上做电源异常专项老化测试。
如果以后换更复杂的MCU平台,这套控制逻辑几乎可以平移过去,只是把I2C底层驱动换掉、寄存器地址按新PMIC调整而已。电源管理这种底层能力,尽早做扎实,后面整个产品的稳定性都会受益。