1. 项目缘起与整体设计思路
搞嵌入式的人都有一个共识:低功耗设计里,电源管理是最容易被低估的一块。很多人画板子的时候随手拿个LDO就上了,结果到了量产阶段发现待机电流压不下去、电池续航对不上规格书、上电时序还老出问题。我这次做的这个项目,核心就是用PCA9422这颗电源管理芯片配合STM32F303K8这颗小钢炮MCU,搭一套完整的电源管理方案。说白了,就是让MCU能自己管自己的电——该省的时候省到极致,该干活的时候稳稳当当。
先说说为什么选这两个器件。STM32F303K8是Cortex-M4内核,64KB Flash、12KB RAM,封装小(LQFP32或者UFQFPN32),跑起来主频能到72MHz,带FPU,做电机控制、传感器融合这类活儿绰绰有余。但它有个特点:没有内置的复杂电源管理单元,只有一个简单的POR/PDR和可编程电压检测器。这意味着如果你想做多电压域、动态电压调节、精细的功耗模式切换,就得外挂一颗PMIC。PCA9422就是干这个的。
PCA9422是NXP出的一颗多通道PMIC,专门给低功耗MCU系统设计的。它集成了几个关键模块:一个降压转换器(Buck)、几个低压差线性稳压器(LDO)、一个电池充电器(支持锂离子/锂聚合物)、还有I2C接口可以动态配置输出电压和开关状态。最香的是它支持动态电压调节,MCU可以根据当前负载通过I2C实时调整核心电压,这在低功耗场景下非常关键。
整体设计思路是这样的:锂电池输入经过PCA9422的充电器和电源路径管理,一路给系统供电,另一路给电池充电。PCA9422输出多路电压:一路3.3V给STM32F303K8的IO和模拟部分,一路可调的1.8V到3.3V给MCU内核(通过内部LDO或者直接供电),还有一路给外设传感器。STM32F303K8通过I2C总线跟PCA9422通信,读取充电状态、电池电压、调整输出电压、控制各路电源的开关。MCU自己则利用STM32的低功耗模式(Sleep、Stop、Standby)配合PMIC的电源状态切换,实现整机功耗的分级管理。
这个方案解决的核心问题是:让一个没有内置PMU的MCU也能拥有接近高端SoC的电源管理能力。适合谁参考?做便携式设备、IoT节点、手持仪器、电池供电的工业传感器的朋友,尤其是那些用STM32F3系列但又想抠功耗的项目。如果你用的是STM32L4或者U5系列,那内置的电源管理已经很强了,这个方案可能有点重复,但PCA9422的充电器功能仍然有参考价值。
注意:PCA9422的I2C地址是7位的,默认0x62(7位地址),写操作时左移一位变成0xC4,读操作是0xC5。这个在STM32的HAL库配置里很容易搞错,后面会细说。
2. 核心细节解析与实操要点
2.1 PCA9422的电源架构与关键参数
PCA9422的内部结构可以分成三块:输入路径管理、充电器、输出稳压器。输入路径管理负责在适配器输入和电池之间做优先级切换,当适配器插入时,系统由适配器供电,同时给电池充电;适配器拔掉时,自动切到电池供电,切换过程不会导致系统掉电。这个功能对于需要“不断电”的设备来说太重要了,比如数据记录仪,换电池的时候不能丢数据。
充电器部分支持锂离子和锂聚合物电池,充电电流可以通过I2C配置,最大能到1A左右(具体看散热条件)。充电电压默认4.2V,也有4.35V的版本可选。充电过程分预充、恒流、恒压三个阶段,状态可以通过寄存器读取。这里有个坑:预充电流和终止电流的配置寄存器是分开的,而且单位不一样,预充电流的单位是mA,终止电流的单位是电池容量的百分比(C/10、C/20等),配置的时候要算清楚。
输出稳压器方面,PCA9422通常有一个Buck(降压)和两个LDO。Buck的输出电压范围是0.6V到3.3V,步进25mV,最大输出电流1A(取决于输入输出电压差和电感选型)。LDO的输出电压范围是0.8V到3.3V,步进25mV,最大输出电流300mA(每个通道)。这些参数在数据手册里都有表格,但实际用的时候要注意压差:LDO在输出300mA时,如果输入是3.7V(锂电池典型电压),输出3.3V,压差只有0.4V,这时候LDO的功耗是0.4V × 0.3A = 0.12W,SOT23封装的热阻大概200°C/W,温升就是24°C,还能接受。但如果输出3.3V、输入降到3.4V,压差0.1V,LDO可能就进入 dropout 区了,输出会跟着输入往下掉。所以锂电池供电时,LDO输出3.3V的方案要慎重,最好用Buck输出3.3V,LDO输出1.8V或者2.5V给低电压外设。
STM32F303K8的供电范围是2.0V到3.6V,核心电压可以通过内部LDO降到1.8V左右。但如果你想让MCU内核直接由外部PMIC供电( bypass 内部LDO),需要把VDD和VDDA接到3.3V,然后VCAP引脚接外部1.8V。不过STM32F303K8的VCAP引脚是内部LDO的输出,不能直接外部供电,所以这颗MCU的内核电压没法从外部动态调节。这一点跟STM32L4系列不一样,L4的VCORE引脚可以外部供电。所以在这个方案里,PCA9422的动态电压调节主要是给外设用的,比如传感器、射频模块,MCU本身的功耗管理还是靠STM32的低功耗模式。
2.2 I2C通信配置与寄存器操作
PCA9422的I2C接口支持标准模式(100kHz)和快速模式(400kHz),建议用400kHz,因为配置寄存器比较多,低速会拖慢启动时间。STM32F303K8的I2C外设配置要注意几点:时钟源选择、上升时间配置、模拟滤波器使能。F3系列的I2C时钟源可以选HSI(8MHz)或者SYSCLK,用HSI更稳,因为SYSCLK变化时I2C时序会跟着变。上升时间根据上拉电阻和总线电容算,一般4.7k上拉、100pF电容,上升时间大概200ns,对应I2C_TIMINGR寄存器的值需要算一下。
具体配置步骤:
- 使能I2C时钟和GPIO时钟,配置SCL和SDA为复用开漏模式,加上拉电阻(外部4.7k)。
- 配置I2C_TIMINGR寄存器。以400kHz、HSI 8MHz为例,PRESC=1(分频后4MHz),SCLDEL=4(数据建立时间),SDADEL=2(数据保持时间),SCLH=15,SCLL=13。这个值不是唯一的,只要满足时序要求就行。
- 使能I2C外设,等待总线空闲。
- 写寄存器时,先发从机地址(写),再发寄存器地址,再发数据。读寄存器时,先发从机地址(写),发寄存器地址,再发从机地址(读),然后读数据。
PCA9422的寄存器地址是8位的,但很多寄存器是16位或者有多个位域。比如充电电流配置寄存器,地址0x10,低6位是充电电流值,单位是50mA,所以写0x0A就是500mA。Buck输出电压寄存器,地址0x20,低7位是电压值,步进25mV,0x00对应0.6V,0x1E对应1.35V(0x1E=30,30×25mV=750mV,加上0.6V基准就是1.35V)。这里要注意:基准电压是0.6V,不是0V,算的时候别搞错。
实操心得:PCA9422的I2C通信偶尔会出现NACK,尤其是在电源切换的瞬间。我的处理方式是加重试机制,每次写操作失败后延时1ms重试,最多3次。另外,在MCU进入低功耗模式前,先把PCA9422配置成“保持输出”状态,避免唤醒时电源波动导致I2C通信失败。
2.3 STM32F303K8的低功耗模式与PMIC协同
STM32F303K8支持三种低功耗模式:Sleep、Stop、Standby。Sleep模式下内核停止,外设还在跑,功耗大概几mA;Stop模式下所有时钟停止,保留SRAM和寄存器内容,功耗大概几十uA;Standby模式下除了备份域,其他全关,功耗大概几uA。但F3系列的Stop模式功耗比L4系列高不少,因为它的工艺是90nm,漏电流大。实测下来,Stop模式下RTC运行、SRAM保持,功耗大概20uA到50uA,具体看温度和电压。
跟PCA9422协同的时候,策略是这样的:
- 运行模式:MCU全速跑,PCA9422的Buck输出3.3V,LDO输出1.8V给传感器。总电流取决于负载,一般几十mA。
- 空闲模式:MCU进入Sleep,外设降频,PCA9422把Buck输出电压降到3.0V(通过I2C写寄存器),LDO关掉一路。总电流降到几mA。
- 待机模式:MCU进入Stop,PCA9422把Buck输出降到2.8V,LDO全关,只保留一路给RTC或者唤醒源。总电流降到几十uA。
- 关机模式:MCU进入Standby,PCA9422进入Ship Mode(运输模式),所有输出关闭,只保留电池监测。总电流降到几uA。
这里的关键是唤醒源。STM32F303K8的Stop模式可以通过EXTI中断唤醒,比如按键、传感器中断。但PCA9422的I2C通信在Stop模式下是没法用的,因为I2C外设时钟停了。所以唤醒后第一件事是重新初始化I2C,然后读取PCA9422的状态寄存器,确认电源状态。这个流程要写进唤醒中断服务函数里,而且要注意唤醒后的时钟稳定时间,HSI启动大概几us,但I2C通信前最好延时1ms等电源稳定。
注意:STM32F303K8的Standby模式唤醒后相当于复位,程序从头开始跑。所以如果你在Standby模式下想保留一些状态,得写到备份寄存器或者Flash里。PCA9422的Ship Mode进入后,I2C接口也关了,只能靠外部按键或者适配器插入来唤醒。这个在便携设备里很常见,比如耳机盒、手环。
3. 实操过程与核心环节实现
3.1 硬件设计与物料选型
先列一下核心物料清单:
| 器件 | 型号 | 封装 | 备注 |
|---|---|---|---|
| PMIC | PCA9422 | QFN24 | 带充电器、Buck、双LDO |
| MCU | STM32F303K8 | LQFP32 | 72MHz,64KB Flash |
| 电感 | 2.2uH | 0805 | 饱和电流>1.5A,DCR<50mΩ |
| 电容 | 10uF/6.3V | 0805 | X5R或X7R,Buck输入输出 |
| 电阻 | 4.7k | 0402 | I2C上拉 |
| 电池 | 锂聚合物 | 3.7V | 容量根据需求选 |
硬件设计有几个关键点:
Buck电感选型:PCA9422的Buck开关频率是2MHz(默认),电感值推荐2.2uH。计算饱和电流:假设最大输出1A,纹波电流是输出电流的30%,即0.3A,峰值电流是1A + 0.15A = 1.15A。所以电感的饱和电流至少要1.5A,留点余量。DCR要小,不然效率上不去。我选的是0805封装的2.2uH,饱和电流2A,DCR 40mΩ,实测效率在3.7V输入、3.3V输出、500mA负载时大概92%。
输入输出电容:Buck的输入电容要能承受开关纹波电流,一般选10uF X5R,再加一个0.1uF高频电容。输出电容也是10uF,ESR要低,不然纹波大。LDO的输出电容要求比较宽松,1uF到10uF都行,但要注意稳定性,有些LDO对输出电容的ESR有要求,PCA9422的LDO是内部补偿的,所以随便选。
I2C上拉电阻:4.7k是标配,但如果总线电容大(比如走线长、挂了很多设备),可以降到2.2k。上拉电阻接到3.3V,不要接到电池电压,因为电池电压会变,I2C电平也跟着变,可能导致通信不稳定。
电池连接:PCA9422的电池引脚要加一个10uF电容,靠近芯片放置。电池温度检测(NTC)如果不用,要接一个10k电阻到地,不然充电器可能不工作。
3.2 软件初始化流程与代码实现
软件部分我分成几个模块:I2C驱动、PCA9422配置、低功耗管理、唤醒处理。先看I2C驱动的初始化:
// I2C初始化,400kHz,HSI时钟源 void I2C_Init(void) { RCC->AHBENR |= RCC_AHBENR_GPIOBEN; RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // PB6=SCL, PB7=SDA, 复用开漏 GPIOB->MODER &= ~(GPIO_MODER_MODER6 | GPIO_MODER_MODER7); GPIOB->MODER |= (GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1); GPIOB->OTYPER |= (GPIO_OTYPER_OT_6 | GPIO_OTYPER_OT_7); GPIOB->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR6 | GPIO_OSPEEDER_OSPEEDR7); GPIOB->AFR[0] |= (4 << 24) | (4 << 28); // AF4 = I2C1 // 复位I2C I2C1->CR1 |= I2C_CR1_SWRST; I2C1->CR1 &= ~I2C_CR1_SWRST; // 配置时序:400kHz,HSI 8MHz I2C1->TIMINGR = 0x00201D2B; // PRESC=0, SCLDEL=2, SDADEL=0, SCLH=29, SCLL=27 I2C1->CR1 |= I2C_CR1_PE; }这个TIMINGR的值是我实测调出来的,0x00201D2B对应400kHz,上升时间大概250ns。如果你用的上拉电阻不同,这个值要微调。调试的时候可以用示波器看SCL和SDA的波形,确保上升沿和下降沿干净。
接下来是PCA9422的配置函数:
// 写PCA9422寄存器 uint8_t PCA9422_WriteReg(uint8_t reg, uint8_t data) { uint8_t retry = 3; while (retry--) { I2C1->CR2 = (0x62 << 1) | (2 << 16) | I2C_CR2_START; while (!(I2C1->ISR & I2C_ISR_TXIS)); I2C1->TXDR = reg; while (!(I2C1->ISR & I2C_ISR_TXIS)); I2C1->TXDR = data; while (!(I2C1->ISR & I2C_ISR_STOPF)); I2C1->ICR |= I2C_ICR_STOPCF; if (!(I2C1->ISR & I2C_ISR_NACKF)) return 0; I2C1->ICR |= I2C_ICR_NACKCF; delay_ms(1); } return 1; } // 初始化PCA9422 void PCA9422_Init(void) { // 配置充电电流500mA PCA9422_WriteReg(0x10, 0x0A); // 配置Buck输出3.3V PCA9422_WriteReg(0x20, 0x6C); // (3.3-0.6)/0.025 = 108 = 0x6C // 配置LDO1输出1.8V PCA9422_WriteReg(0x30, 0x30); // (1.8-0.8)/0.025 = 40 = 0x28,这里用0x30是2.0V // 使能Buck和LDO1 PCA9422_WriteReg(0x01, 0x03); }注意Buck输出电压的计算:Vout = 0.6V + (reg_val × 25mV)。所以3.3V对应(3.3-0.6)/0.025 = 108 = 0x6C。LDO的计算是Vout = 0.8V + (reg_val × 25mV),1.8V对应(1.8-0.8)/0.025 = 40 = 0x28。我上面写0x30是2.0V,实际用的时候按需改。
低功耗管理的代码:
// 进入Stop模式 void Enter_StopMode(void) { // 配置PCA9422为低功耗状态 PCA9422_WriteReg(0x20, 0x58); // Buck降到2.8V PCA9422_WriteReg(0x01, 0x01); // 只保留Buck,关LDO // 配置STM32进入Stop模式 RCC->APB1ENR |= RCC_APB1ENR_PWREN; PWR->CR |= PWR_CR_LPDS; // 低功耗深度睡眠 PWR->CR |= PWR_CR_CWUF; PWR->CR |= PWR_CR_PDDS; // 进入Stop模式 // 配置唤醒源,比如PA0上升沿 EXTI->IMR |= EXTI_IMR_MR0; EXTI->RTSR |= EXTI_RTSR_TR0; __WFI(); // 等待中断 // 唤醒后重新初始化I2C和PCA9422 I2C_Init(); PCA9422_Init(); }这里有个细节:进入Stop模式前要把I2C外设关掉,不然Stop模式下I2C引脚可能有漏电流。我的做法是在Enter_StopMode里先I2C1->CR1 &= ~I2C_CR1_PE,唤醒后再重新使能。
3.3 功耗实测与数据分析
我搭了一个测试板,用电子负载模拟不同负载条件,测了整机功耗。测试条件:电池电压3.7V,环境温度25°C。
| 工作模式 | MCU状态 | PCA9422状态 | 实测电流 | 备注 |
|---|---|---|---|---|
| 运行 | 72MHz全速 | Buck 3.3V, LDO 1.8V | 28mA | 负载包括MCU和传感器 |
| 空闲 | Sleep | Buck 3.0V, LDO关 | 6.5mA | 外设降频 |
| 待机 | Stop | Buck 2.8V, LDO关 | 42uA | RTC运行 |
| 关机 | Standby | Ship Mode | 3.2uA | 仅电池监测 |
从数据看,Stop模式下的42uA比预期高了一点。查了一下原因:STM32F303K8的Stop模式功耗跟电压有关,3.3V时大概35uA,2.8V时降到25uA左右。另外,PCB上的漏电流也有贡献,比如I2C上拉电阻在Stop模式下如果引脚没配置好,会有持续电流。我的处理是把I2C引脚配置成模拟输入,关掉上拉,这样能省几uA。
还有一个发现:PCA9422的Buck在轻载时效率下降明显。500mA负载时效率92%,但10mA负载时效率只有75%左右。这是因为Buck进入了PFM(脉冲频率调制)模式,开关频率降低,开关损耗占比变大。如果应用大部分时间在轻载,可以考虑让Buck在轻载时切到LDO供电,或者选一颗静态电流更低的PMIC。
实操心得:测功耗的时候,万用表要选uA档,但万用表的采样率低,测到的可能是平均值。想看动态功耗,最好用示波器加电流探头,或者用专门的功耗分析仪。我一开始用万用表测Stop模式电流,读数是30uA,后来用示波器看,发现唤醒瞬间有几百uA的尖峰,平均下来才是42uA。这个尖峰是MCU唤醒时时钟启动和I2C通信造成的,没法完全消除,但可以通过优化唤醒流程缩短尖峰持续时间。
4. 常见问题与排查技巧实录
4.1 I2C通信失败排查
I2C通信失败是这个方案里最常见的问题,表现是MCU读不到PCA9422的寄存器,或者写进去没反应。排查步骤:
- 检查硬件连接:SCL和SDA有没有接反?上拉电阻有没有焊?用万用表测SCL和SDA对VCC的电阻,应该是4.7k左右。如果电阻无穷大,说明上拉没接或者虚焊。
- 检查地址:PCA9422的7位地址是0x62,写操作时左移一位是0xC4,读是0xC5。用逻辑分析仪抓波形,看第一个字节是不是0xC4。如果发的是0x62,那肯定NACK。
- 检查时序:用示波器看SCL频率是不是400kHz,上升时间是不是在300ns以内。如果上升时间太长(比如超过1us),说明上拉电阻太大或者总线电容太大,需要减小上拉电阻。
- 检查电源:PCA9422的VDD引脚有没有电压?如果电池没接或者适配器没插,PCA9422可能不工作。有些PMIC需要先给VDD供电才能通信,PCA9422的VDD可以从电池取电,但电池电压太低(比如低于2.5V)时,内部LDO可能没起来,I2C也不响应。
我遇到过一次诡异的情况:I2C能读不能写。后来发现是写寄存器的时候没有等STOPF标志,直接发了下一个START,导致总线冲突。STM32的I2C外设在发送STOP后,要等STOPF置位才能发下一个START,不然会出问题。这个在HAL库里有处理,但用寄存器操作的时候容易漏。
4.2 充电器不工作或充电电流不对
充电器不工作的表现是:插上适配器,电池电压不上升,或者充电状态寄存器一直是0。排查:
- NTC引脚:如果不用温度检测,NTC引脚要接10k电阻到地。如果悬空,充电器会认为温度异常,停止充电。
- 充电电流配置:充电电流寄存器写的是50mA的倍数,写0x0A是500mA。但实际充电电流还受输入电流限制影响,如果适配器能力不足,充电器会自动降低电流。可以读输入电流限制寄存器确认。
- 电池电压:如果电池电压低于2.5V,充电器进入预充模式,电流很小(比如50mA)。这是正常的,等电压升到2.5V以上就会切到恒流模式。
- 热问题:充电电流大时,PCA9422会发热。如果结温超过150°C,充电器会过热保护,停止充电。摸一下芯片烫不烫,如果烫手,要么降低充电电流,要么改善散热。
4.3 低功耗模式唤醒失败
唤醒失败的表现是:MCU进入Stop模式后,按按键没反应,或者唤醒后程序跑飞。排查:
- 唤醒源配置:EXTI的IMR、RTSR、FTSR要配置正确。比如PA0上升沿唤醒,IMR的bit0要置1,RTSR的bit0要置1,FTSR的bit0要清0。
- 时钟配置:Stop模式下HSI是关的,唤醒后要重新使能HSI并等待稳定。如果唤醒后直接跑I2C初始化,可能因为时钟没稳定导致通信失败。我的做法是唤醒后先延时1ms,再初始化外设。
- 电源状态:PCA9422在Stop模式下如果被配置成关断输出,MCU可能直接掉电,没法唤醒。所以进入Stop模式前,要确保PCA9422的Buck输出保持开启,只是降低电压。
- 中断优先级:如果唤醒中断的优先级太低,可能被其他中断阻塞。建议把唤醒中断设成最高优先级。
避坑技巧:调试低功耗模式时,先把所有外设关掉,只留唤醒源,测最简系统的功耗。然后逐个打开外设,看哪个外设增加了功耗。这样能快速定位问题。我一开始没关I2C,Stop模式电流多了15uA,后来把I2C引脚配置成模拟输入,电流就降下来了。
4.4 常见问题速查表
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| I2C NACK | 地址错误、上拉缺失、电源未上 | 检查地址0xC4、上拉4.7k、VDD电压 |
| 充电电流小 | 预充模式、输入限流、NTC悬空 | 检查电池电压、适配器能力、NTC接10k |
| Stop模式电流大 | 外设未关、引脚漏电、电压偏高 | 关外设、引脚设模拟输入、降电压 |
| 唤醒后跑飞 | 时钟未稳定、电源波动、中断冲突 | 延时1ms、检查PCA9422状态、调优先级 |
| Buck输出纹波大 | 电感选型不当、输出电容小 | 换2.2uH/2A电感、加10uF电容 |
| 芯片发热 | 充电电流大、LDO压差大 | 降充电电流、改用Buck供电 |
5. 方案优化与扩展思路
5.1 动态电压调节的进阶用法
前面提到STM32F303K8的内核电压没法外部调节,但外设电压可以。比如你挂了一个射频模块,它在发射时需要3.3V,接收时可以降到2.5V,休眠时断电。通过PCA9422的I2C接口,MCU可以在不同工作阶段动态调整LDO输出电压,甚至关掉某一路LDO。这个在无线传感器节点里很有用,射频模块的功耗占大头,动态调节能省不少电。
具体实现:在射频模块的驱动里加一个RF_SetPowerMode函数,根据当前模式写PCA9422的LDO寄存器。比如发射模式写0x6C(3.3V),接收模式写0x50(2.8V),休眠模式写0x00(关断)。注意写寄存器后要延时一段时间等电压稳定,一般100us到1ms,看负载电容大小。
5.2 电池电量计的实现
PCA9422没有内置库仑计,但可以通过读取电池电压和充电状态来估算电量。锂电池的放电曲线比较平,3.7V到3.4V之间对应大概60%到20%的电量,所以单纯看电压误差很大。我的做法是结合开路电压法和负载电压法:在MCU进入Sleep模式时,负载电流很小,这时候读电池电压比较准;在运行模式下,根据负载电流查表补偿。具体表格可以实测得到,用电子负载模拟不同电流,记录电压和电量的对应关系。
代码实现:
uint8_t Get_BatteryLevel(void) { uint16_t vbat = PCA9422_ReadReg(0x05); // 电池电压寄存器 uint16_t vbat_mv = vbat * 5; // 假设步进5mV uint8_t level; if (vbat_mv > 4100) level = 100; else if (vbat_mv > 3900) level = 80 + (vbat_mv - 3900) / 10; else if (vbat_mv > 3700) level = 50 + (vbat_mv - 3700) / 10; else if (vbat_mv > 3500) level = 20 + (vbat_mv - 3500) / 10; else if (vbat_mv > 3300) level = 5 + (vbat_mv - 3300) / 20; else level = 0; return level; }这个表是粗略的,实际用的时候要根据电池型号和负载特性调整。另外,充电时电压会偏高,所以充电状态下不要用电量计,直接显示充电图标就行。
5.3 多路电源的时序控制
有些外设对上下电时序有要求,比如传感器要先上模拟电再上数字电,或者射频模块要先上IO电再上核心电。PCA9422的多路输出可以通过I2C按顺序使能,实现时序控制。具体做法:在初始化函数里,先写LDO1使能,延时1ms,再写LDO2使能,再延时1ms,最后写Buck使能。关断时反过来。
这个功能在调试的时候很有用,比如某路外设上电时电流冲击大,导致电池电压瞬间跌落,MCU复位。通过分时上电,可以减小冲击。我试过在射频模块上电时,先开LDO给IO供电,再开Buck给功放供电,冲击电流从500mA降到200mA,电池电压跌落从300mV降到100mV,效果很明显。
最后再分享一个小技巧:PCA9422的寄存器配置可以存在STM32的Flash里,每次上电时从Flash读取配置,通过I2C写入PCA9422。这样如果硬件改了,只需要更新Flash里的配置表,不用重新编译代码。配置表可以用结构体数组定义,每个元素包含寄存器地址和值,初始化时遍历数组写入。这个做法在量产时特别方便,不同批次的板子可能用了不同的电池或外设,只需要改配置表就行。