两串锂电池有源均衡模块设计与实现:基于MP2642与PIC18的飞行电容方案 前阵子帮某公司的备用电源模块做BMS改进电池包是两串18650锂离子标称7.4V应用场景是应急照明、路由器小UPS这类长时间挂在待机电量上的设备。新需求听起来不复杂待机时自动把两节电芯的电压差均衡到20mV以内不能靠电阻发热硬耗还得能通过串口把状态上报出来。我最终用MP2642GR-Z搭均衡功率通道、用PIC18F47J53做采样和状态机把两串电池的均衡做成了一块独立小模块。这篇完整记录从选型、硬件、固件到调试踩坑的过程重点是讲清楚每一步为什么这样做以及那些常规文档里不会写的细节。1. 需求拆解两串电池的“均衡”到底在平衡什么1.1 串联电池为什么会失衡两节电池串联以后回路电流处处相等理论上它们应该同步充放电但实际电芯之间的差异会随着循环次数被不断放大。原因主要有四个制造本身的容量公差、内阻差异、自放电率差异、以及电芯所处位置的温度差异。这几个因素叠加以后就会出现在同一套串联回路里一节电芯还有不少余量另一节却已经先到截止电压的情况。充电端的问题最明显。两串电池共用一个充电器充电器检测的是总电压。高电压那节已经到4.2V了低电压那节可能还只有3.9V但充电器看总电压8.1V不到8.4V就会继续充结果就是高节长期处于过充边缘低节长期充不满。放电时反过来容量差导致低节先到保护电压整包容量被最短的那块板子卡死。这是串联电池系统容量衰减和安全隐患的头号来源。备用电源场景比动力电池更隐蔽大部分时间系统都挂在浮充或涓流状态偶尔才真正放电。电芯之间的差异不会像电动车那样快速爆发但几个月下来电压差能拉到一两百毫伏。我们拆过几组旧模块最严重的一组两节电芯静态电压差到了180mV整包的有效容量只剩标称的六成。1.2 备用电源场景对均衡的特殊要求备用电源的均衡和动力电池的逻辑不太一样。动力电池讲究大电流、快转移最好能在行驶或充电的间隙就把压差抹平。备用电源不一样它不缺时间缺的是稳定和低干扰。模块常年带电待机均衡器最好满足几个条件均衡过程不能产生明显的热热点否则影响设备长期可靠性均衡电流不需要很大几十毫安级别就够用关键是可持续均衡动作不能干扰主控采样和通信避免电压跳变把系统搞得误动作均衡目标电压要设置合理不能把低节电芯硬顶到超过安全上限另外一个容易被忽略的点是备用电源的充电机会间歇性工作均衡器必须在充电停止的空窗期也能独立运转否则均衡周期会被切得七零八落。这意味着均衡系统一定要自带完整的判断和控制能力不能只依赖外部充电机的管理逻辑。1.3 为什么我放弃了被动均衡被动均衡的原理很直白把高电压那节电芯并联一颗功率电阻让多余能量以热量形式耗散掉。成本低、逻辑简单很多BMS保护板就是用这招。我一开始也试过用一颗5欧的功率电阻配PWM控制均衡电流大概能到300mA。实测发现几个硬伤。首先是热量。300mA在5欧电阻上是0.45W的发热板子小的话几颗电阻就是局部热源长期待机时对旁边电芯的温度影响很不友好。其次是速度被动均衡在充电末期才有效而且电阻一直耗的是高节电芯的能量如果充电机不工作高节电芯很快会被拖到正常电压以下搞出新的失衡。第三被动均衡天生只能“耗高不补低”两个电芯都低于理想电压但压差不大时它毫无作为。备用电源需要的是把能量从高节搬去低节的有源方案而不是烧掉。2. 方案选型MP2642GR-Z 与 PIC18F47J53 的分工2.1 选型逻辑功率通道与控制核心分离均衡系统本质上解决两个问题一是判断该往哪节电芯搬能量、搬多少二是把能量实际搬过去。我习惯把这两件事拆开分别交给不同器件这样调试时能独立验证。PIC18F47J53负责判断。它是一颗8位单片机128KB Flash对均衡程序来说非常宽裕自带12位ADC采电芯电压的精度足够内部振荡器跑满后连外部晶振都省了串口上报也直接复用外设。我的任务简单说就是读电压、算压差、按状态机切开关顺便把日志通过UART发到调试工具。MP2642GR-Z负责搬能量。这是一颗集成同步整流的降压转换器工作电压范围覆盖两串锂电池包6V到8.4V的区间输出通过反馈电阻可调带软启动和使能引脚非常适合被单片机直接当做一个受控电源来用。实际方案里它专门负责把电池包的电压降到一个设定的目标电压比如4.3V给后面的储能电容充电。不需要它承担太多花哨功能稳定、可关断、能限流这就是全部要求。这种选型思路有一个额外好处均衡功率路径和控制逻辑完全隔离。即使单片机程序有Bug导致开关切错MP2642这一级还有独立的过流保护而且切换瞬间只需关掉EN就可以停掉能量搬运调试安全很多。2.2 均衡拓扑选择飞行电容法为什么适合这个场景两串均衡的经典拓扑有好几种。双向电感均衡效率高、电流能力大但需要两对功率管和一个能双向工作的电流控制环固件复杂度明显上升。反激式变压器隔离好也能将能量搬运到任意电芯但变压器体积和成本对一块小板子来说不太划算。我最后选了飞行电容法也叫开关电容均衡法核心思路是用一颗大容量电容当临时能量仓库反复执行“充电—投切—放电”的循环。飞行电容法最大的优势是天然解决了接地参考问题。上一节电芯的正极是电池包最高点下一节电芯的负极是电池地它们的地参考不同。如果用普通降压电路直接跨接在任一节电芯两端参考电位很难处理。飞行电容在充电时由MP2642供电投切时整个电容两端的电压是“浮起来”的它可以被开关矩阵接到上节电芯两端也可以被接到下节电芯两端。控制上只需要保证充电和投切两个阶段严格错开就不会出现共地冲突。这个方法还有一个工程上的好处所有关键节点都能直接用示波器观察。电容两端电压、四颗开关的栅极波形、电池电压变化全部可以看到调起问题来比反激变压器直观得多。2.3 系统框图与能量转移计算整个系统可以分成几块来说明。电池包两端接到模块输入端MP2642从电池包取电输出经过预充电阻给飞行电容充电。飞行电容两端通过四颗MOS组成的开关矩阵可以被投切到任意一节电芯的两端。PIC18F47J53负责采集两节电芯电压和飞行电容电压对比压差后决定当前该给哪节电芯补充能量并让开关矩阵执行投切。能量转移的计算方式很简单E 0.5 × C × (V充电完成² − V电芯当前²)我用的飞行电容是两颗2200µF低ESR电解电容并联等效约4.4mF。假如电容充到4.3V电芯当前电压4.0V单次投切换取的储能就是0.5 × 0.0044 × (18.49 − 16.00) 5.48mJ一次完整循环充电加投切大概需要500ms平均搬运功率约11mW。虽然数字不大但24小时累计下来大约能搬0.26Wh折合到4V电压下大概是65mAh对一个待机时漂移到几十毫伏压差的两串包来说完全够用。这套方案的本质是“细水长流的维护型均衡”正好契合备用电源的时间充裕属性。3. 硬件设计采样、功率通道与开关矩阵3.1 电压采样与校准12位ADC的精度陷阱电芯电压测量是整个系统的基础做不准后面全是白费。两串电池只需要测两个点电池包正极VTOP和中间点VMID代码里相减得到两节电芯电压。每个采样点用两颗电阻分压把最高4.5V左右的电压映射到ADC可接受的范围。分压电阻我选的是0.1%精度的低温漂型号不要为了省几毛钱用1%后面校准会补得很痛苦。分压之后经过一级运放跟随器再进ADC引脚。运放不是必须的如果MCU的ADC输入阻抗足够高可以直接采但我还是加了因为分压网络的输出阻抗会影响采样保持电容的建立时间加一级跟随后采样结果稳定很多。每个ADC引脚附近放100nF和10nF两颗电容滤掉高频开关噪声。采样引脚上再串一颗1k电阻防止异常时外部电压倒灌损坏引脚。固件里做两点校准用高精度电源分别给采样通道加1.000V和4.200V采集原始ADC码算出每通道的增益和偏移存进Flash。实测校准以后全量程误差可以压到±3mV以内。注意校准之后千万别换分压电阻换了必须重做我吃过这个亏。3.2 MP2642GR-Z均衡电源通道的配置MP2642的输入直接接电池包两端输入电容用两颗22µF陶瓷电容紧贴芯片引脚摆放这是降压转换器稳定工作的基本前提。反馈电阻网络把输出电压设定在4.30V这个值比电芯最高电压4.2V高出一点留出足够的充电压差又不至于每次搬运都把电容打到太高电压。如果之后换用磷酸铁锂电芯只需要改反馈电阻把目标电压调到3.65V附近即可。EN引脚接PIC的普通IO口固件控制均衡时置高不需要均衡时拉低整条功率路径彻底关断。软启动引脚加上合适电容让MP2642在上电时输出坡度平缓上升。这里有个细节飞行电容初始是完全没电的如果不做任何限制直接让MP2642输出给电容充电瞬间浪涌电流会非常大可能触发芯片过流保护甚至把输入端的电池包电压拉出明显塌陷。我在MP2642输出和飞行电容之间串了一颗0.5欧的预充电阻把充电峰值电流限制在安全的范围内代价是充电时间稍长但换来的是系统稳定。充电阶段MP2642工作在恒压状态。刚开始电容电压低电流大随着电容电压接近4.3V电流自然减小整个过程不需要专门的恒流环路。3.3 四开关飞行电容矩阵的设计与驱动飞行电容的投切需要四颗开关布局如下两颗管接电容正端分别能接到电池包正极VTOP和中间点VMID两颗管接电容负端分别能接到VMID和电池地GND。投给下节电芯时导通电容正端到VMID、电容负端到GND投给上节电芯时导通电容正端到VTOP、电容负端到VMID。这样四颗管子刚好覆盖两种投切组合。驱动上我用了高边P管加低边N管的组合简化了电平转换问题。P管栅极用一颗小信号N管去拉单片机IO口控制N管即可。开关管的耐压选25V以上导通电阻要小因为虽然平均均衡电流只有几十毫安但投切瞬间电容放电的峰值电流可能到一两安培。栅极驱动电阻不能省不然开关过程振铃会很难看。软件上必须强制互锁任何时刻都先关断全部四颗开关等足够长的死区时间再导通目标组合。如果出现交叉导通等于把电容直接短路轻则炸开关管重则电芯短路保护。下面的固件状态机里我会专门讲这个时序。3.4 供电树与整板保护主控用的3.3V电源没有从MP2642的输出取而是单独用了一颗低压差稳压器从电池包供电。这么做的原因很简单均衡动作时MP2642的输入电流会周期性变化如果主控和它共用一条电源路径采样精度会受影响。分开供电以后均衡开关引起的电池电压微跌就不会传导到ADC参考电压上。整板保护方面输入端加了反接保护和一颗慢熔保险丝电池包正常工作时绝不会反插但维修时总有人会犯这种错误几毛钱换一块板子不值得。后端加了TVS管防浪涌两串电池的储能密度不算特别高但均衡开关的感性负载切换会产生尖峰TVS管能兜底。主控IO口到功率部分的信号线上都加了串联电阻防止功率侧的异常电压反馈到IO口造成单片机损伤。4. 固件实现状态机与均衡算法的细节4.1 采样滤波与电芯状态判定ADC采样看似简单实际坑很多。均衡开关动作时电流突变电池电压会有短暂波动这时候采样必踩坑。我的做法是定义一个明确的采样窗口均衡投切结束后等150ms让所有瞬态平息再开始采。每个采样周期内连续采20个点去掉最大和最小值剩下18个取平均这一套组合拳能把随机噪声压得很干净。两节电芯的电压按VTOP减VMID、VMID减GND分别算出来。还要把MCU内部基准电压也采一遍用来修正VDD波动带来的误差这一步对长期漂移非常有效。电芯状态判定不只是看绝对电压还要看电池包总电压是否在合理区间。电池包总电压低于6.0V或者高于8.4V时整套均衡逻辑直接禁用防止在异常状态下强行搬运能量。这个判定每个循环都做不信任上次的判断结果。4.2 均衡状态机的四个阶段固件核心是一个四状态状态机空闲、预充电、投切、稳定。空闲状态下系统只采样不动作对比两节电芯压差预充阶段打开MP2642的EN让飞行电容充到目标电压投切阶段先关MP2642、关闭全部开关、等待死区再导通目标电芯对应的组合让电容能量灌进去稳定阶段关闭所有开关等待电压回落然后回到空闲循环。typedef enum { BAL_IDLE, BAL_PRECHARGE, BAL_XFER, BAL_SETTLE } bal_state_t; void bal_loop(void) { switch (bal_state) { case BAL_IDLE: measure_cells(); if (should_balance()) { bal_charge_on(); bal_state BAL_PRECHARGE; } break; case BAL_PRECHARGE: if (cap_voltage() CAP_TARGET) { bal_charge_off(); bal_switches_off(); delay_us(DEAD_TIME); bal_switches_select(bal_target_cell); bal_state BAL_XFER; } break; case BAL_XFER: if (cap_voltage() bal_target_cell_voltage() 20) { bal_switches_off(); bal_state BAL_SETTLE; } break; case BAL_SETTLE: delay_ms(150); bal_state BAL_IDLE; break; } }死区时间我取200µs保证四颗开关彻底关断、电容和任何节点都断开之后才导通目标组合。投切结束的判据是电容电压降到接近目标电芯电压说明能量已经基本放完。这时候关断全部开关再进入稳定期避免电容残留电荷在下一轮充电前引起误判。4.3 均衡结束条件与迟滞窗口均衡不能一直跑必须定义清晰的结束条件否则系统会陷入“压差波动—反复均衡—再波动”的循环。我设计了三个条件压差进入10mV以内即停止这个精度对备用电源足够低节电芯已经抬升到设定目标默认4.18V留一点缓冲避免充到4.20V触发过充保护时停止防止均衡器变成隐形过充器连续均衡总时间超过预设的运行配额也强制停止避免电芯异常时无谓地反复搬运能量。启动阈值和停止阈值做成了迟滞窗口压差超过25mV才启动均衡压差降到10mV以下才停止。中间这段死区保证开关不会频繁启停。均衡运行配额我设成“运行时间不超过总时间的50%”给电芯留出静置和电压回弹的时间。这些参数在实际调试中都值得用几个晚上慢慢磨启停太频繁会造成开关管和电容的额外损耗。5. 调试实录从台架到实包的踩坑过程5.1 台架搭建与初始测试调试第一步不是直接上整包电池而是用两台可调电源串联模拟两串电池。一台设为4.20V模拟高节一台设为3.85V模拟低节这样压差固定、内部功耗可控遇到问题不会把电芯搞坏。模块通过USB转串口工具连接到电脑实时看日志。示波器探在飞行电容两端和开关栅极观察每个阶段的波形。初始上电就遇到一个现象MP2642输出不稳定一会正常一会打嗝。查了一圈发现是预充电阻选太小电容初始充电电流太大触发了芯片限流。把0.5欧串上去以后波形立刻正常。这一步验证了前面的设计判断也说明调试台架的重要性——如果是拿真实电池组调试这种限流打嗝可能直接引起电池保护板误动作。5.2 典型测试数据与日志分析台架稳定后我记录了长时间均衡的数据。初始状态是V14.183V、V23.921V压差262mV。均衡启动后低节电芯电压缓慢上升高节电芯因为要给飞行电容充电也略有下降两者相向而行。四个小时后的典型结果如下时间V1高节V2低节压差状态0分钟4.183V3.921V262mV均衡中60分钟4.151V3.963V188mV均衡中120分钟4.111V4.012V99mV均衡中240分钟4.058V4.049V9mV已收敛这里有个现象值得解释高节电芯电压也在下降因为飞行电容充电时MP2642是从整个电池包取电而电池包的正极在高节电芯这一侧等效于高节电芯也在持续放电。最终两节电芯向着中间的电压值靠拢而不是单方面抬高低节这正是均衡该有的效果。日志里每行包含时间戳、两节电压、压差和当前状态码方便后期用脚本画趋势曲线。完整的UART日志片段类似T0000 V14.183 V23.921 dV262 STXFER T0100 V14.151 V23.963 dV188 STXFER T0200 V14.111 V24.012 dV99 STXFER T0400 V14.058 V24.049 dV9 STIDLE实测均衡过程正常板温升稳定在6°C左右对备用电源外壳内的小空间完全可接受。整板静态功耗约5mA待机时也不会对电池包造成明显负担。5.3 三个让我印象深刻的坑第一个坑是飞行电容投切瞬间的电压跌落。第一次实包测试时投切瞬间低节电芯电压被拉下去一大截甚至误触发了一次欠压报警。示波器一看是电容放电电流太大在电芯内阻上产生了不小的压降。解决方法是控制投切前的电容目标电压不要过高同时把预充过程做慢一点让电容电荷相对“温和”地灌进电芯。第二个坑是ADC采样被开关噪声污染。投切瞬间开关管栅极驱动会向控制地注入一段干扰即便采样窗口避开了投切时刻传感器节点上的残影也会让某个值偶尔跳变。我加了软件上更严格的丢弃机制投切后至少跳过三个完整采样周期才允许刷新电芯电压缓存。第三个坑是校准参数漂移。一开始分压电阻用了1%精度校准完的第二天再测误差又回到20mV以上。根源是电阻温度系数不一致电芯工作温度稍微变化分压比值就变了。全部换成0.1%、低温度系数的电阻后再校准误差连续一周稳定在±3mV以内。这个教训让我明白了精密测量回路里元件选型比算法更有决定权。6. 常见问题速查与后续扩展6.1 常见问题排查表现象可能原因解决办法均衡启动后压差长时间不降飞行电容容量太小、目标电压设置偏低、均衡配额限制过短加大电容容量、调高电容目标电压、放宽运行配额MP2642发热明显预充电阻太小导致充电电流过大增大预充电阻或降低开关频率飞行电容电压充不上去反馈分压错误、EN未拉高、软启动电容过大检查反馈网络、测量EN电平、调小软启动电容投切瞬间开关管损坏死区时间不足出现交叉导通延长死区到200µs以上检查栅极驱动波形采样电压周期性跳动采样时刻和投切时刻重叠采样窗口避开投切增加中值滤波长期浮充后压差依然很大均衡电流太小维护速度赶不上漂移速度升级电感拓扑提高搬运功率最后这一条尤其值得认真对待。飞行电容方案做维护型均衡够用但如果系统经常深度放电、电芯漂移速度很快就需要更大功率的搬运途径。6.2 后续扩展方向要把这个方案提升到更高功率最自然的路线是改成双向电感均衡用两颗半桥开关加一颗电感替代飞行电容PIC18F47J53的PWM模块直接输出占空比控制搬运功率能提升一个数量级。MP2642在这个升级里仍然有用可以继续承担主控电源和预充电的职责。如果从两串扩展到四串或更多串飞行电容的开关组合会几何级增加这时候更合理的是改用反激变压器或者逐个电芯扫描的思路。不过控制核心PIC18F47J53仍然够用因为均衡本质上依然是“测量、判断、搬运、安全”这条链路的反复执行。另外MP2642的反馈分压网络可以改成数字电位器或DAC驱动的形式让目标电压可以在固件里按不同电芯化学体系动态调整灵活性会大很多。我在这个项目里最大的体会是两串均衡虽然电路规模不大但“测量准、判断稳、搬运可控、保护到位”四个环节一个都不能少。飞行电容拓扑胜在没有复杂的电流环任何一环都能用示波器和日志直接验证。对备用电源这种时间充裕、稳定优先的场景来说它虽然不是性能最强的方案却是容错最好、最容易被调出来的方案。这套逻辑打通以后后续换电感拓扑、扩串数、加通信都只是在既有骨架上的自然延展。