☰
两节串联电池主动均衡设计:MP2642GR-Z与STM32F411RE实践
2026/10/15 1:25:56 网站建设 项目流程

1. 两节串联为什么会失衡:容量差、自放电差与“木桶效应”

在储能和备用电源系统里,两节串联电池之间的压差一旦被拉开,整个模组的可用容量和循环寿命都会往下塌。与其用被动均衡把多余的能量在电阻上烧成热量,不如用主动均衡芯片直接把电荷从高电压单元搬到低电压单元。这篇就聊聊我最近用 MP2642GR-Z 搭配 STM32F411RE 做的一块两节串联电池均衡板,从硬件接线、I2C 通信到均衡策略和实测数据,把能复现的细节全部摊开。适合正在做小容量储能、UPS 备用电池或者两串锂电模组的工程师参考,尤其是第一次接触主动均衡芯片的开发者。

1.1 失衡的三个来源与量化代价

先说清楚问题本身。任何两节电池都不可能是完全一致的:出厂容量有偏差、内阻有偏差、自放电率有偏差,使用一段时间后这些偏差还会被放大。再加上电池在模组里的位置不同,散热条件不同,温度差异会进一步加剧自放电和容量衰减的差异。在串联拓扑里,充电电流和放电电流完全一样,于是容量小的那节总是先充满、先放空,时间一长,两节电池的 SOC(荷电状态)差距就越拉越大。

这个差距的代价可以用“木桶效应”一句话概括:整串电池的可用容量等于最弱的一节,而不是平均值。举个例子,两节 50Ah 磷酸铁锂串联,标称电压 6.4V,假设两节之间 SOC 相差 8%,那就是 4Ah 的电荷量差。充电时电压高的那节先顶到充电截止电压,充电停止,电压低的还没充满;放电时电压低的先到放电截止电压,放电停止,电压高的还剩不少。一来一回,整串电池每次循环少用 4Ah,相当于白白丢了 8% 的容量。在备用电源场景里,这种容量损失平时看不见,等到市电掉电测试时才发现备用时间缩水,那时候再处理就晚了。

1.2 被动均衡和主动均衡的本质差别

传统的被动均衡思路很简单:在电压高的电芯上并联一个放电电阻,把多余的能量以热量形式放掉。成本低、控制简单,但有两个硬伤。一是均衡电流做不大,受限于电阻功耗和散热,一般只有 50~100mA,碰上几十安时的大电芯,均衡一次要几十个小时;二是能量浪费严重,放掉的都是电池里实实在在存储的电能,最后变成封装内部的热量,对散热设计非常不友好。

主动均衡的思路是把电荷从高电压电芯“搬运”到低电压电芯,而不是烧掉。实现方式通常是电感或电容式的能量转移,效率能做到 80%~90%。同样处理 4Ah 的不平衡,1A 均衡电流大约 4 小时完成,被动均衡按 0.1A 算要 40 小时,而且被动方案要把 4Ah × 3.2V ≈ 12.8Wh 的能量全部变成热量散掉,主动方案按 85% 效率算,实际发热只有不到 2Wh。这就是我在这个项目里最终选择 MP2642GR-Z 这类主动均衡芯片的根本原因。

提示:均衡的目标不是把每节电池电压做到完全相等,而是把 SOC 差控制在一个可接受范围。电压相等不等于 SOC 相等,不同电芯的 OCV-SOC 曲线有细微差异,判断时脑子里要时刻有这个前提。

2. MP2642GR-Z 接入电池组:拓扑、接线与电感选型

2.1 这颗芯片替你完成了什么

MP2642GR-Z 是专为两串电池设计的双向主动均衡控制器,内部集成功率开关和控制环路,外部只需要一颗功率电感。它的核心工作模式是:持续检测两个电芯的电压,当检测到电压差超过内部阈值时,自动把电荷从高电压电芯泵到低电压电芯。泵浦方向由芯片内部逻辑决定,不需要 MCU 判断极性,这点非常省事。

MCU 在中间扮演的角色是“策略决策者”:芯片只关心怎么搬电荷,但什么时候搬、搬到什么程度、系统当前是否适合均衡,这些判断需要交给 STM32F411RE。MCU 通过 I2C 读写芯片的寄存器,配置使能位、查询两个电芯的电压遥测、读取故障状态,再根据整机工况决定均衡是否运行。

