4、CAN通信基础:CAN总线物理层与数据链路层、CAN报文结构、DBC文件解析、CAN通信矩阵
做VCU标定,CAN通信是躲不开的坎。我见过不少新人,上来就拿着DBC文件刷数据,结果车跑起来一堆故障码——说白了,就是没搞懂CAN总线到底在干什么。
这一章,咱们把CAN通信的底裤扒干净。从物理层的电平怎么跳,到报文里每个bit怎么排,再到DBC文件怎么把二进制翻译成物理量,最后看通信矩阵怎么组织整车信号。嗯,这些东西搞明白了,你调车的时候心里才有底。
4.1 CAN总线物理层与数据链路层
CAN总线分两层:物理层和数据链路层。物理层管信号怎么在线上跑,数据链路层管报文怎么组织、怎么仲裁、怎么纠错。
4.1.1 物理层:差分信号与总线电平
CAN总线用两根线:CAN_H和CAN_L。信号靠两根线的电压差来传递,这叫差分传输。好处是抗干扰能力强——你想想看,车上的电磁环境多恶劣,点火线圈、电机、继电器都在啪啪放电,单端信号早就被淹没了。
| 信号状态 | CAN_H电压 | CAN_L电压 | 差分电压 | 逻辑值 |
|---|---|---|---|---|
| 显性(Dominant) | 3.5V | 1.5V | 2.0V | 0 |
| 隐性(Recessive) | 2.5V | 2.5V | 0V | 1 |
注意,CAN总线的逻辑是反的:显性电平(差分2V)代表逻辑0,隐性电平(差分0V)代表逻辑1。这个设计是为了总线仲裁——多个节点同时发数据时,谁先发0谁赢。
4.1.2 数据链路层:帧类型与仲裁机制
CAN的数据链路层定义了五种帧:数据帧、远程帧、错误帧、过载帧、帧间隔。咱们标定最常用的是数据帧,偶尔用远程帧请求数据。
仲裁机制是CAN的亮点。多个节点同时发数据,总线通过ID的优先级来决定谁先发。ID越小,优先级越高。为什么?因为显性位(0)会覆盖隐性位(1),所以ID前面0越多的节点,越早抢到总线。
4.2 CAN报文结构
标准CAN数据帧长什么样?我直接给你拆开看。
标准帧(11位ID)结构:
| SOF | 仲裁场(12) | 控制场(6) | 数据场(0-64) | CRC场(16) | ACK场(2) | EOF(7) |
| 1 | ID(11)+RTR(1) | IDE(1)+r0(1)+DLC(4) | 数据字节 | CRC(15)+DEL(1) | SLOT(1)+DEL(1) | 7 |
扩展帧(29位ID)结构:
| SOF | 仲裁场(32) | 控制场(6) | 数据场(0-64) | CRC场(16) | ACK场(2) | EOF(7) |
| 1 | ID(11)+SRR(1)+IDE(1)+ID(18)+RTR(1) | r1(1)+r0(1)+DLC(4) | 数据字节 | CRC(15)+DEL(1) | SLOT(1)+DEL(1) | 7 |
几个关键字段你得记住:
- SOF(Start of Frame): 1位显性,告诉总线“我要发数据了”。
- ID(Identifier): 标准帧11位,扩展帧29位。决定优先级,也标识报文内容。
- RTR(Remote Transmission Request): 数据帧为0,远程帧为1。
- DLC(Data Length Code): 4位,表示数据场有多少字节。范围0-8。
- 数据场: 0-8字节,真正传的数据。
- CRC(Cyclic Redundancy Check): 15位CRC校验 + 1位分隔符。检错用的。
- ACK(Acknowledge): 接收节点在ACK Slot发显性位,告诉发送方“我收到了”。
4.3 DBC文件解析
DBC文件是CAN总线的“翻译官”。它把二进制报文翻译成工程师能看懂的物理量——比如车速、转速、水温。没有DBC,你看到的CAN数据就是一堆0和1。
4.3.1 DBC文件结构
一个标准的DBC文件包含以下部分:
VERSION ""
NS_ :
BS_
BU_
BO_
EV_
...
BS_: 波特率定义,如 500000
BU_: 网络节点列表,如 VCU、ECU、BMS、MCU
BO_: 报文定义
BO_ 100 VCU_1: 8 VCU
SG_ VehicleSpeed : 0|16@1+ (0.01,0) [0|300] "km/h" ECU,BMS
SG_ AccelPedalPos : 16|8@1+ (0.4,0) [0|100] "%" ECU
EV_: 信号值编码(枚举)
EV_ AccelPedalPos_Error : 0 "NoError" 1 "SensorFault" 2 "PlausibilityFault" ;
我来拆解一下信号定义行:
- SG_ VehicleSpeed : 信号名称
- 0|16@1+ : 起始位0,长度16位,Intel格式(@1),无符号(+)
- (0.01,0) : 精度0.01,偏移0
- [0|300] : 物理范围0-300 km/h
- "km/h" : 单位
- ECU,BMS : 接收节点
4.3.2 Intel vs Motorola格式
这是新人最容易搞混的地方。说白了就是字节内bit的排列顺序:
| 格式 | 起始位定义 | 跨字节排列 | 常用场景 |
|---|---|---|---|
| Intel(小端) | LSB(最低有效位) | 低字节在前,高字节在后 | 大部分ECU信号 |
| Motorola(大端) | MSB(最高有效位) | 高字节在前,低字节在后 | 部分老式控制器 |
举个例子:一个16位信号,起始位0,长度16。Intel格式下,Byte0是低8位,Byte1是高8位。Motorola格式下,Byte0是高8位,Byte1是低8位。同一个原始值0x1234,Intel解析出来是0x3412,Motorola解析出来是0x1234——差远了。
4.4 CAN通信矩阵
通信矩阵是整车的“信号地图”。它定义了谁发、谁收、什么时候发、发什么。一个完整的整车通信矩阵包含:
- 报文列表: 所有CAN报文的ID、名称、周期、发送节点、接收节点
- 信号列表: 每个报文包含的信号,以及每个信号的起始位、长度、精度、偏移、范围、单位
- 周期与触发: 周期性报文(如10ms、100ms)和事件触发报文(如故障时发送)
- 网络管理: 节点唤醒、休眠、心跳报文等
下面是一个简化的通信矩阵示例:
| 报文ID | 报文名称 | 周期(ms) | 发送节点 | 接收节点 | 信号列表 |
|---|---|---|---|---|---|
| 0x100 | VCU_1 | 10 | VCU | ECU, BMS | VehicleSpeed, AccelPedalPos, BrakeSwitch |
| 0x200 | ECU_1 | 20 | ECU | VCU | EngineSpeed, EngineTorque, CoolantTemp |
| 0x300 | BMS_1 | 100 | BMS | VCU, MCU | BatterySOC, BatteryVoltage, BatteryCurrent |
| 0x400 | MCU_1 | 50 | MCU | VCU | MotorSpeed, MotorTorque, InverterTemp |
4.5 本章知识体系
下面这张图把CAN通信的核心知识点串起来了。从物理层的两根线,到数据链路层的帧结构,再到DBC怎么翻译,最后落到通信矩阵怎么组织整车信号——你顺着这个逻辑走一遍,CAN通信就没秘密了。
嗯,CAN通信这块内容不少,但都是标定工程师的必修课。物理层决定了你能不能收到信号,数据链路层决定了信号怎么组织,DBC决定了你怎么看懂信号,通信矩阵决定了你找谁要信号。四层打通了,你在CAN总线上就是“透明人”——所有数据对你来说都是明牌。