搞电池均衡的都知道,两串电池虽然数量少,但该出问题的时候一点不含糊。我之前在某项目里做过一套储能和备用电源的均衡方案,正好用了MP2642GR-Z这颗转换器和STM32F030RC单片机,把两节串联电池单元玩明白了。这套方案从头到尾都是自己搭的,从硬件拓扑、采样调理到均衡策略、联调避坑,有不少东西值得单独写一篇复盘,今天就把完整的技术细节和实操经验梳理出来,给做BMS、便携储能、备电设备的工程师一点参考。
先说清楚这套东西解决的是什么问题。两节锂电池串联,标称7.4V或6.4V,用在小型UPS、应急照明、便携基站备电里非常常见。电池出厂时参数再接近,用一段时间后容量、内阻、自放电率都会出现差异。充电时容量小的一节先到截止电压,放电时容量小的一节又先到欠压保护,整组电池的可用容量被最弱的一节锁死。差异一旦超过安全范围,轻则容量跳水,重则过充起火。均衡就是在电池之间搬能量,让两节电池的电压和荷电状态尽量保持一致。
下面我把这套从方案选型到软硬联调的全过程拆开讲。
1. 为什么两串电池也要专门做均衡
1.1 两串电池的真实痛点
很多人觉得两串电池简单,直接串联用不就行了,干嘛加均衡电路。实际跑过就知道,问题远比你想象的多。
我模拟过一个最典型的场景:两节标称2600mAh的18650电池,一节的容量是2600mAh,另一节因为循环次数多,实际只剩2400mAh。串联充满后按同样电流放电,到某一段,小容量那节电压会断崖式下跌,整组还没放出多少电,保护板就触发欠压保护了。然后每次循环,小容量那节都在满充满放,大容量那节一直处于浅充浅放,差异越拉越大,恶性循环。
再看电压层面。如果充电时两节电池压差是50mV,随着电量接近满充,电压曲线变得很陡,这50mV对应的容量差可能只有百分之几,但已经足以让一节先达到4.2V截止。假如压差到了200mV以上,那过充风险是实打实的,保护板如果只做总压保护而不做单体均衡,那颗高压电池离报废就不远了。
做备用电源的尤其要注意这个。设备在备用状态下长期浮充,电池一直承受微小的过充电流,如果没有均衡,某一节电压被顶到4.25V以上,电解液持续分解,鼓包只是时间问题。所以串联电池的均衡不是可选功能,而是保障安全和寿命的必需品。
1.2 被动均衡与主动均衡怎么选
主流的均衡方案分两类,被动均衡和主动均衡。
被动均衡的本质是"烧掉多余的电荷"。每节电池并联一个泄放电阻,单片机检测到某节电压偏高,就打开对应的MOS管,用几十毫安到几百毫安的电流把多余的能量变成热量放掉。优点是简单可靠,成本极低,但缺点是能量白白浪费掉,均衡电流一大发热就hold不住,而且它只能"削峰",不能把能量补给低压侧那节电池。
主动均衡则是在电池之间搬能量,把高压电池的电荷泵到低压电池里去。能量没有浪费,均衡电流也可以做得比较大,适合容量大、对效率有要求的场合。缺点就是电路复杂度高,成本上来一截。
具体到我要做的这个项目,要求是:
- 两节串联磷酸铁锂或三元锂,系统电压8.4V以内
- 均衡电流目标0.8A左右,收敛速度要快
- 静态功耗尽量低,备用电源场景要长期待机
- 板级空间有限,不能堆一大堆分立器件
列完这些需求,被动均衡基本可以放弃,0.8A的泄放电流在那么小的板子上散热根本吃不消。主动均衡方案里,可以用的有开关电容法和电感能量转移法。开关电容法结构简单,但均衡电流受电容容量和开关频率限制,做大电流比较吃力。电感能量转移法效率高、电流大,控制灵活,通过PWM控制功率级占空比就能调节搬运电流大小,是最合适的路线。
核心功率级我用的是MP2642GR-Z,主控选STM32F030RC。为什么不选更高端的芯片?因为两串均衡根本不需要那么强的MCU,F030RC是Cortex-M0内核,主频48MHz,内置12位ADC、多路定时器和DMA以及丰富的GPIO,资源完全够用,关键它便宜、供货稳定、功耗低,用在量产产品上综合成本优势明显。
2. 系统架构与核心器件定位
2.1 整体拓扑与能量流动
这套均衡系统的架构可以分成三块:功率级、采样调理、控制核心。我画一个简单的文字示意:
电池组正极 BAT+ |---[功率级:MP2642GR-Z + 电感 + MOS开关]---> BAT- | ↑ 控制PWM与使能 | STM32F030RC | ↑ ADC采样 |---[分压电阻+RC滤波]---> 单片机ADC |---[LDO供电]---> 3.3V 电池组负极 BAT-能量流动方向由单片机决策。当检测到B1电压高于B2超过阈值时,单片机控制功率级把B1的能量搬到B2;反过来B2高于B1,就把能量往B1搬。整个过程是一个双向的降压-升压转换,等效于在电池之间挂了一个自动调节方向和大小的"能量搬运工"。
MP2642GR-Z在这里不是简单做一个固定电压输出。它内部集成了同步开关管,具备高效率的功率转换能力,我在设计时把它当作可控功率级来用,通过外部反馈网络和单片机的PWM控制,可以调节它的工作状态,从而控制能量的流向和大小。
STM32F030RC负责采集电池电压、判断均衡方向、输出PWM和使能信号,以及处理各种保护逻辑。
2.2 MP2642GR-Z 在均衡电路里的角色
当初选这颗芯片,主要是看中它的三个特性。
第一是效率。同步整流结构,在轻载和中等负载下效率都能做到90%以上,这对均衡电路很重要。因为能量在电池之间搬来搬去,每多浪费一分,就多一分热量,尤其是备用电源长时间浮充,功率级如果低效,板子温升会很难看。
第二是外部元件简单。电感、电容、反馈电阻一接,功率级就能工作。内部开关管的导通电阻和驱动能力都设计好了,不需要外部再搭复杂的驱动电路,板子尺寸和物料成本都能压下来。
第三是使能和软启动控制方便。MCU可以直接控制它的使能脚,需要均衡时就启动,不需要时就完全关断,静态功耗几乎为零。软启动功能也能避免均衡启动瞬间的大电流冲击。
顺便说一句,如果你手里有类似规格的降压型同步转换器,不用纠结型号,只要具备以下条件就可以参考这套方案:输入电压范围覆盖电池组总压,集成同步整流,有使能脚,能通过外部反馈和PWM控制输出电压或电流。原理是相通的。
2.3 STM32F030RC 的资源盘点
STM32F030RC这芯片很多人熟悉,48脚的封装,64KB Flash,16KB RAM,主频48MHz。对均衡控制来说,几个关键资源我数一下:
- ADC:12位精度,16个外部通道,配上DMA可以连续采样多个电压点,不用CPU干预。
- 定时器:TIM1是一个高级定时器,带互补PWM输出,可以直接用来驱动半桥或者产生带死区的控制信号。
- GPIO:数量足够,接使能、LED、外部报警、通信接口都够用。
- 通信:带了I2C、SPI、USART,将来要接BMS上位机或者扩展显示面板都很方便。
均衡控制本质上是一个低速闭环,采样周期做到50ms到100ms就绰绰有余了。F030RC的48MHz主频跑这点算法绰绰有余,而且Cortex-M0内核的代码密度也高,用通用寄存器操作方式写,64KB Flash完全够装。
选它还有一个现实原因:在储能备电这类成本敏感的行业里,BOM成本压得很低,一颗F030RC比F103便宜不少,功能却不缩水。很多项目的BMS从控或者均衡子板用它都是这个考量。
3. 硬件设计与细节实现
3.1 电池电压采样与信号调理
采样是整个均衡系统最关键的环节,没有准确的电压数据,均衡策略就是空中楼阁。
两节串联电池有三个采样点:BAT-、中点M、BAT+。以BAT-作为系统地,中点电压约等于B1的电压,BAT+约等于两节电压之和。每节电池电压通过差分计算得到:V1 = VM - VBAT-,V2 = VBAT+ - VM。
单片机的ADC输入范围是0到3.3V,而电池电压最高能到4.3V甚至4.35V,所以必须先分压。我用的分压电阻比是2:1,也就是把电压衰减到原来的三分之二,这样4.35V对应2.9V,留了0.4V的余量。
分压后必须接RC滤波,截止频率我算了一下。
设计目标:对100kHz以上的高频干扰衰减30dB以上 取R=10kΩ,C=100nF 截止频率 f_c = 1 / (2πRC) ≈ 159Hz这样对PWM开关频率及其谐波有足够的衰减,给ADC的是一个很干净的直流信号。同时信号调理链路的输入阻抗不能太低,否则会从电池取额外的电流,所以我还在ADC引脚前面加了一级电压跟随器,用运放做缓冲,输入阻抗拉高到兆欧级别,分压电阻的精度选1%的金属膜电阻,基准用外部精密基准,把采样误差控制在±10mV以内。
这里特别提醒:MCU内部的ADC参考电压如果直接用VDD,VDD有一点波动就会直接影响采样精度。我实测VDD纹波在均衡启动时能到30mV,反映到采样结果就是最大十几毫伏的跳动,这对均衡阈值来说太大了。后来加了外部基准芯片,精度稳定在0.1%,问题立刻解决。
3.2 功率级与驱动电路
功率级我用了MP2642GR-Z配合外部电感、续流回路以及一组MOS开关来搬运能量。这里分享几个设计要点。
电感选型很关键。均衡电流设计目标是0.8A,电感饱和电流至少要留1.2倍裕量,也就是1A以上。磁芯我用的是铁硅铝功率电感,额定电流高、损耗低,体积适中。感值选了22μH,对应的工作频率设在300kHz左右。感值太小,纹波电流大,输出电流纹波会传导到电池上,影响采样和电池寿命;感值太大,响应变慢,体积也大。
开关频率是另一个需要权衡的点。频率高,电感体积可以缩小,但开关损耗和EMI都上升;频率低,损耗小但电感要加大。300kHz是一个均衡点,既控制了体积,又不会让功率级的温升太夸张。
驱动电路上,用定时器输出的PWM信号直接控制MP2642GR-Z的使能和反馈网络。注意PWM信号的电平要与芯片的逻辑电平匹配,如果芯片的逻辑输入阈值是5V,而单片机是3.3V输出,中间必须加电平转换。我这边因为选型时特意确认了兼容性,直接直连即可。
MOS开关管选择的是低压大电流的N沟道MOSFET,导通电阻在10mΩ级别,VDS耐压在30V,覆盖两串电池电压绰绰有余。栅极驱动电阻我用10Ω到22Ω,用来限制栅极充放电电流,降低振铃。
3.3 系统自身供电与保护
整个均衡板自身需要供电。最方便的就是直接从电池组取电,经过一颗低功耗LDO降到3.3V给单片机。待机时均衡不启动,功率级关断掉,整板静态电流实测只有几毫安,对备用电源的电池来说可以忽略。
硬件保护上我做了四层:
- 输入端串联一颗自恢复保险丝,电流超过阈值自动断开,防止功率级短路时烧电池。
- 电池正负极之间并联TVS管,吸收静电和浪涌,避免瞬态电压打坏半导体器件。
- 过压保护:单片机检测到任意一节电池电压超过4.25V,立即关断均衡功率级并拉低报警引脚。
- 过温保护:板上贴了一颗NTC热敏电阻贴在功率电感附近,当温度超过75°C时降额运行,超过85°C直接停机。
还有一点值得强调:虽然只有两节电池,但功率级的开关节点在PWM切换瞬间会有很高的dv/dt,容易通过空间耦合干扰ADC采样。所以我在PCB布局时把功率部分和采样部分做了明确分区,功率回路走底层大面积敷铜,采样走线走顶层并用地线包围,同时在功率级输出端增加一个陶瓷电容吸收高频噪声。
4. 软件框架与均衡策略
4.1 软件总体框架
单片机程序整体是一个状态机加主循环的结构。主循环每100ms执行一轮完整处理,包含采样、滤波、状态判断、控制输出、故障检测。这个周期对均衡控制来说足够了,毕竟电池电压本身变化很慢。
程序状态定义如下:
- IDLE:待机,压差正常,功率级关断
- BALANCE_TO_LOW:把高压侧能量搬到低压侧
- PROTECT:故障锁定,需要断电或按键复位才能解除
4.2 关键代码与算法实现
ADC采样的代码,我用DMA方式连续采集多个通道:
#define ADC_CH_BAT1 0 #define ADC_CH_BAT2 1 uint16_t adc_buf[2][32]; volatile uint8_t adc_dma_done = 0; void ADC_Init(void) { // 使能ADC和GPIO时钟,配置PA0、PA1为模拟输入 RCC->APB2ENR |= RCC_APB2ENR_ADCEN; RCC->AHBENR |= RCC_AHBENR_GPIOAEN; GPIOA->MODER |= GPIO_MODER_MODER0 | GPIO_MODER_MODER1; // 配置ADC为连续扫描模式,DMA循环传输 ADC1->CFGR1 = ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | ADC_CFGR1_CONT; ADC1->CFGR2 = 0; ADC1->SMPR = ADC_SMPR_SMP_7; // 采样周期拉长,提高精度 ADC1->CHSELR = (1 << 0) | (1 << 1); ADC1->CR = ADC_CR_ADEN | ADC_CR_ADSTART; }采样原始值要转换成实际电压。配合外部基准,转换公式为:
#define VREF_MV 3300 #define ADC_FULL_SCALE 4096 #define DIVIDER_RATIO 1.5f float adc_raw_to_voltage(uint16_t raw) { return (float)raw * VREF_MV / ADC_FULL_SCALE * DIVIDER_RATIO / 1000.0f; }不过我在实际代码里不会直接做浮点运算,而是全部换算成整数mV处理,避免Cortex-M0内核跑浮点拉低性能。
滤波部分我用了滑动平均加中值剔除。每100ms采一轮,保留最近32个采样值,先去掉最大最小值,再求平均:
uint16_t filter_voltage(uint16_t new_sample) { static uint16_t history[32]; static uint8_t index = 0; uint32_t sum = 0; uint16_t min_val = 0xFFFF, max_val = 0; uint8_t i; history[index] = new_sample; index = (index + 1) & 0x1F; for (i = 0; i < 32; i++) { sum += history[i]; if (history[i] < min_val) min_val = history[i]; if (history[i] > max_val) max_val = history[i]; } sum -= min_val + max_val; return (uint16_t)(sum / 30); }均衡策略用的是压差滞回控制。启动阈值50mV,停止阈值20mV,中间留了30mV的滞回带。为什么必须加滞回?因为如果没有滞回,压差在阈值附近波动时均衡会反复启动和停止,功率级开关频繁切换,干扰很大,还会损伤电池。加滞回后,启动后要等到压差降到20mV以下才停止,整个控制非常稳定。
#define BALANCE_START_MV 50 #define BALANCE_STOP_MV 20 uint8_t balance_state = 0; // 0=空闲, 1=运行中 void balance_update(int16_t diff_mv) { // diff_mv = V1 - V2,单位mV if (balance_state == 0) { if (abs(diff_mv) >= BALANCE_START_MV) { balance_state = 1; if (diff_mv > 0) { set_balance_direction(DIR_B1_TO_B2); } else { set_balance_direction(DIR_B2_TO_B1); } set_pwm_enable(1); } } else { if (abs(diff_mv) <= BALANCE_STOP_MV) { balance_state = 0; set_pwm_enable(0); } } }PWM占空比输出做了限幅处理,均衡电流与占空比成正比,但占空比不能一路加到满,否则电流脉冲过大,电感会饱和。我限制在最大80%的占空比,并且启动时用软启动斜坡,把占空比从10%逐步抬升到目标值。这样既保护了电感,也避免电流突变对电池造成冲击。
4.3 保护逻辑与故障处理
保护逻辑我融合在同一个100ms周期里。每次采样完毕后做一次全局健康检查:
typedef struct { uint16_t v_bat1_mv; uint16_t v_bat2_mv; int16_t temp_c; uint8_t fault_code; } system_status_t; void safety_check(system_status_t *status) { if (status->v_bat1_mv > BAT_OVP_MV || status->v_bat2_mv > BAT_OVP_MV) { enter_protect(FAULT_OVP); return; } if (status->v_bat1_mv < BAT_UVP_MV || status->v_bat2_mv < BAT_UVP_MV) { enter_protect(FAULT_UVP); return; } if (status->temp_c > OTP_TRIP_C) { enter_protect(FAULT_OTP); return; } }故障处理采用锁存机制。一旦进入保护状态,均衡停止、PWM关断、报警拉高,而且不会自动恢复,需要外部掉电或者人工复位。这是刻意的设计选择:电池安全场景宁可多一些人工干预,也不要让系统在故障未查明时反复尝试恢复。
我在联调时遇到过一个有意思的情况:软件刚烧进去时,系统一上电就进保护,看门狗也没触发。查了半天发现是ADC采样在系统上电瞬间还没有稳定,采样到了几个离谱的电压值。后来在ADC初始化之后加了一个500ms的稳定延时和连续5次采样的有效判定,才解决这个问题。这就是"软件保护"和"硬件电路"实际结合时才会暴露出来的细节。
5. 联调过程与实测记录
5.1 上电自检与基准校准
硬件焊接完成后不要急着接电池,先用直流稳压电源模拟电池电压做基本验证。
我当时的步骤是这样:
- 直流电源输出设为8.4V,串一个100Ω限流电阻接到板子的电池端。
- 上电后测量LDO输出,确认3.3V正常。
- 用万用表测量三个采样点的分压后电压,和单片机读到的ADC值换算结果对比。
- 手动往单片机里烧一个测试固件,固定输出PWM使能信号,用示波器看功率级开关节点波形,确认频率和占空比正确。
- 校准环节:用精密直流电源分别给B1和B2模拟几个特征电压点,比如3.0V、3.6V、4.2V,记录ADC原始值和实际电压值,算出增益和偏置误差,写入校准参数区。
校准这一步特别重要。虽然理论上电路设计误差只有1%左右,但实际焊接、基准漂移、走线压降都会引入额外误差,不做校准最多能差到50mV以上。我在量产版的产线上也保留了校准步骤,每块板子都要跑一遍电压校准,大数据统计下来的最大偏差可以做到±10mV以内。
5.2 均衡实验数据与处理
系统调试通过后,我搭了一个完整的电池测试平台:两节18650磷酸铁锂电池,用充放电柜把B1充到3.55V,B2放到3.30V,模拟一个250mV的初始压差,然后启动均衡。
记录的部分数据如下:
| 时间(min) | B1电压(V) | B2电压(V) | 压差(mV) | 均衡电流(A) |
|---|---|---|---|---|
| 0 | 3.550 | 3.300 | 250 | 0.78 |
| 5 | 3.538 | 3.314 | 224 | 0.76 |
| 15 | 3.505 | 3.352 | 153 | 0.75 |
| 25 | 3.472 | 3.390 | 82 | 0.72 |
| 32 | 3.451 | 3.427 | 24 | 0 |
| 40 | 3.450 | 3.432 | 18 | 0 |
从实测看,250mV的压差在32分钟内收敛到24mV以下,达到了停止阈值。整个过程中均衡电流基本稳定在0.75A附近,后段因为压差变小,电流自然下降,这和理论分析一致。均衡完成后,两节电池的电压基本一致,系统进入待机,静态电流降到几毫安。
温度表现方面,室温25°C下连续均衡30分钟,功率电感表面温度升到40°C左右,功率级芯片温升约15°C,手摸只有温热,不需要额外散热片。
效率计算了一下:均衡过程实际搬运的电量约等于电压差乘以搬运电荷量,考虑到转换损耗,能量转换效率估算在88%左右。这在主动均衡方案里是一个不错的水平。
5.3 调试中踩过的具体问题
联调过程中遇到了几个让我印象深刻的坑,这里详细说说。
第一个是ADC采样受PWM干扰。现象是均衡一启动,单片机读到的电压就开始跳,最大跳了40mV,均衡策略跟着乱跑,频繁切换方向。排查思路:先看采样电路滤波是否足够,再看PCB布局,最后发现是功率级的地线走线和采样地线共了一段铜皮,PWM电流在这个公共阻抗上产生了压降。解决办法是把功率地单独走线,在电池负极端子处单点汇合,同时把采样RC滤波的截止频率从159Hz降到79Hz,问题彻底消失。这种现象在电源和MCU混合设计里非常常见,调试时一定要优先怀疑地线。
第二个是均衡电流上不去。设计目标0.8A,实际只能到0.4A。开始怀疑电感饱和,换了一个大体积电感没改善。后来用示波器看开关节点波形,发现关断瞬间振铃特别严重,说明驱动关断速度不够快,或者死区时间过长。调整栅极驱动电阻从22Ω改到10Ω,同时把定时器的死区时间缩短,均衡电流马上恢复到0.75A。电流上不去的根源往往不是电感容量不够,而是开关效率被拖累了。
第三个是软启动还是引入了过冲。我在程序里设置了软启动斜坡,占空比从10%慢慢往上加,但实际测试发现启动瞬间电流还是会突然冲到1.2A。后来想明白了:软启动时电感电流建立需要时间,如果上一个均衡周期结束时电感里还残留磁能,下一个周期一开始就容易过冲。解决办法是在停止均衡时先让PWM占空比平滑减到0,而不是直接关断,保证电感电流彻底归零后再休眠。这也算是一个经验积累。
6. 常见问题速查与避坑清单
6.1 常见问题速查表
| 现象 | 可能原因 | 排查方法 | 解决办法 |
|---|---|---|---|
| 采样电压跳动大 | 地线公共阻抗、滤波不足 | 用示波器测ADC引脚纹波 | 功率地单点汇合,降低RC截止频率 |
| 均衡电流偏小 | 驱动不足、电感饱和 | 看开关节点波形、测电感温度 | 调栅极电阻、换饱和电流更大的电感 |
| 均衡启动即过流 | 电感残留能量、软启动过短 | 抓启动瞬间电流波形 | 延长软启动斜坡,停止前先降占空比到0 |
| 均衡方向频繁切换 | 无滞回、阈值太小 | 看压差实时曲线 | 增加滞回带,阈值适当调大 |
| 上电自动进保护 | ADC未稳定、基准未建立 | 检查上电时序波形 | 初始化后延时,增加采样有效判定 |
| 静态功耗偏高 | LDO待机电流大、功率级未完全关断 | 用功耗仪测各支路电流 | 确认使能脚电平,选低静态电流LDO |
这六类问题基本覆盖了我见过的大部分两串均衡调试场景,照着查,大多都能快速定位。
6.2 我个人的几条实操心得
均衡方案做了几个版本之后,有一些心得是文档和规格书里学不到的,这里一并写出来。
项目里如果条件允许,把采样基准和分压电阻都留出校准点。我在板上留了一个测试焊盘,产线上用自动化设备自动烧录校准系数到Flash末尾区域,比出厂后才发现单板偏差再返工要省太多事。
均衡策略不要只看电压差,还要参考电池的SOC区间。磷酸铁锂的电压曲线中间段非常平,可能SOC差到20%,压差才几十毫伏。只用压差判断,在平台区会错过很多真正的失衡。我当时做的是先判断电池处于哪个SOC区间,在平台区优先用开路电压法或者库仑计辅助修正,在电压陡峭区再用压差法,两者结合判断效果明显更好。
另外,均衡电流不是越大越好。大电流意味着电感、开关管、线路都要承受更高的应力,发热也更大,板子稍微设计紧凑一点就容易热积累。我实测下来,0.5A到1A的均衡电流对18650这类电池来说很合适,既能在一个小时内完成压差收敛,又不至于让板子温度失控。想要更高均衡电流的,建议先做热仿真再上板。
最后说一个扩展点。这套方案虽然只做了两串,但架构是可以往上推的。如果要做四串、八串,硬件上主要是增加采样通道和开关矩阵,软件上把状态机改成多通道轮询,均衡策略升级成"选出最高电压和最低电压,两者之间搬能量"即可。MP2642GR-Z继续当功率级,STM32F030RC如果接口不够用就换F103或者G0系列,整体代码架构不用大改。
我实际用这套思路做过四串的变体,效果同样稳定。所以如果你正在做两串或者更多串的均衡控制,这套从芯片选型到软件策略的复盘可以直接复用,至少能帮你少走一半弯路。