需要说明的是,具体管脚命名和寄存器地址请以 MP2642GR-Z 官方数据手册为准,下面给出的接线逻辑按这类主动均衡芯片的通用框架描述,整体拓扑是可靠的。

2.2 接线关系与采样走线的关键

两节电池的串联关系很直观:电芯1的正极是整个模组的 BAT+,电芯1的负极与电芯2的正极在中间相连,电芯2的负极是整个模组的 BAT-。芯片需要感知三个节点:顶层电芯电压、底层电芯电压、以及串联中点。

连接节点接向位置说明
VBAT 顶层采样电芯1正极顶层电芯电压采样与芯片供电
中点采样电芯1负极 / 电芯2正极串联中点,必须单独引线
GND 底层采样电芯2负极底层参考地
SW 开关节点外置功率电感两端电感型能量搬运路径
SCL / SDAF411RE 的 I2C 引脚需要上拉到 3.3V,可加串阻抑制振铃
ENF411RE 的 GPIO高电平使能均衡控制器
INTF411RE 的外部中断引脚故障或状态变化通知

这里必须强调采样线的走法。芯片做均衡方向判断依赖的是电压比较,所以 VBAT、中点、GND 这三条采样线必须采用独立的 Kelvin 接法,直接从电芯端子上拉细线到芯片采样脚,绝不能在采样路径上共用负载电流的铜皮。原因很简单:均衡电流或者负载电流在铜皮上会产生毫伏级压降,总线阻越宽越容易被忽略,但这几分压降足够让电压比较器做出错误判断。实测中,采样线不处理干净的板子,电压读数的抖动可以达到 20mV 以上,比均衡停止阈值还大,加上之后整个状态机就没法稳定工作。

2.3 电感和电容的选型

电感是这套方案里最容易选错的元件。它直接影响均衡电流峰值、系统效率和开关噪声。我整理了一份自己的选型参考:

参数推荐范围选型理由
电感量2.2~10 µH太小则电流峰值过大,容易触发过流保护;太大则响应慢、体积大
饱和电流≥ 1.5 × 峰值均衡电流防止电感饱和后电感量骤降,电流瞬间激增
DCR尽量 < 50 mΩ直接影响能量搬运效率
类型屏蔽式绕线功率电感叠层电感抗饱和能力弱,屏蔽型对周边走线干扰小

我最终用的是 4.7µH、饱和电流 4.5A 的屏蔽绕线电感,DCR 大概 20mΩ。这个参数的逻辑是:芯片的峰值均衡电流能做到 2A 级别,按 1.5 倍余量就需要至少 3A 饱和电流,再预留一点温度降额,4.5A 比较稳妥。

PCB 布局上,四条硬性要求:第一,SW 开关节点和电感之间的走线要短要粗,开关节点面积控制在最小,避免形成天线辐射;第二,去耦电容紧贴 VBAT 和 GND 引脚,100nF 陶瓷电容配合 10µF 的电解电容组合;第三,I2C 两根信号线不要贴着电感或者 SW 节点走,必要时两侧包地处理;第四,电池采样线采用星型接地,先汇到芯片的采样地,再统一回流到电池负极,不要和功率地混在一起。这几条如果第一条没做好,后面实测时示波器上看到的开关振铃会教你重新做人。

3. STM32F411RE 上位控制:I2C 通信与寄存器操作

3.1 为什么选 F411RE 这颗 MCU

均衡芯片本身是个能量搬运执行器,它并不了解整机状态:现在是在充电还是放电?温度合不合适?要均衡多久?这些策略问题需要一个 MCU 来做。选 STM32F411RE 有几点实际考量:

第一,这颗芯片在 100MHz 下运行 Cortex-M4F 内核,512KB Flash、128KB SRAM,跑均衡状态机绰绰有余,剩余空间还能做日志缓存和曲线记录。第二,硬件 I2C 支持 400kHz 快速模式,和均衡芯片通信完全够用,不用软件模拟 I2C。第三,GPIO 数量足够覆盖均衡使能、中断输入、状态指示灯、与主机通信这几件事,不需要为了 IO 扩展再挂一颗芯片。第四,Cortex-M4 的 FPU 和 DSP 指令虽然在这个项目里不是刚需,但以后要加数字滤波或者 SOC 估算算法时,不用换平台。

对比过更小的 G0 系列和老的 F103 系列:G0 便宜但 SRAM 太小,日志不够存;F103 频率和外设都够,但同配置下价格和供货灵活性不如 F4 系列。最终 F411RE 是成本、性能、开发速度三者平衡下来的选择。

