做了好几年电池管理相关的开发,一直在和各种储能、备用电源打交道。看到这个标题里的 MP2642GR-Z 和 STM32F723ZE,我第一反应是:这哥们大概率是在做一个两串电池均衡控制板,而且对器件的定位想得很清楚。两颗芯片搭在一起,均衡器和主控各管各的,既没把控制逻辑压在一颗芯片上,也没有用一颗纯模拟均衡芯片硬扛全局。这篇文章就围绕这个组合,聊聊方案怎么定、硬件怎么摆、固件怎么写,以及我在同类项目里实际踩过的坑。
双串电池在储能和备用电源系统里非常常见,户外电源、小型 UPS、低压储能簇都有它的身影。别以为只有两串就简单,恰恰是因为电池少,单体之间的差异会直接体现在整机可用容量上。某节电芯自放电快一点,或者内阻大一点,整包的实际容量就会明显缩水,时间一长甚至会在充电末端把一个电芯顶到过压。以前做被动均衡,电阻放电发热大、时间慢,在储能这种动辄几十安时电芯的场景下根本压不住。换成 MP2642GR-Z 这类主动能量转移方案,加上 STM32F723ZE 做策略仲裁,合力的效果完全不一样。
1. 为什么两串电池必须均衡,方案怎么定的
1.1 不均衡会让备用电源提前失效
先看最实际的故障场景。两节电池串联,充电电流是从正极一路穿过两节电芯回到负极,电流完全一样,但容量和内阻不一样。容量低的那节先充满,容量高的那节还在慢慢爬。充电机不知道内部情况,它只看总电压,总电压到了设定值就停。结果就是每次充电,容量低的都处于过充边缘,容量高的永远充不满。
放电反过来,容量低的先放到截止电压,系统为了保护电池直接罢工,另一节明明还有不少余量,却只能眼睁睁看着放不出来。
备用电源场景更苛刻。UPS 平时处于浮充状态,电池基本不深放,全靠小电流维持。如果两节电芯自放电率不一致,一节长期处于低电量状态,硫酸盐化或者锂电析锂就会加速,等真正停电需要切换时,本来就该满血的电池组已经处于半瘫痪状态。所以在设计一个 mS 级切换的备用电源时,均衡不是加分项,是安全项。
1.2 被动均衡为什么在储能场景不划算
被动均衡的原理很直白:把电量高的电池通过电阻放点电,让高位者等待低位者。问题也在这。电量是宝贵的,被白白放掉不说,电阻产生的热量还得想办法散掉。几十毫安的均衡电流对几安时的电芯勉强凑合,对几十安时的储能电芯就是个安慰。想要均衡电流大一点,电阻得加大,PCB 面积和散热跟着膨胀,均衡时间还是要好几个小时。
更关键的是,被动均衡只对“充电末端过充”的问题有效,对放电场景几乎束手无策,因为你不可能靠放电来提升整包放出的电量。这也是我在储能项目里坚持用主动均衡的原因——主动均衡本质上是把高电量电芯的能量“搬运”到低电量电芯,两节电芯相互补血,不浪费能量,发热小,均衡时间短,充放电两个方向都受益。
1.3 主动均衡与 MCU 分工
MP2642GR-Z 是一颗专门做双向能量转移的均衡芯片,它的价值在于把复杂的功率开关控制逻辑直接集成进去。我只需要配置外部电感、设定工作模式,它就能自动判断哪个电芯需要转移能量,还能通过 I2C 把两节电芯电压和状态回传给主控。
STM32F723ZE 在这里起的是大脑作用。它不会去干预 MP2642 内部每一个 PWM 周期,而是负责更高层的事情:多周期电压采样和滤波、判断当前处在充电、放电还是静置状态、决定均衡的启动和停止条件、通过 CAN 或者串口把数据上报给系统级管理单元。
这种分工有一个很实际的好处。如果主控死机或者程序跑飞了,均衡芯片还能按照内部默认策略继续工作,保护电池不失控;反过来,均衡芯片就算出问题,主控也能检测到异常并发出告警。两个器件互为冗余,系统鲁棒性比单芯片方案高出一截。
2. 关键硬件:MP2642GR-Z 到底做了什么
2.1 能量转移原理
MP2642GR-Z 采用的是电感式电荷泵结构,本质上是一个双向 Buck-Boost 转换器。它的两个功率开关和外部储能电感跨接在电池串联节点之间,通过调节 PWM 占空比,能量可以从高电压电池流向低电压电池。
举个例子,电池 1 电压 3.60V,电池 2 电压 3.42V,压差 180mV。芯片内部主控计算后决定:从电池 1 抽电,经过电感存储,再释放到电池 2。等效关系可以用一个简化的占空比公式表达:
D ≈ V_low / V_high,也就是 D ≈ 3.42 / 3.60 ≈ 0.95
但这只是理想占空比,实际设计中还需要考虑 MOSFET 导通电阻、电感 DCR、线路电阻的压降。均衡电流越大,这些寄生参数的影响越明显。按照这个项目的设置,外部电感选 10μH,开通频率 500kHz,平均均衡电流能到 800mA 左右,峰值为 1.6A。对于两串 10Ah 的电芯,压差 180mV 大约在 20 分钟以内就能拉回 30mV 以内,这个效率是被动均衡完全比不了的。
2.2 引脚与外围电路
MP2642GR-Z 采用小封装,两侧的功率引脚可以直接接电池串联节点,中间是控制逻辑引脚。我这里拿项目实际用到的引脚做了一个整理,方便照着画板子:
| 引脚 | 功能 | 接法 |
|---|---|---|
| VBAT1 | 低端电池正极 | 接电池1正极,就近放 1μF 陶瓷电容 |
| VBAT2 | 串联节点 | 接电池1负极/电池2正极,放 10μF 电容 |
| VSS | 系统地/电池负极 | 接电池2负极,单点回流到采样地 |
| LX | 开关节点 | 接 10μH 电感,电感另一端接 VBAT2 |
| EN | 使能 | 接 MCU GPIO,高电平开启 |
| SCL / SDA | I2C 接口 | 上拉到 3.3V,各串 2.2kΩ |
| ADDR | I2C 地址选择 | 接 VSS 或 VDD,区分板上器件地址 |
| FLT | 故障输出 | 开漏,上拉到 3.3V,接 MCU 外部中断 |
有一个细节必须注意:VBAT1 和 VBAT2 引脚上的陶瓷电容要尽量靠近引脚放置,而不是靠近电芯。均衡芯片开关动作时会有很大的 di/dt,如果电容离引脚太远,环路电感会造成电压尖峰,严重时会把芯片的电源引脚击穿。我自己第一版板子就是因为电容位置偏了 3mm,实测高频噪声从正常范围一路飙到 2V 以上,后来整个重摆了一版才解决。
2.3 寄存器与控制模型
MP2642GR-Z 内部有完整的电压检测和逻辑控制电路,通过 I2C 可以读取实时数据,也可以设置工作模式。项目里常用的几个寄存器我整理了一下:
| 寄存器 | 含义 | 说明 |
|---|---|---|
| 0x00 | 状态寄存器 | 返回空闲/均衡中/故障/过温 |
| 0x01 | CELL1 电压 | 12 位 ADC,分辨率 1mV |
| 0x02 | CELL2 电压 | 12 位 ADC,分辨率 1mV |
| 0x03 | 控制寄存器 | 使能均衡、选择自动/手动模式 |
| 0x04 | 均衡电流上限 | 可设 200mA/400mA/800mA |
| 0x05 | 均衡压差阈值 | 默认 30mV,可调 |
默认情况下,芯片会自动检测两节电芯压差,超过阈值就开始均衡。这种自跑模式对很多场景已经够用,但我还是建议把阈值设由主控统一配置,而不是直接吃默认值。因为不同电化学体系的电芯对均衡起止点的要求完全不同,铁锂电池和三元锂电池的充电末端特性差异很大,固化在芯片里的默认值未必适配你的电芯规格。
3. 围绕 STM32F723ZE 搭建的整板系统
3.1 系统框架:两个核心层级
整个板子的架构可以分成两个层级。
第一层是功率均衡层,由 MP2642GR-Z、匹配电感和外围采样电阻组成。这层直接对接电池组,负责能量转移的具体动作。第二层是主控层,STM32F723ZE 负责策略运算和系统通信。它的 ADC 引脚通过精密电阻分压网络监测电池总电压和中间节点电压,I2C 总线连接均衡芯片,另一路 UART 或 CAN 接口用于和上位机或者储能系统主机互联。
为什么要把电压采样做成两路并联?一个直接原因就是安全冗余。MP2642 内部 ADC 能测电芯电压,但它毕竟聚焦在均衡本身,一旦内部基准漂移或者采样链路故障,主控完全失去判断依据就麻烦了。STM32F723ZE 自己有独立的 12 位 ADC 和硬件过采样功能,接两个精密电阻分压网络作为第二套电压观测通道,平时用于校准 MP2642 回传的数据,异常时也能直接旁路均衡芯片的读数。这属于没有写在规格书里、但做系统设计时一定会想到的部分。
3.2 引脚分配与接线关系
这里放一份实际可用的引脚分配,方便以后做板参考:
| STM32 引脚 | 外设 | 连接对象 | 功能 |
|---|---|---|---|
| PB6 | I2C1_SCL | MP2642 SCL | 均衡芯片时钟 |
| PB7 | I2C1_SDA | MP2642 SDA | 均衡芯片数据 |
| PA0 | ADC1_IN0 | 电池总压采样 | 总电压监测 |
| PA1 | ADC1_IN1 | 中间节点采样 | 单节电压计算 |
| PA8 | GPIO 输出 | MP2642 EN | 控制均衡使能 |
| PC13 | GPIO 输入 | MP2642 FLT | 故障中断输入 |
| PA9 | UART1_TX | 调试口/上位机 | 状态上报 |
| PA10 | UART1_RX | 调试口/上位机 | 参数下发 |
| CAN1_RX/TX | CAN 外设 | 储能系统主机 | 远程监控 |
这里有个很容易踩的坑:I2C 的上拉电阻。MP2642GR-Z 的逻辑电平可能是 1.8V 或者 3.3V,不同封装批次会有差异。如果只按芯片手册标称值选了 1.8V 上拉,而 STM32F723ZE 的 GPIO 又工作在 3.3V,两边电平匹配就会出现间歇性通信失败。我建议在 PCB 上预留三组上拉电阻位,一组接 1.8V,一组接 3.3V,一组不贴。调试时根据实际芯片输出电压选择贴哪组,省去改版的麻烦。
3.3 电源树与散热考虑
主控供电由电池总电压经过一颗低压差线性稳压器降压到 3.3V 提供。因为均衡芯片开关动作会带来低频纹波,LDO 的输出端必须加大容量陶瓷电容,我实际用了 22μF 加 0.1μF 的组合,把 3.3V 上的纹波压到 30mV 以内,避免干扰 STM32 的 ADC 采样。
散热方面,MP2642 内部集成 MOSFET,但封装面积有限。连续均衡 800mA 时,芯片功耗大约在 0.3W 到 0.5W,虽然不夸张,但如果主板放在密闭的储能机箱里,长期运行也会积热。建议在芯片附近留足量的铜皮散热区,有条件就加过孔阵列连接到底层铜皮。均衡电流越大,这一步越不能省。
4. 固件里的均衡状态机,怎么写不会乱
4.1 任务划分
STM32F723ZE 主频有 216MHz,跑均衡策略绰绰有余。我的固件结构里分了三层任务:1ms 定时器中断负责读取 MP2642 状态寄存器,10ms 任务负责 ADC 采样和电压滤波,1s 任务负责均衡判据更新和系统状态上报。
这里要特别强调,电压滤波不能省。电池电压尤其是浮充状态下的电压,有一堆噪声叠加在上面。如果不滤波,均衡策略会被噪声带着反复启停,继电器和功率开关频繁动作,寿命跟着缩水。
4.2 电压读取和滤波代码
MP2642 电压读取代码不长,核心就是 I2C 读取 12 位数据:
uint16_t read_mp2642_voltage(uint8_t cell_id) { uint8_t reg = (cell_id == 1) ? 0x01 : 0x02; uint16_t value = 0; uint8_t buf[2] = {0}; HAL_I2C_Master_Transmit(&hi2c1, MP2642_ADDR, ®, 1, 10); HAL_I2C_Master_Receive(&hi2c1, MP2642_ADDR, buf, 2, 10); value = (uint16_t)(((buf[0] & 0x0F) << 8) | buf[1]); return value; }主控自己的 ADC 采样通道用了中值加滑动平均的双重复合滤波。中值滤波可以有效剔除尖峰噪声,滑动平均则抹平长时间漂移:
#define ADC_SAMPLE_COUNT 7 uint16_t get_filtered_voltage(ADC_HandleTypeDef *hadc, uint32_t channel) { uint16_t raw[ADC_SAMPLE_COUNT] = {0}; for (int i = 0; i < ADC_SAMPLE_COUNT; i++) { HAL_ADC_Start(hadc); HAL_ADC_PollForConversion(hadc, 10); raw[i] = HAL_ADC_GetValue(hadc); HAL_ADC_Stop(hadc); HAL_Delay(2); } // 简单冒泡排序取中值 for (int i = 0; i < ADC_SAMPLE_COUNT - 1; i++) { for (int j = 0; j < ADC_SAMPLE_COUNT - 1 - i; j++) { if (raw[j] > raw[j + 1]) { uint16_t tmp = raw[j]; raw[j] = raw[j + 1]; raw[j + 1] = tmp; } } } return raw[ADC_SAMPLE_COUNT / 2]; }分压电阻的标称误差会导致单节电压测量偏差 10mV 以上,这在均衡判断里是不可接受的。所以固件里还要做一个校准流程:上电静置后,用高精度万用表实测两节电芯电压,把偏差系数写入 Flash,之后每一次上报电压都用这个系数修正。不要嫌这一步麻烦,没有校准的均衡系统,误差可能比均衡阈值还大,等于白做。
4.3 均衡启动停止逻辑
均衡逻辑不能只看当下压差,要结合电池状态来判断。我的策略分成了两个模式:充电均衡和静置均衡。
充电模式下,允许均衡开启的区间是电池总电压在某个范围内。以铁锂双串为例,单节标称 3.2V,两串就是 6.4V,充电末端电压设定在 7.3V。当主控读到总电压大于 6.8V,认为电池进入充电末端,才开始允许均衡。这个设计的逻辑在于,充电末端最容易出现压差拉大的情况,同时均衡电流对充电时间影响最小。
静置模式下,判断就简单了。如果系统检测到没有充放电电流,并且压差持续 30 秒超过启动阈值,就开启均衡。这里有一个强制延时逻辑,防止刚切负载时电压回弹造成误判。
实际控制核心代码如下:
typedef enum { BAL_IDLE, BAL_1_TO_2, BAL_2_TO_1, BAL_PROTECT } balance_state_t; balance_state_t balance_calc(uint16_t cell1_mv, uint16_t cell2_mv) { uint16_t diff; if (cell1_mv > cell2_mv) { diff = cell1_mv - cell2_mv; } else { diff = cell2_mv - cell1_mv; } if (diff > BAL_START_THRESHOLD_MV) { // 默认 30mV return (cell1_mv > cell2_mv) ? BAL_1_TO_2 : BAL_2_TO_1; } if (diff < BAL_STOP_HYSTERESIS_MV) { // 默认 10mV,滞回 return BAL_IDLE; } return BAL_PROTECT; }看到这里你可能会问:为什么要设置一个 10mV 的滞回区间?因为电芯电压在均衡过程中不是单调变化的,均衡电流断开的瞬间,电芯电压会有一个回弹。如果启动阈值和停止阈值设成同一个值,就会出现“启动一下、停止一下、再启动”的振荡。设置滞回区间,本质上是给判断加了一个缓冲区。我一般把启动阈值设在 30mV,停止阈值设在 10mV,两者之间用 20mV 的裕量挡住噪声和回弹。
4.4 保护条件优先级
均衡系统内部保护逻辑其实很少有人展开讲。均衡本质上是给电池做微小的电量搬运,看似温和,但在异常情况下也可能导致问题:如果均衡芯片内部 MOSFET 击穿,会形成两节电芯之间的短路大电流,那将是灾难性的。
固件里必须做的保护有两条。第一,均衡开启前检查 FLT 引脚,如果 FLT 拉低,说明芯片内部已经检测到异常,严禁使能均衡。第二,每次均衡启动前和均衡启动后 5 秒读取一次均衡电流,正常情况下电流方向应该和压差方向一致。如果出现电流异常大或者方向反了,立即关闭使能并拉闸。这套逻辑可以防止芯片内部失效时把故障扩大。
5. 实测表现与调试实录
5.1 一组实测数据
我在模拟项目环境里做过一轮完整测试,电芯用的是两节 10Ah 磷酸铁锂,初始压差 178mV。均衡目标是把压差降到 10mV 以内。测试过程记录了均衡启动后的电压变化:
| 时间 | CELL1 电压 | CELL2 电压 | 压差 | 状态 |
|---|---|---|---|---|
| 0 min | 3.602V | 3.424V | 178mV | 均衡中 |
| 5 min | 3.586V | 3.440V | 146mV | 均衡中 |
| 10 min | 3.571V | 3.455V | 116mV | 均衡中 |
| 15 min | 3.558V | 3.468V | 90mV | 均衡中 |
| 20 min | 3.546V | 3.480V | 66mV | 均衡中 |
| 30 min | 3.527V | 3.503V | 24mV | 均衡中 |
| 40 min | 3.510V | 3.501V | 9mV | 停止均衡 |
均衡停止后,断开均衡器,静置 30 分钟,压差又回弹到 15mV 左右。这是正常现象,因为电芯极化效应消失后电压会有一个恢复过程。所以我在固件里把均衡停止阈值设成 10mV,实际停机后即使回弹到 15mV 也在 30mV 的启动阈值之内,不会造成频繁重启。
5.2 踩过的三个坑
第一个坑是采样地和功率地混接导致电压读数飘。MP2642 开关动作时,功率地会有比较大的地弹噪声。如果 ADC 采样地直接从功率地拉过来,每次均衡电流越大,电压读数偏差就越大。后面我把采样地单独走了一条细线,单点接到电池负极,ADC 读数才稳下来。
第二个坑是 I2C 通信偶发失败。排查了很久发现是 EN 引脚和 I2C 地址选择引脚共用了同一组 GPIO。上电时序里,EN 拉高瞬间 I2C 地址还在切换,芯片直接失去响应。解决方式是让 EN 的 GPIO 和 ADDR 的 GPIO 错开,主控先完成地址锁存,再拉高使能。
第三个坑是均衡电感的饱和电流余量不够。一开始选用的电感规格书上标称额定电流 1A,但实测连续均衡时温度上升后电感量骤降,高频噪声变大了,均衡效率反而往下掉。后面换成饱和电流 3A 的电感,才算彻底解决。这个经验是:电感的饱和电流按峰值均衡电流留两倍裕量,不要只看平均电流选型。
5.3 安全提醒
储能系统的调试和普通开发板不一样,电池能量就在那里,短路和过充都可能造成严重后果。所有均衡测试最好在专用防护环境里进行,工作台附近要放灭火器,测试线不能细,尽量用带绝缘夹的测试线。第一次上电不要直接接满电的电芯,先用低容量电芯或者串联一个小阻值电阻限流,确认电流正常再放开。
我通常的做法是先用可编程电源模拟两节电芯电压,跑一遍均衡代码逻辑,确认状态切换正确之后,再换成真实电芯做长时间测试。这一步能把大部分逻辑错误在安全的模拟环境里发现,省掉很多麻烦。
6. 写在最后的一些体会
这套 MP2642GR-Z 和 STM32F723ZE 的组合,我实际用下来的最大感受是“硬件把脏活干完,软件只负责做聪明的决定”。以前做纯模拟均衡,PCB 上堆满了比较器和 MOS 管,调试一个 di/dt 尖峰能折腾好几天。现在均衡芯片把功率级和高精度电压测量都集成好了,软件开发重心放在滤波、状态判断和保护策略上,整体项目周期缩短了将近一半。
如果让我重新做一遍这个项目,我会在两处提前改进:一是从一开始就把 I2C 地址选择和上拉电阻做成可配置,省得后续改板;二是把均衡策略参数全部放到 Flash 里,支持通过上位机在线修改,这样现场调试不需要重新烧录固件。
做电池相关开发,最重要的是对异常保持敬畏。任何一次看似“可以忽略”的电压异常,都有可能发展成安全事故。均衡只是一个环节,但它承载的使命并不轻——让每一节电芯在安全边界内发挥出全部容量,在需要的时候顶上去。这大概就是我做这件事最真实的动力。