“聊到BMS充电,很多刚入行的兄弟一上来就被GB/T 27930-2015那一堆报文名字砸懵了:CHM、BHM、BCP、CTS、CML、BRO、BCL、BCS、BEM……每个缩写好像都认识,串在一起完全不知道谁先谁后、谁该等谁、超时了怎么处理。这篇文章我就根据自己做BMS和充电桩联调的实际经验,把这套国标充电全流程从头到尾拆一遍,重点放在报文交互的时序、每个关键字节的判读方法、以及实车上容易踩的坑。适合做BMS底层软件、充电桩协议开发、以及整车充电系统测试的朋友参考,也适合刚入行的新人用来建立整体框架。”
1. 理解GB/T 27930-2015到底管了什么
1.1 协议定位:一段看似简单却决定充电成败的对话
GB/T 27930-2015是电动汽车非车载传导式充电机与电池管理系统之间的通信协议标准。所谓“非车载”,指的是充电机装在车外,比如直流快充桩;对应的“车载”充电机则是车上那个AC-DC充电模块,那个走的是另一套逻辑,不在这个标准范围内。
这套协议真正的本质,是BMS和充电机之间的一段握手-配置-充电-结束的对话。和人与人交流一样,双方要先确认“你听得见我说话吗”“你是什么身份”“你支持什么规矩”,然后才能进入正题开始充电,充完了还要体面地互相道别、统计电量。如果其中任何一句话没说清楚、超时没回应,整个充电过程就可能中断,甚至引发绝缘故障、继电器粘连等安全问题。
我见过不少刚接触协议栈的人,上来就抓着报文结构表背字节,却忽略了协议最核心的状态机。其实GB/T 27930-2015的精髓在于:它把整个充电过程严格划分成几个阶段,每个阶段规定了必须发送哪些报文、以什么周期发送、允许的响应时间是多少。只要状态机跳转逻辑正确,报文即使有小的解析偏差,也大多能兜住;反之,状态机一乱,整个充电流程直接崩。
1.2 为什么“报文时序”才是命门
协议原文里有大量的周期和超时参数。这些数字不是随便定的,每条都对应着一个真实的物理风险。比如低压辅助上电之后,BMS需要在规定时间内完成绝缘监测并发送BRM(电池铭牌报文),因为充电机要据此判断该车是否在自己支持的电压、电流范围内,超时就会认为BMS没有准备好,直接结束充电流程。
整车CAN网络上除了这套充电协议报文,还跑着很多其他报文,比如VCU的车速、扭矩、仪表信息。如果BMS的CAN收发器滤波配置得不好,或者总线负载率过高导致报文延迟,就可能出现充电桩侧超时误判。我实际排查过一起“充电10秒就中断”的问题,最后定位是CAN总线终端电阻虚接,导致边沿信号质量差,充电机偶尔收不到完整帧。
所以在读标准时,建议把每个阶段的时间约束整理成一张表,对照着看协议,而不是一头扎进字节定义里。后面我们逐段拆解时,我会把关键周期和超时阈值一并列出来。
2. 充电握手阶段:BMS与充电机的第一次对话
2.1 握手报文细节:CHM和BHM怎么互相认识
充电机插上枪、完成物理连接后,会先进行低压辅助上电,也就是通过充电枪的辅助电源引脚给BMS提供12V或24V电。BMS上电后开始周期性发送CHM(充电机握手报文),充电机则回应BHM(BMS握手报文)。这里有个非常容易误解的点:CHM虽然是BMS发出去的,但名字叫“充电机握手报文”,表示的是“BMS发给充电机的握手信息”;而BHM是“BMS握手报文”,却是充电机发给BMS的。
这个命名方式确实反直觉,我刚开始也经常搞混。理解它的关键是站在“报文内容描述的是谁”的角度:CHM里描述的是充电机编号、充电机类型,所以叫充电机握手报文;BHM里描述的是BMS版本号、BMS制造商,所以叫BMS握手报文。
CHM的周期是250ms,BHM也是250ms。BMS发送CHM后开始计时,如果在规定时间内没有收到BHM,就要进入故障处理。实际项目里这个超时一般设为1秒左右,也就是丢失4帧就判定异常。需要注意的是,BMS不能只在收到BHM后才发CHM,而是应该一直发送,直到完成握手并进入下一阶段。协议规定双方都需要连续正确收到对方的握手报文后,才能继续下一步,这种“互发互等”的机制是为了避免单方面误判。
BRM(电池铭牌报文)是握手阶段里信息量最大的一帧。它由BMS发送,周期250ms,里面包含了电池类型、额定容量、额定总电压、制造商、电池成组方式、电池组序号等关键参数。充电机会拿BRM里的额定电压和额定容量去和自身的输出能力做匹配:如果充电机最大输出电压低于电池额定电压,或者最大输出电流过小,就可能直接拒绝进入充电阶段。
配套的BRO(电池铭牌确认报文)是充电机对BRM的应答。它有两个关键值:一个表示“是否允许充电”,另一个表示“不充电的原因”。我遇到过一种情况:BMS发了BRM,充电机回了BRO,但里面的允许标志是“不允许”,于是BMS只能停在握手阶段反复重发BRM。查下来是BRM里的电池制造商编码填了一个保留值,充电机固件不认这个厂商ID,直接判为不支持的电池类型。
2.2 参数配置阶段:BCP、CTS与CML的你来我往
握手完成之后,双方进入参数配置阶段。BMS发送BCP(电池充电参数报文),周期250ms,里面包含了电池当前总电压、最高单体电压、最低单体电压、最高单体温度、最低单体温度、最高允许充电电压、最大允许充电电流、最高允许充电温度等关键限值。这些参数是充电机执行充电控制的基础依据。
充电机收到BCP后,会根据这些参数算出自己可以提供多大电压、多大电流,然后发送CTS(充电机参数确认报文)回应是否准备就绪,并告知BMS“充电机最大输出电压”“最大输出电流”“最小输出电压”等自身能力参数。如果BCP中的最大允许充电电压低于充电机的最低输出能力,或者最高允许充电温度过低,充电机无法满足时,CTS里的“是否允许充电”标志会置成不允许,同时附上原因。
在CTS之后,BMS还要发送CML(电池充电准备就绪报文),告诉充电机“我已经准备好,可以开始绝缘检测和继电器闭合了”。这里有个细节:CML里面有一个“BMS是否允许充电”标志,必须等BMS完成自检、继电器状态正常之后才能置位。很多BMS为了图省事,在参数配置阶段一开始就发CML置位,但此时电池组正极继电器还没断开预充电路,如果充电机恰好在这时执行绝缘监测,会检测到异常电压,导致绝缘故障报警。
我自己的做法是:把CML置位放到最后一步,确认绝缘监测完成、正负继电器均处于断开状态、接触器驱动电路无故障后,再发出。这样虽然多等了几个周期,但能显著减少充电启动阶段误报绝缘故障的概率。
2.3 绝缘检测与低压辅助上电的逻辑
绝缘检测本身是充电机执行的,不是BMS。充电机会在确认双方握手完成、收到BCP和CML后,对直流回路执行绝缘电阻检测。如果绝缘电阻低于标准阈值,充电机拒绝闭合输出接触器,并发送故障报文。BMS在这个过程中能做的,就是保证自己在合适的时间点“让开”——不要在充电机检测绝缘时,提前闭合车载继电器,把电池电压引到直流母线上。
低压辅助上电是个经常被忽视的环节。它发生在物理连接之后、CAN通信正式握手之前。BMS的CAN收发器和主控芯片靠辅助电源供电,因此BMS程序必须允许在上电瞬间就进入充电握手流程,而不是等待整车高压上电完成。有些车型的BMS上电需要等VCU的唤醒信号,导致充电桩已经发出握手报文时BMS还没起来,双方反复超时,最终充电桩报“BMS无响应”。这类问题在售后市场尤其多见,做乘用车BMS和商用车BMS的朋友都容易遇到。
3. 充电阶段核心报文与SOP计算
3.1 充电需求与充电机输出报文的配合
完成握手、参数配置和绝缘检测后,充电机闭合输出接触器,BMS和充电机进入正式的充电阶段。这一阶段最核心的报文是BCL(电池充电需求报文)和BCS(电池充电状态报文),两者都由BMS发送,周期都是50ms。
BCL里包含三个关键值:充电需求电压、充电需求电流、充电模式。充电需求电压一般取“电池当前最高单体电压 × 单体串联数 × 一个略大于1的修正系数”,再经过充电机能力上限截断;充电需求电流则由BMS的SOP(State of Power,可输出功率状态)估算模块输出,再叠加温度、SOC、单体电压的一致性修正。
BCS则是BMS把充电过程中的实际状态回传给充电机,主要包括电池组当前总电压、当前总电流、SOC、以及一个“剩余充电时间”的估算值。充电机拿到BCL后,会以“需求电压 + 需求电流”为目标,执行电压环和电流环控制;同时充电机自身也会周期性发送CCS(充电机充电状态报文),里面包含充电机输出电压、输出电流、累计充电时间等信息,供BMS监控充电机是否实际按需求输出。
实际联调中,我最常遇到的问题是BCL里的需求电流变化过于剧烈。有一次BMS的SOP模块在SOC 85%附近出现估算跳变,需求电流从100A瞬间降到40A,充电机来不及平滑跟踪,输出电流出现明显过冲,虽然没触发故障,但母线电压被拉出很大的纹波。后来在BMS软件里对需求电流增加了一阶低通滤波,同时限制了每个控制周期的变化率,问题就消失了。
3.2 SOP状态估算如何影响充电曲线
SOP估算直接决定BCL里的需求电流,是BMS充电控制中最有技术含量的部分之一。简单说,SOP要回答的问题是:在当前温度、SOC、单体电压、单体温度分布的情况下,电池还能安全地充进去多大的电流。
SOP计算的输入通常包括:
- 最高单体电压与最低单体电压:防止过充,通常用最高单体电压做上限约束,用最低单体电压做下限约束,两者差值过大时还要考虑限流。
- 最高/最低温度与温度变化率:低温时锂离子扩散速率慢,允许充电电流要显著降低;高温时析锂和热失控风险增加,同样要限流。
- SOC区间:低SOC时可以大电流充电,高SOC时恒流段缩短,恒压段拉长,需求电流要按电压窗口动态调整。
- 一阶或二阶RC等效电路模型的端电压预测:用当前电流估算若干秒后的端电压,确保不超过充电截止电压。
不同BMS厂商的SOP算法差异很大,有的用MAP表插值,有的用模型在线计算。但从GB/T 27930-2015的角度看,它只关心最终交给BCL的那个电流值是否合法、是否平滑。因此做协议栈时不需要关心SOP内部算法,但一定要设置合理的限幅和变化率限制,防止异常值直接通过BCL发给充电机。
BSM(电池状态信息报文)在充电阶段同步发送,周期250ms,里面包含电池组SOC、单体最高/最低电压、最高/最低温度、绝缘电阻估算值等。充电机会结合BSM的绝缘信息来做二次安全判断。如果BMS在充电过程中检测到绝缘电阻突然下降,应立即通过BEM发送故障报文,同时把BCL中的需求电流置为0。
3.3 充电机输出与电池状态的闭环监控
充电阶段不是BMS单方面发需求就完事了,还需要BMS持续监控充电机是否“言行一致”。
- BMS每个周期把BCS发送给充电机,同时每250ms上报BSM。
- BMS需要持续解析CCS,对比充电机当前输出电压是否接近BCL里的需求电压,当前输出电流是否接近需求电流,若偏差超过一定阈值且持续一段时间,需要主动降低需求或终止充电。
- 如果CCS显示充电机输出电压低于电池总电压,且电流方向反向,说明可能存在电流倒灌,BMS需要及时上报故障。
我之前排查过一个“充电中BMS偶发复位”的案例,公网CAN和充电CAN共用一路物理总线,充电桩每50ms发送CCS和CML,BMS自己的BMS状态报文也在同一个CAN口上往外发,总线负载一高,BMS主控的中断响应不过来,看门狗超时复位。后来把充电CAN单独拆出来,通讯才稳定下来。这也是很多商用车BMS在做整车CAN拓扑设计时容易忽略的点。
4. 充电结束阶段与故障报文处理
4.1 正常结束时的统计报文与继电器控制
正常结束有两种情况:BMS主动结束和充电机主动结束。
BMS主动结束通常是因为达到了截止条件,比如最高单体电压达到充电截止电压、SOC达到100%、充电电流降到截止电流。BMS需要发送BST(BMS终止充电报文),其中的“终止充电原因”要填准确:是“达到截止电压”还是“达到截止电流”,不同的原因对应充电机流程里不同的响应方式。充电机收到BST后,会停止输出并发送CST(充电机终止充电确认报文),BMS收到CST后断开充电继电器。
充电机主动结束一般是充电机检测到自身故障或收到了桩端的停止指令,它会发送CST。BMS收到CST后,也应断开继电器,并回发BST确认,然后双方进入统计阶段。
统计阶段的报文是BSD(BMS统计数据报文)和CSD(充电机统计数据报文)。BMS在结束充电后发送BSD,周期250ms,包含本次充电的累计充电时间、充入电量;充电机回应CSD,累计输出电量、充电时长等数据。整个充电流程到此结束,双方在完成统计数据交互后,退出通信状态。
实操中要注意一点:不要在BST里填一个空值或默认值就发出。充电机端的运维平台通常会记录终止原因,填错了会给后来排查问题的人造成误导。我见过一台车几乎每次充电都报“其他原因终止”,最后查BMS代码发现BST里的终止原因字段根本没赋值,这是个很低级但很常见的错误。
4.2 异常结束与BEM、故障报文的正确用法
异常结束是我工作中最常被拉去现场处理的情况,协议里的核心报文是BEM(BMS异常报文)。BEM只在BMS检测到故障时发送,里面包含故障等级和故障类型两个关键字段。
故障等级一般分为1级、2级、3级:1级最严重,要求充电机立即停止输出;2级要求限制输出;3级则是提示性告警,充电可以继续,但需要关注。BMS一旦发送了1级故障报文,还应当配合本地断开继电器操作,不能光发报文却不断开,否则万一充电机没有及时响应,就会造成过充风险。
BEM的故障类型字段是十六进制编码,不同的bit位代表不同故障,比如绝缘故障、继电器粘连、电池过压、电池欠压、过温、通信超时等等。我之前接手过一个项目,测试工程师反馈“BMS报了绝缘故障,但充电桩不认”,查下来是BEM中的故障类型编码和充电桩固件期望的不一致,双方参照的标准版本不一致——充电桩按GB/T 27930-2011的编码解析,BMS按2015版编码发送。所以联调前一定要先确认双方的标准版本和故障类型编码是否一致。
除了BEM,通信超时本身也是异常结束的常见原因。BMS发送BCL后如果连续多个周期没有收到充电机的CCS,需要主动判断通信超时。协议里对这个超时有一个推荐值:连续丢失50ms内的报文超过一定次数就判定超时。实际项目我喜欢用“每50ms周期连续丢失4帧”作为阈值,即200ms没有收到CCS就进入故障处理。太短容易误判,太长又起不到保护作用。
5. 实践中的常见问题与排查心得
5.1 三个最常见的“充电中断”现场
第一个现场:插枪后仪表显示“充电连接中”,半天没有进入充电。排查思路是先看CAN报文,CHM有没有发出来、BHM有没有回过来,再确认低压辅助上电是否正常。很多情况下是充电枪的CC/CP信号检测没通过,车端根本没有发送CHM。
第二个现场:充电启动后几十秒内电流掉为0,然后充电桩报“BMS通信超时”。这个要重点看BCL和CCS的周期是否稳定,CAN总线负载率是否过高。之前有一次就是总线终端电阻松动,导致波形边沿变差,高波特率下的误码率上升,BMS侧实际收到了报文但CRC校验失败,被当作丢帧处理。
第三个现场:BMS报绝缘故障但绝缘检测仪实测正常。这往往是BMS在充电机执行绝缘检测时提前闭合了继电器,把电池电压引到了母线上,充电机一测电压不对就报绝缘故障。解决方法是严格按照状态机时序,把CML置位放在全部就绪之后。
5.2 排查工具与个人经验总结
开发阶段使用PCAN或同类USB-CAN分析仪抓包,配合Wireshark的CAN插件或者周立功的CANPro也能解析部分协议。对于GB/T 27930-2015,建议自己写一个简单的DBC文件,把各报文和信号都定义好,抓包后直接换算成物理值,能省很多事。
我还习惯在BMS软件里加一个“充电状态打印”的调试接口,把当前状态机、收到的最后一帧关键报文、故障标志都打印出来。出了问题先看打印日志,再结合CAN抓包,基本能快速定位是协议状态机问题、信号解析问题,还是物理层问题。
软件层面,如果BMS的主控MCU资源足够,建议把充电协议栈做成独立任务,设置单独的CAN接收邮箱,避免被其他任务阻塞。我还建议在代码里增加一个“非法跳变保护”:即状态机不允许从“充电阶段”直接跳回“握手阶段”,必须经过异常处理或正常结束流程,防止意外重启后双方状态不一致。
6. 几个容易踩坑的细节补充
6.1 定时器与超时判定的实用建议
协议里有很多250ms、50ms的周期,以及各种超时阈值。写代码时建议用统一的软件定时器基准,不要每个模块各搞一套计时。我用的是1ms tick,所有报文周期和超时都通过计数器累积,代码里每个定时器单独变量,最后统一在一个时隙处理函数里检查。这个设计的好处是排查超时问题时只需要看一个入口。
还有一个容易忽略的点:BMS在充电过程中如果因为某些原因(比如休眠)导致CAN控制器关闭,重新唤醒后必须重新走握手流程,不能直接从断电位置恢复。我见过有BMS在唤醒后直接发BCL进入充电阶段,充电机还停留在握手阶段,两边状态不一致,最后只能拔枪重启。
6.2 结合BMS和BMU的分工来理解报文
网络热词里有人提到BMS和BMU的区别,这里顺便说一句。BMU(Battery Management Unit)通常指电池包内的采集单元,负责单体电压、温度采集和均衡;BMS则是整车层面的电池管理系统,负责SOC估算、SOP计算、继电器控制、热管理和充电协议。在GB/T 27930-2015的报文交互中,真正跟充电机通信的是BMS主机,BMU的数据经过内部通信汇总到BMS后,才能组装成BCP、BCL、BSM等报文。
所以如果测试时发现BCP里的单体电压数据不动,不要先怀疑充电桩,先看看BMU到BMS的内部通信是不是断了。很多时候整车CAN是好的,但电池包内部的菊花链通信失效,导致BMS拿不到单体数据,只能发极限值或者默认值。
6.3 关于标准版本与扩展
GB/T 27930-2015目前已是国内电动车直流充电领域的主流标准,但实际应用中有不少车型和桩企在2015版基础上做了私有扩展,比如增加预约充电、V2G相关报文。做协议栈时要注意,私有扩展的报文不能占用标准报文的帧ID和周期,否则会影响互操作性。
另外,如果要做出口项目或对标新国标,可能还需要了解GB/T 27930-2023的调整内容,但从存量市场看,2015版仍然是最需要吃透的版本。把2015版的状态机和报文细节搞明白,再去看新版本会轻松很多。我个人的建议是:新手先用手写报文的方式把整个充电流程完整跑一遍,不要完全依赖协议栈集成,这个过程对理解报文交互的帮助远比看十遍文档都大。
我最后分享一个习惯:每次做充电联调之前,先在CAN分析仪里录一段正常的、完整的充电报文作为“黄金波形”,后面不管是改BMS软件还是换充电桩,只要波形结构和这段对不上,就能快速定位差异。这套方法陪我排查了大大小小几十个充电问题,今天一并分享给你,希望你在面对GB/T 27930-2015那串报文时,也能少一点懵圈,多一点从容。