3.2 I2C 通信骨架与代码

通信层面要处理的寄存器不多,基本就三类:控制寄存器、状态/故障寄存器、两节电芯的电压遥测寄存器。以下代码展示了用 HAL 库读写均衡芯片的基础函数:

#define BAL_I2C hi2c1 #define BAL_ADDR 0x25 /* 7位地址,以数据手册为准 */ #define BAL_REG_CTRL 0x00 #define BAL_REG_STAT 0x01 #define BAL_REG_VCELL1_H 0x02 #define BAL_REG_VCELL1_L 0x03 #define BAL_REG_VCELL2_H 0x04 #define BAL_REG_VCELL2_L 0x05 #define BAL_CTRL_EN (1U << 0) static HAL_StatusTypeDef bal_write_reg(uint8_t reg, uint8_t val) { return HAL_I2C_Mem_Write(&hi2c1, (uint16_t)(BAL_ADDR << 1), reg, I2C_MEMADD_SIZE_8BIT, &val, 1, 50); } static HAL_StatusTypeDef bal_read_regs(uint8_t reg, uint8_t *buf, uint8_t len) { HAL_StatusTypeDef st; for (uint8_t retry = 0; retry < 3; retry++) { st = HAL_I2C_Mem_Read(&hi2c1, (uint16_t)(BAL_ADDR << 1), reg, I2C_MEMADD_SIZE_8BIT, buf, len, 100); if (st == HAL_OK) return HAL_OK; HAL_Delay(1); } return st; }

为什么用HAL_I2C_Mem_Read而不是先写地址再读?因为一条Mem_Read调用就在内部处理了起始条件、从机地址、寄存器指针、重复起始和数据读取的完整时序,代码简洁且不容易出错。我加了重试机制,原因是在均衡芯片检测到故障并进入锁存状态时,它可能短暂不响应 ACK,或者在忙状态时直接 NACK。实测重试 3 次、间隔 1ms 后总线基本都能恢复,不用做复杂的总线恢复流程。

上拉电阻也值得单独说。400kHz 下如果总线上只有这一颗从机,总电容不大,4.7kΩ 上拉就能得到干净波形;如果总线上还挂了 EEPROM 或者温度传感器,直接把上拉降到 2.2kΩ。我在 SCL 和 SDA 上各串了一个 100Ω 电阻抑制振铃,配合示波器实测,边沿过冲明显改善。注意上拉必须接到芯片 IO 供电的 3.3V 侧,绝对不要图省事接到板子的 5V 电源,这个坑我后面实测部分会细说。

3.3 电压读取与数据可信度校验

电芯电压遥测寄存器通常是 16 位数据,分高字节和低字节存储。读取后需要合并,并做合理性校验:

static uint16_t bal_read_cell_mv(uint8_t reg_h, uint8_t reg_l) { uint8_t buf[2]; if (bal_read_regs(reg_h, buf, 2) != HAL_OK) return 0xFFFF; uint16_t raw = ((uint16_t)buf[0] << 8) | buf[1]; /* 数据有效性判断:0.5V~5V 之外的值一律视为异常 */ if (raw < 500 || raw > 5000) return 0xFFFF; return raw; }

这个校验非常关键。I2C 在电气噪声大的环境里偶尔会读到错误数据,如果直接用错误电压去做均衡判据,状态机会做出完全错误的行为。把异常值挡在外面,宁可判为故障也不冒险均衡,是电池系统设计的基本原则。均衡期间芯片自身的 ADC 采样也可能被开关噪声影响,所以严格来说,电压遥测最好在芯片停止开关动作之后再读取,这一点在下一节的测量窗口里展开。

4. 均衡策略与状态机:什么时候均衡、均衡多久、停在哪

4.1 判据设计:阈值、迟滞与系统工况

均衡策略的第一条原则是:不能只看瞬时电压差就启动均衡。我采用的判据是启动阈值 30mV、停止阈值 10mV,并且要求电压差持续 10 秒以上才触发。这个迟滞设计是为了避免状态机在阈值附近反复横跳。如果不加迟滞,噪声稍微波动一下就可能让均衡在启动和停止之间来回切换,电感上的电流反复建立又关断,效率损失远大于收益。

