第2章:CAN通讯基础
大家好,我是老张。今天咱们聊聊CAN通讯。说实话,做VCU和BMS的协同控制,CAN总线是绕不开的坎。我记得刚入行那会儿,被CAN报文折腾得够呛——明明看着数据发出来了,ECU就是不认。后来才发现,是帧格式选错了。
这一章,我会把CAN总线的物理层、数据链路层、报文格式和仲裁机制讲透。嗯,都是实战中必须掌握的东西。
2.1 CAN总线物理层
先说说物理层。说白了,就是信号怎么在线上跑。
CAN总线用两根线:CAN_H和CAN_L。平时两根线电压都是2.5V左右。发显性位(逻辑0)时,CAN_H拉到3.5V,CAN_L降到1.5V,差分电压2V。发隐性位(逻辑1)时,两根线回到2.5V,差分电压0V。
关键参数:
- 总线电平:显性0V(逻辑0),隐性1V(逻辑1)——注意,这是反逻辑
- 最大通信距离:40m @ 1Mbps,1000m @ 50kbps
- 终端电阻:120Ω,总线两端各一个
我遇到过一个问题:某次台架测试,BMS老是丢帧。查了半天,发现终端电阻焊错了,用了100Ω。换回120Ω,问题消失。所以啊,终端电阻别马虎。
2.2 数据链路层
数据链路层,负责把物理层的信号组织成有意义的报文。CAN的数据链路层包含几个关键部分:
- 帧起始(SOF):1个显性位,告诉所有节点“我要发数据了”
- 仲裁场:包含ID和RTR位,决定谁有优先权
- 控制场:包含IDE位和数据长度码(DLC)
- 数据场:0-8字节,真正要传的数据
- CRC场:15位CRC校验 + 1位CRC界定符
- ACK场:接收节点回应,告诉发送方“我收到了”
- 帧结束(EOF):7个隐性位
你想想看,一个报文就这么几个部分,但每个位都有讲究。我刚开始做VCU时,就因为在控制场里把DLC设错了,导致BMS死活不认数据。后来查规范才发现,DLC必须与实际数据字节数一致。
2.3 CAN报文格式
CAN报文分两种:标准帧和扩展帧。区别就在ID长度上。
| 特性 | 标准帧 | 扩展帧 |
|---|---|---|
| ID长度 | 11位 | 29位 |
| IDE位 | 0(显性) | 1(隐性) |
| 最大节点数 | 2048个 | 5.3亿个 |
| 数据长度 | 0-8字节 | 0-8字节 |
| 典型应用 | 动力系统、车身控制 | 诊断、多ECU系统 |
我个人习惯,在VCU和BMS之间用标准帧就够了。11位ID,2048个ID空间,完全够用。扩展帧一般留给诊断或者多ECU的复杂系统。
实战建议:在定义CAN矩阵时,把标准帧ID从0x100到0x7FF留给动力系统,0x000到0x0FF留给诊断。这样好管理,也方便排查问题。
2.4 CAN总线仲裁机制
仲裁机制,说白了就是多个节点同时发数据时,谁说了算。
CAN总线是“线与”逻辑:显性位(0)会覆盖隐性位(1)。仲裁时,每个节点从ID的最高位开始,逐位比较。谁的ID小(显性位多),谁就赢。
举个例子:
- 节点A:ID = 0x100(二进制:001 0000 0000)
- 节点B:ID = 0x200(二进制:010 0000 0000)
从最高位开始比:A发0,B发0,平手。第二位:A发0,B发1,A的0覆盖了B的1,A胜出。B自动退出发送,等下次总线空闲再试。
注意:仲裁机制决定了ID越小,优先级越高。所以VCU的报文ID通常比BMS的小,因为VCU控制指令需要优先发送。我曾经见过一个项目,把BMS的ID设得比VCU还小,结果VCU指令总是被BMS报文挤掉,导致电机响应延迟。嗯,这种低级错误,千万别犯。
2.5 知识体系总览
下面这张图,把CAN通讯的核心逻辑串起来了。从物理层的差分信号,到数据链路层的报文结构,再到仲裁机制,一条线下来,你就知道CAN总线是怎么工作的了。
2.6 实战中的坑
最后,分享几个我踩过的坑:
- 终端电阻:总线两端各一个120Ω,别省。少一个,信号反射严重,丢帧率飙升。
- ID分配:VCU的ID一定要比BMS小。优先级决定了控制指令不能被数据报文堵住。
- DLC设置:DLC必须与实际数据字节数一致。多设或少设,接收方都会解析错误。
- CRC校验:别关。有些工程师为了省时间关掉CRC,结果数据出错都不知道。
避坑指南:我曾经在BMS项目中,因为终端电阻只装了一个,导致CAN总线在长距离传输时频繁丢帧。排查了两天才找到原因。从那以后,我每次布线都会用万用表量一下总线两端的电阻,确保是60Ω(两个120Ω并联)。
好了,CAN通讯基础就讲到这里。下一章,咱们聊聊VCU和BMS之间具体怎么通过CAN报文交换数据。到时候,我会拿实际项目中的CAN矩阵来举例,保证干货满满。
公众号:蓝海资料掘金营,微信deep3321