多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

STM32F103RC与PCA9422构建锂电池充电与电源管理系统详解

STM32F103RC与PCA9422构建锂电池充电与电源管理系统详解 前阵子帮一个做便携式设备的朋友调电源他选了 PCA9422 加 STM32F103RC 的组合。说实话一开始我觉得有点大材小用——一块全能型 PMIC 配一颗经典的 Cortex-M3 主控怎么看都像“杀鸡用牛刀”。等真正把系统跑起来才知道这两个芯片搭在一起反而把“电源管理”这件事做得相当完整充电、多路输出、电量监测、状态上报、低功耗联动全都通过 I2C 捏在一个软件框架里调试起来简直不要太舒服。这篇文章就围绕这条主线展开讲讲用 PCA9422 和 STM32F103RC 做一套完整电源管理的实际过程。主要包括为什么这么选型、硬件上要注意哪些坑、I2C 通信和寄存器配置怎么写、实际调试中出现过的典型问题以及从样机到量产还需要补哪些测试。如果你是第一次用 PMIC或者正打算把手头的锂电池充电方案换成集成方案这篇文章应该能帮你少走不少弯路。1. 整体设计方案为什么是 PCA9422 加 STM32F103RC1.1 集成 PMIC 对比分立方案的三个决定性理由很多人做电池供电设备时第一反应是自己搭一颗单节锂电池充电管理芯片再加一颗 DC-DC、一颗 LDO用 GPIO 模拟控制流程。这样确实便宜芯片单价低原理图也好画。但你真放到量产里看问题不少。第一是面积。一套分立方案至少需要三个电源芯片、两个电感、一堆电容电阻在 PCB 上少说占掉 200 平毫米。而 PCA9422 这种单芯片方案把所有充电管理、电源通路控制、多路稳压输出、电量检测全收进去外围就只剩下电感和去耦电容板子上能省出很大一块空间。第二是可靠性。电源路径管理是个容易翻车的地方适配器插入时系统要用外部电源供电同时还要给电池充电电池没电时又要防止反灌。分立方案里这些逻辑要靠分立 MOS 管和比较器搭时序稍有不对就会打嗝甚至烧管子。PCA9422 内置了完整的路径管理逻辑谁给系统供电、多大电流给电池充电它是自己协调的MCU 只需要读状态、发指令就行。第三是灵活性。PCA9422 的充电电压、充电电流、输出轨电压、保护阈值都是通过 I2C 寄存器动态配置的。这意味着同一块硬件软件写成 4.2V 就是标准锂电池改成 4.35V 就能适配高电压电池充电电流也能根据适配器能力动态调整。分立方案想做到这种灵活性得改电阻换芯片PCB 返工没跑。1.2 主控为什么用 STM32F103RC既然 PMIC 这么强主控随便选一颗不行吗确实可以但 STM32F103RC 在这个场景里有几个实打实的优势。首先是 I2C 外设成熟稳定。F103 的 I2C 模块虽然网上吐槽不少但它本身集成了多主机仲裁、时钟同步、错误检测配合 HAL 库或标准外设库都很好用。对 PCA9422 这种低速设备来说100kHz 和 400kHz 模式都绰绰有余。其次是低功耗模式丰富。STM32F103 支持睡眠、停机和待机三种低功耗模式。停机模式下电流可以降到微安级而且能被外部中断、I2C 或定时器唤醒。做电池供电产品时这个特性太关键了平时主控睡大觉PMIC 有中断比如充电完成、电量低就唤醒主控处理一下然后接着睡。再次是引脚和资源够用。RC 后缀有 64 个引脚FLASH 达到 256KBRAM 48KB既能带一个 LCD 显示屏又能挂一堆传感器。我的那个朋友甚至把 USB 协议栈都跑在了这颗芯片上资源依旧有余量。1.3 系统的硬件层次划分整个系统可以按功能拆成三层第一层是电源输入和电池接口。USB 适配器或移动电源接进来经过 PCA9422 的输入检测模块判断是标准下行端口、充电下行端口还是专用充电端口然后决定可从适配器抽取多少电流。电池直接接 PMIC 的电池引脚不需要外部保护电路吗建议还是要一颗电池保护 ICPMIC 侧重充电管理和系统供电电池保护 IC 侧重过充过放和短路保护两者职责不同。第二层是电源输出。PCA9422 内部集成了多路降压转换器和 LDO。系统主电源从 SYS 引脚直接取主控和外设可以分别接不同的输出轨。比如说 3.3V 给数字电路1.8V 给传感器音频或显示背光走独立的一路这样各轨之间互不干扰动态负荷隔离也更彻底。第三层是控制与监测。STM32F103RC 通过 I2C 总线与 PCA9422 通信读取充电状态、电池电压、系统电流下发充电配置响应 PMIC 的中断请求。这一层就是整个软件系统的大本营后面所有调试工作都围绕它展开。2. 硬件设计的核心环节与参数计算2.1 电源通路设计的几个关键点PCA9422 的外部引脚不算复杂但布局时要注意几个功能区。充电通路方面输入 VBUS 引脚直接连 USB 或者适配器接口建议输入端加一颗 TVS 管和共模电感。TVS 防静电和浪涌共模电感防高频干扰。VBUS 到 PMIC 的走线尽量短粗因为充电电流可能到 1A 以上线细了压降大到不可接受。电池引脚 BATT 接单节锂离子电池正极走线同样要短粗。为了测电池电压准确建议在靠近电池引脚处放一颗 10uF 陶瓷电容做滤波。PMIC 通常内置低侧电流检测所以电池负极端直接接系统地即可不要试图在电池负极串采样电阻——除非你打算外接电量计否则只会徒增损耗。系统输出 SYS 引脚比较特殊。它把输入路径和电池路径的手动选择逻辑封装好了系统任何时候都由它供电。SYS 上需要一颗大容量储能电容我的习惯是至少 22uF因为当电池从充电状态切换到放电状态、输入源拔掉瞬间SYS 电压会有个小的凹坑电容太小可能触发负载复位。NTC 热敏电阻的安装也是重点。一般 10k NTC 接在 PMIC 的 TS 引脚和地之间放置位置要紧贴电池表面或靠近电池仓。充电时 PMIC 会周期性检测 TS 电阻换算成电池温度。温度低于 0 度或者高于 45 度就要停止或降额充电否则锂电容易出事。NTC 到 PMIC 的走线要远离大电流回路否则采到的温度会飘。2.2 电感选择与纹波计算PCA9422 内部的降压转换器外部只需要一个电感。有些人觉得随便找颗电感就能用结果效率上不去纹波超标甚至电感啸叫。电感量主要按输出纹波和负载瞬态的平衡需求来选。以 3.3V 输出轨为例设输入电压 5V开关频率 2MHz目标负载电流 600mA允许的电感电流纹波按负载电流的 30% 算也就是 180mA。输出电压和输入电压的关系决定了占空比 D 约为 3.3/5 0.66。电感量按公式L (Vin - Vout) × D × Ts / ΔI其中 Ts 是开关周期2MHz 对应 0.5 微秒。代入数据L (5 - 3.3) × 0.66 × 0.5e-6 / 0.18 ≈ 3.1 微亨所以选 3.3 微亨是合理起点留一点裕量也可以选 4.7 微亨代价是瞬态响应略慢。实际还要确认电感的饱和电流至少要大于 1.3 倍最大负载电流并且 DCR 尽量低。DCR 太高重载时效率损失全变成热量在密闭外壳里这就是温升隐患。电感的选型还有一个容易被忽略的坑屏蔽罩。开放式电感在小体积产品里会向周围辐射磁场如果旁边就是天线或者音频电路很容易干扰。优先选屏蔽式电感虽然贵一点但省心。2.3 PCB 布局的禁忌与要点电源电路布局说一千道一万核心就一句话高频开关电流回路的环路面积越小越好。具体到 PCA9422输入电容、开关引脚、电感这三点之间的回路要紧凑。我通常把输入 10uF 陶瓷电容放在 PMIC 的 VBUS 引脚旁边正极走线尽可能短然后从电容负极直接打过孔到地层。这个过孔不能省也别图方便把它放到电感下面去。地过孔的数量要足。PMIC 的地焊盘下面开一排列阵式过孔能显著降低寄生电感。遇到过样机正常、量产偶发复位的情况很多人排查半天结果就是地阻抗偏大导致噪声耦合。I2C 总线的 SCL 和 SDA 布线要远离 SW 开关节点和电感下方。它俩差多远算远至少隔开一整块地皮别平行走长距离。I2C 上拉电阻一般选 4.7k 或 2.2k取决于总线上挂几个设备和走线长度。400kHz 模式、走线超过 10cm我建议直接上 2.2k保证沿口够陡。2.4 STM32F103RC 外围配套电路主控这部分比较常规但有几个细节值得说一下。STM32F103RC 的 VDD 引脚组全部要接 100nF 去耦电容且每个电容要靠近对应引脚。VDDA 建议加一颗 1uF 加一颗 10nF 并联给内部模拟电路提供干净电源。如果这个项目里有电池电压采集需求但想直接用 STM32 的 ADC 而不用 PMIC 的 ADC那就需要注意 VDDA 的干净程度甚至考虑给 ADC 单独用一颗低噪声 LDO 供电。复位电路方面STM32 的 NRST 引脚用一个 100nF 电容接地即可。这颗电容的值别贪大超过 300nF 可能导致上电时复位释放过慢反而触发 PMIC 的看门狗复位。BOOT0 引脚通过 10k 电阻下拉到地方便调试阶段随时用 BOOT1 或者串口烧录量产时也可以把它直接接地并锁定读保护。SWD 调试接口留 4 个端子SWDIO、SWCLK、GND、VCC。别小看这个口后面调 I2C 时序、看寄存器值、擦除 FLASH全靠它。我之前帮人排障对方没留 SWD 口出了问题只能靠串口打日志痛苦指数翻倍。3. 软件架构和 I2C 通信实现3.1 初始化驱动的骨架与超时保护STM32 和 PCA9422 的通信全部走 I2C。首先要把 MCU 侧 I2C 外设配置好开启时钟设置引脚复用为开漏输出模式然后配置 I2C 频率。下面这段是基于 HAL 库的初始化片段工程上用起来改动很少I2C_HandleTypeDef hi2c1; void MX_I2C1_Init(void) { hi2c1.Instance I2C1; hi2c1.Init.ClockSpeed 400000; hi2c1.Init.DutyCycle I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 0; hi2c1.Init.AddressingMode I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 0; hi2c1.Init.GeneralCallMode I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode I2C_NOSTRETCH_DISABLE; HAL_I2C_Init(hi2c1); }注意配置里我开了时钟延展NoStretchMode 设为禁用。PCA9422 这类 PMIC 的寄存器操作速度比较慢有时一方处理内部状态机时会短暂拉低 SCL如果关闭时钟延展就可能出现总线忙或者错误帧。开启延展能让双方自动适配速度代价是最高吞吐率降低。对电源管理这种低频率控制来说我们优先保证可靠性。写一条经验任何 I2C 操作都要加超时。HAL 库的 HAL_I2C_Mem_Write 自带超时参数但有些人在嵌入式 RTOS 环境里直接塞 HAL_Delay 当超时这非常危险。如果 PCA9422 的 SCL 被拉死或者设备掉电HAL_Delay 会一直卡住整个任务被锁死。正确做法是给超时参数传一个固定毫秒数比如 100并且主循环里做一个失败计数连续失败超过 5 次就触发报警提示。3.2 寄存器初始化序列的编写逻辑PCA9422 上电以后默认配置可能不是产品要的参数。我们需要在 STM32 启动初期主动写入一组配置值。这组配置通常包括充电终止电压比如 4.2V预充电电流比如 100mA恒流充电电流比如 500mA充电截止电流比如 60mA降压输出轨电压中断使能寄存器下面这段代码演示了写入充电配置的典型流程寄存器地址是示意值实际要根据具体芯片手册确认#define PCA9422_REG_CHG_CTRL 0x11 #define PCA9422_REG_BUCK_CTRL 0x20 #define PCA9422_REG_INT_MASK 0x30 uint8_t config_charge 0x0A; // 充电电压 4.2V预充电电流 100mA uint8_t config_buck 0x3C; // 降压输出 3.3V uint8_t config_int 0x00; // 使能充电完成、低电量、输入插入中断 void pca9422_init(void) { if (HAL_I2C_Mem_Write(hi2c1, PCA9422_I2C_ADDR, PCA9422_REG_CHG_CTRL, I2C_MEMADD_SIZE_8BIT, config_charge, 1, 100) ! HAL_OK) { // 记录初始化失败重试或报警 } // 后续寄存器依序写入 }写配置的顺序建议是先配置中断掩码再配置降压输出最后配置充电参数。原因是充电一旦使能PMIC 就开始工作如果此时主控尚未准备好接收中断状态可能丢失。反过来先屏蔽中断、配置好再打开中断逻辑上最安全。3.3 读取状态和换算物理量PCA9422 的 ADC 会把电池电压、系统电压和充电电流转成寄存器数值。但寄存器里存的不是直接物理量而是一个按步进编码的数字。拿到原始值以后要按公式换算。假设电池电压寄存器值是 0x5A1F手册给出的步进是 1mV那么实际电压就是0x5A1F 23071 十进制再乘以 1mV得到 23.071V 吗不对那是假设寄存器直接按绝对值编码的情况。实际大多是偏移编码或者二补数。所以换算公式绝不能拍脑袋必须以手册给出的比例因子和偏移量为准。我的建议是把这些换算写成一个独立的小函数并且把量程、偏移、比例因子做成常量表。这样即便换了芯片版本改动也集中在一处。调试时还可以反向用串口打印把物理量值存成日志对照万用表实测值验证换算是否正确。电池电量百分比最粗糙的做法就是查电压表映射。单节锂电池 3.0V 对应 0%4.2V 对应 100%中间按曲线分段。这个做法简单但受负载影响很大——同样的电池轻载 3.7V 和重载 3.7V实际剩余电量完全不同。如果产品对电量精度有要求建议用 PMIC 内的电流积分库仑计功能或者至少做一个空载/带载校准表。3.4 STM32 低功耗模式与 PMIC 的联动整套系统做完基本功能后很多人会觉得项目结束了。但电池产品真正见功力的是待机功耗。STM32F103RC 停机模式电流大约几个微安PCA9422 如果只保持基本稳压输出待机电流也在几十微安级别。两者加起来可以做到非常小。关键点在于PMIC 何时把主控叫醒我习惯把 PMIC 的 INTB 中断引脚接到 STM32 的一个外部中断 GPIO上升沿或者低电平触发具体看 PMIC 手册。主控进停机模式之前先把 I2C 外设时钟关掉但保留外部中断和 RTC。充电完成、电池电压过低、输入插入、输入拔出这些事件PMIC 都会通过 INTB 拉低来产生中断。主控收到中断后从停机模式唤醒读取状态寄存器判断事件类型做相应处理然后再次进停机。说一个我踩过坑进停机模式前一定把 I2C 总线释放干净也就是确保 SCL 和 SDA 都是高电平。曾经有一次我的代码在发送过程中直接进了 STOP 模式I2C 总线保持在半路状态PMIC 那边卡死直到硬件复位才恢复。后来我做了两件事进低功耗前先把 I2C 完全复位一遍并且把 I2C 引脚配置恢复成普通 GPIO 高电平输出这样总线绝不会被卡住。4. 调试中的典型问题与排查清单4.1 I2C 读不到设备寄存器怎么办这是最常见的开局问题。焊好板子上电烧录I2C 扫描却发现设备没有应答。先检查三件事第一PCA9422 有没有正常上电复位。很多 PMIC 的 I2C 接口在输入电源异常或者 RESET 引脚被拉低时会不响应。拿示波器测 VBUS 到 SYS 的上电波形看有没有锯齿状的重启。第二I2C 地址对不对。PCA9422 通常通过外部引脚配置几位地址位地址可能与默认值不同。仔细看原理图地址引脚接高还是接低再对照手册算地址。我见过不下三次软件里写死地址 0x6C其实硬件是 0x63就差一个位扫描结果完全空白。第三总线上拉电阻值。如果主控板上已经有一个 10k 上拉PMIC 模块上又有一个 4.7k 上拉并联后等效电阻太低驱动能力不足SDA 拉不低通信就会失败。用示波器看 SCL/SDA 低电平能不能到 0.4V 以下一眼就能判断。4.2 充电电流和设定值相差很远设了 500mA 充电实际量只有 300mA这种问题要分两类看待。一类是输入限流。PMIC 会根据适配器能力自动限制输入电流如果适配器只能输出 500mAPMIC 会把充电电流往下降确保系统总功耗不超过输入能力。这种情况不是故障是正常保护。想验证就去读输入源状态寄存器看限流值是多少。另一类是发热降额。充电时 PMIC 内部结温过高会自动降低充电电流。在密闭外壳里锂电池上方 2mm 处就是 PMIC温度很容易飙过降额阈值。解决办法是优化散热比如铺铜面积加大、加导热胶或者调整充电电流上限。这个原因靠读 PMIC 的温度寄存器一般能看出来温度值偏高基本可以实锤。4.3 系统突然复位复位源查不到复位可能来自多个地方STM32 自己的 NRST 引脚被干扰拉低、看门狗超时、PMIC 的复位输出动作。排查思路是先分清是哪一侧。在 STM32 的复位控制寄存器 RCC_CSR 里读复位标志能区分是软件复位、看门狗复位还是 NRST 引脚复位。如果是 NRST 引脚复位大概率是电源轨瞬间跌落触发了电压监测复位或者外部复位芯片动作。这时候把示波器探头放到 SYS 电压轨上用深存储模式抓异常波形。常见的元凶是射频模块发射时电流尖峰或者 OLED 屏刷新瞬间负载冲击把 SYS 电压拉掉几百毫伏。解决办法是在 SYS 端加大容量储能电容或者在负载前端加一级 LDO 缓冲。4.4 低功耗下电流下不来软件写了 STOP 模式实测整机电流还有 3mA这种问题最让硬件工程师头大。先一级一级拆。从电池端串联一个微安级电流表然后用排除法断开传感器供电、关闭显示屏、断开通讯模块。每次都去掉一个外围负载观察电流变化。很多时候问题不在 STM32 也不在 PMIC而是漏掉了某个传感器的工作电流。还有一种隐蔽问题PMIC 的某个输出轨没有关空载也有静态电流。检查配置寄存器里有没有禁用未使用的 LDO。F103 的某些 GPIO 在输出模式下如果外接下拉电阻也会产生额外电流。进 STOP 前把所有用不到的 GPIO 都配置成模拟输入模式能省下不少。4.5 快速排查清单现象检查项优先排查方向I2C 扫描不到地址、上拉、复位示波器看总线波形充电电流偏小输入限流、NTC 温度、发热降额读状态寄存器、测温系统重启SYS 电压跌落、看门狗深存储示波器抓波动待机电流过大未关的外设、GPIO 状态逐路断电排除电池发热充电电压偏高、NTC 失效验证电池型号和配置5. 模具到量产要补充的测试与细节5.1 电源相关的进料检验项目PMIC 这种核心芯片进料检验比外观抽检更重要。我们通常要求供应商提供出厂测试报告覆盖关键电气参数静态电流、充电路径导通电阻、降压效率。有条件的话每批抽 5 到 10 片焊一个最小测试板跑一遍 I2C 读写和带载测试。别看这麻烦电芯批次和 PMIC 批次一旦出现不匹配量产良率能掉到 80% 以下。电感的来料差别也很明显。同样标称 3.3 微亨不同供应商的饱和电流和 DCR 可能差 30%。建议把电感也纳入关键物料管理换供应商必须重新三件套验证纹波、效率、瞬态响应。5.2 ESD 和浪涌测试的整改经验便携设备要过静电测试电源输入口是重灾区。USB 口直接承受接触放电能量会沿着 VBUS 和数据线灌进 PMIC。整改方向是 TVS 管选型要准工作电压选高于最大输入电压钳位电压要低于 PMIC 的绝对最大额定值同时 TVS 到 USB 口的引线尽量短缩短泄放路径。还有一种情况设备从测试台搬到金属桌面时产生静电通过外壳缝隙耦合到电池正极导致电池接口附近的 PCB 被击穿。这种问题通常需要调整结构接地让外壳和系统地通过多点连接起来而不是靠模糊的电容耦合。5.3 量产烧录时的校准与标定如果你的产品需要显示电池百分比建议在产线上做一个两点的校准第一次插上电源触发充电完成记录充满电压第二次带载放电到低电量关机点记录最低电压。把这两个点写进 STM32 的备份寄存器或者 Flash 保存起来。这样后续计算电量百分比时能补偿 PMIC ADC 的偏差显示更准。产线校准还有个好处能提前发现电池安装方向反、NTC 漏焊、电池电压异常偏低这些装配问题。每台机器测试软件里做一个电源状态综合检查充电状态、电池电压、系统电压都符合预期再放行能明显降低售后返修率。6. 几个可以继续扩展的方向这套系统搭好以后扩展路径很清晰。如果你后面想做更大功率的设备PCA9422 后面加一个外部负载开关或者升压芯片就能驱动电机、加热丝等重负载前提是 PMIC 的总功率预算要到。想做成多电池的方案也可以把多颗 PMIC 并联或者串联管理STM32F103RC 一颗主控通过 I2C 分别管理两套电源逻辑上也不复杂。软件层面还可以在 STM32 上做电源事件日志。每次 PMIC 中断触发时把事件类型、时间戳、电压值存进 Flash。设备返修时读日志就能知道设备是过放、过温还是充电超时损坏的。这个功能成本几乎为零但对售后问题定位帮助巨大。我个人在实际操作中最深的体会是电源管理方案的成败七分在硬件布局三分在软件调试。PCA9422 再智能遇到地回路设计不良、电感选错、I2C 走线被干扰一样罢工。反过来只要 PCB 基础打牢剩下的工作基本就是愉快的寄存器填填改改了。希望这篇总结能给你一个完整的技术框架让你做自己那套电源管理时少走几个弯路。
返回列表