第二条原则是均衡必须和工作状态绑定。我只允许在系统待机、浮充、且负载电流小于 0.05C 的情况下启动均衡。原因很直接:大电流充放电时,串联回路的负载电流会在电芯内阻与线路阻抗上产生极化电压,这个极化电压叠加到端电压上,会让电压差读数严重失真,误判概率极高。而且均衡电流与负载电流叠加,电池发热更明显,对寿命没有好处。备用电源系统的特点是大部分时间处于浮充或待机状态,均衡窗口非常充裕,不需要去挑战大电流工况。

第三条原则是温度限制。当电池温度低于 5°C 或高于 45°C 时强制禁止均衡。低温下锂电负极析锂风险升高,高温下均衡产生的附加热量可能推高电芯温度,这两类场景都不适合做能量搬运。如果系统里有 NTC,软件直接读取温度再做判断;没有 NTC 的话,可以参考芯片自身的过温保护,但保守的做法还是建议外接温度传感器。

4.2 状态机实现

整个均衡控制核心是一个简单的状态机,任务以 10ms 周期调度:

typedef enum { BAL_IDLE, BAL_CONDITION_CHECK, BAL_ACTIVE, BAL_HOLD, BAL_FAULT } bal_state_t; #define START_DELTA_MV 30 #define STOP_DELTA_MV 10 #define ACTIVE_WINDOW_MS 200 #define HOLD_WINDOW_MS 20 static bal_state_t g_bal_state = BAL_IDLE; static uint16_t g_window_cnt = 0; void bal_task_10ms(void) { switch (g_bal_state) { case BAL_IDLE: if (system_is_idle() && battery_temp_ok()) g_bal_state = BAL_CONDITION_CHECK; break; case BAL_CONDITION_CHECK: read_cell_voltages(&v1_mv, &v2_mv); if (abs((int32_t)v1_mv - (int32_t)v2_mv) > START_DELTA_MV) g_bal_state = BAL_ACTIVE; else g_bal_state = BAL_IDLE; break; case BAL_ACTIVE: bal_write_reg(BAL_REG_CTRL, BAL_CTRL_EN); /* 使能均衡 */ g_window_cnt++; if (g_window_cnt >= (ACTIVE_WINDOW_MS / 10)) { bal_write_reg(BAL_REG_CTRL, 0); /* 进入保持前先停均衡 */ g_window_cnt = 0; g_bal_state = BAL_HOLD; } break; case BAL_HOLD: g_window_cnt++; if (g_window_cnt >= (HOLD_WINDOW_MS / 10)) { g_window_cnt = 0; read_cell_voltages(&v1_mv, &v2_mv); if (abs((int32_t)v1_mv - (int32_t)v2_mv) < STOP_DELTA_MV) g_bal_state = BAL_IDLE; else g_bal_state = BAL_ACTIVE; } break; case BAL_FAULT: bal_write_reg(BAL_REG_CTRL, 0); /* 上报主机,等待人工确认后复位 */ break; } }

注意 BAL_ACTIVE 这个分支:它运行 200ms 后强制停止均衡,进入 20ms 的 HOLD 窗口。这个设计不是多余的。电感型变换器在停止开关后,残留的电压尖峰和振铃需要几个毫秒才能平息,HOLD 窗口就是给这些开关噪声一个“落地”的时间。在 HOLD 窗口里读电压,相当于在系统相对安静的时刻采样,才能拿到可信的数据。

4.3 测量避让:为什么不能边均衡边采样

这是整套方案里最容易被低估的细节。均衡芯片工作的时候,SW 节点在几十纳秒内完成一次电压跳变,产生的高频能量会通过空间耦合和地弹进入采样回路。如果 MCU 的 ADC 引脚走线离电池采样线比较近,读到的电压可能跳变十几甚至二十毫伏。我最初没有加 HOLD 窗口时,观察到一个现象:均衡启动后读到的电压差反而比实际更大,状态机不断延长均衡时间,而芯片自身的电压比较器却认为已经差不多了,两边对不上,整个闭环逻辑就乱了。

另一个叠加因素是 MCU 的 ADC 参考电压。板上的 3.3V 参考电源在均衡电流变化的瞬间会有轻微的下垂,虽然幅值不大,但会让 ADC 的量化结果整体偏移,进一步放大误差。HOLD 窗口同时解决这两个问题:停掉均衡,让 3.3V 稳定回来,再让 ADC 连续采样 16 次取平均,这样读到的电压波动可以压到 1mV 以内,状态机工作就稳定了。

5. 实测验证与踩坑记录

5.1 81mV 偏差的收敛过程

样机做好后,我做的第一项验证是人为制造一个不平衡状态,然后观察均衡效果。方法很简单:两块 50Ah 磷酸铁锂,先把其中一块单独多充 5% SOC,串成两节模组后实测压差约 81mV,随后让系统进入待机均衡模式,每 5 分钟记录一次压差和均衡电流。

时间 (min)压差 ΔV (mV)实测均衡电流 (A)
0811.15
15521.05
30290.92
60140.61
9060.30
12040.18

从数据能看出的规律很典型:压差越大,均衡电流越高;随着电荷逐步搬过去,电感两端电压差变小,功率自然下降,这符合电感型能量转移的物理特征。整个收敛过程大约是 110 分钟把压差从 81mV 拉到 4mV,比我预期的快,因为中间压差大的阶段电流一直维持在高位。

同时记录的温度数据也印证了主动均衡的效率优势:均衡期间芯片表面最高 42°C,电感 39°C,环境 25°C。同样的场景如果使用被动均衡,以 0.1A 的均衡电流处理 4Ah 的不平衡,按照 12.8Wh 发热量计算,电阻器表面温度轻松超过 90°C,而且需要 40 小时才能完成,两者完全不在一个量级。

5.2 三个踩得很深的坑

第一个坑是电感饱和。初期为了压低成本用了 4.7µH、饱和电流只有 1.6A 的叠层电感,结果在大压差启动瞬间,芯片直接报过流故障,还伴随尖锐的啸叫。原因是启动瞬间峰值电流超出饱和电流,电感量骤降到空气电感水平,电流失去限制之后瞬间激增。处理方式是换成 4.7µH、饱和电流 4.5A 的屏蔽绕线功率电感,啸叫消失,过流故障也不再出现。

第二个坑是 I2C 上拉拉错电压。第一次整板焊完调试,发现硬件 I2C 收不到 ACK,或者偶尔收到错乱的数据。用示波器量 SCL 和 SDA 波形,发现高电平被拉到了 5V。问题出在上拉电阻接到了板子的 5V 电源轨,而均衡芯片的 SCL/SDA 引脚最高只能承受 3.6V,5V 上拉等于把引脚强制拉到超范围电压,芯片内部的输入保护逻辑就开始捣乱。改成 3.3V 上拉后通信立刻恢复正常。这个教训总结成一句话:上拉电源必须与芯片 IO 逻辑电平一致,不能想当然接到系统电源。

第三个坑是采样线与功率回路共用。最初原理图设计时,芯片的 VBAT 和 GND 采样脚直接就近连在电池接线端子的同一块铜皮上,均衡电流经过这块铜皮时产生了 2~3mV 的压降,而且压降方向随均衡电流方向变化,导致电压读数来回抖动。改成从电芯端子上单独拉细线走到芯片采样脚之后,读数稳定在 1mV 以内。这个问题的本质是采样电流路径和功率电流路径没有分开,属于典型的 Kelvin 接法缺失。

5.3 批量阶段还需要注意的两个点

除了上面三个坑,产线验证阶段还会遇到两个容易被忽略的问题。一是芯片的故障锁存处理:芯片检测到过温、过流等异常后会进入锁存状态,单纯靠软件写控制寄存器无法恢复,必须通过 EN 引脚下电再上电才能复位。所以软件流程里要有读 FAULT 寄存器的步骤,而不是只会在主循环里盲发使能命令。二是虚焊导致的偶发 NACK:回流焊温度曲线不合适时,芯片引脚可能出现虚焊,I2C 通信表现为偶发超时或 NACK,这种问题在产线上非常难定位。我的处理是在出厂测试固件里加了一段连续读寄存器 100 次的压力循环,任何一次失败就判定不良品,至少能把虚焊板子拦在产线上。

这块板子的方案我后来又复制到了一个四串小型备用电源模块里,做法是用两片同样的均衡芯片分别处理两组两串电池,F411RE 用两路 I2C 分别控制,逻辑结构完全相同。实际跑下来,最明显的感觉是主动均衡方案的调试成本确实比被动均衡高不少,但一旦把状态机、测量避让、故障处理这三块理顺,后续几乎不需要干预,电池一致性维持得比预期好得多。如果你正在做类似的两串储能模块,我的建议是第一版样机就按“接线到位、软件留测量窗口、I2C 加重试”这三个底线来设计,能省掉后面一大半的排错时间。

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

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

立即咨询