第2章:CAN总线协议详解
各位同学,今天我们来啃一块硬骨头——CAN总线协议。说实话,我在车载安全领域摸爬滚打这么多年,CAN总线是我打交道最多的协议之一。它看起来简单,但里面的门道可不少。咱们今天就把它的物理层、数据链路层、帧结构、仲裁机制和错误处理机制,一个一个掰开揉碎了讲清楚。
2.1 CAN总线物理层
先说说物理层。CAN总线用的是差分信号传输,说白了就是两根线——CAN_H和CAN_L。这两根线绞在一起,形成双绞线。为什么用差分?抗干扰能力强啊!你想想看,车里的电磁环境多复杂,发动机点火、电机运转,到处都是噪声。差分信号能把这些共模噪声抵消掉,保证数据传输的可靠性。
我个人习惯把CAN总线的电平状态分成两种:显性(Dominant)和隐性(Recessive)。显性电平对应逻辑0,隐性电平对应逻辑1。当总线上有多个节点同时发送时,显性电平会覆盖隐性电平——这个特性是后面仲裁机制的基础。
关键参数:
- 总线电压:CAN_H约3.5V,CAN_L约1.5V(显性);两者均约2.5V(隐性)
- 传输速率:最高1Mbps(通常车载用250kbps或500kbps)
- 总线长度:与速率成反比,1Mbps时最长约40米
我在项目中遇到过一个问题:某款车型的CAN总线在低温环境下频繁丢帧。排查了半天,发现是终端电阻的阻值漂移了。嗯,这里要注意——CAN总线的两端必须各接一个120欧姆的终端电阻,少了它,信号反射会让你怀疑人生。
2.2 数据链路层
数据链路层,说白了就是负责把物理层传来的比特流组织成有意义的帧。CAN总线用的是CSMA/CA(载波监听多路访问/冲突避免)机制。注意,它不是CSMA/CD(冲突检测),而是CA——避免冲突。怎么避免?靠的就是后面要讲的仲裁机制。
数据链路层定义了五种帧类型:
- 数据帧:传输数据的主力
- 远程帧:请求其他节点发送数据
- 错误帧:检测到错误时发送
- 过载帧:节点忙不过来时发送
- 帧间隔:帧与帧之间的分隔
其中,数据帧和远程帧是我们最常用的。我建议初学者先把数据帧吃透,其他的自然就通了。
2.3 帧结构详解
数据帧的结构,我把它分成七个部分:
| 字段 | 长度(标准帧) | 说明 |
|---|---|---|
| 帧起始(SOF) | 1 bit | 显性电平,同步所有节点 |
| 仲裁场 | 12 bits | 包含11位ID和RTR位 |
| 控制场 | 6 bits | 包含IDE、r0和DLC |
| 数据场 | 0-64 bits | 实际传输的数据,最多8字节 |
| CRC场 | 16 bits | 15位CRC + 1位界定符 |
| 应答场 | 2 bits | 接收节点发送显性电平确认 |
| 帧结束(EOF) | 7 bits | 隐性电平 |
这里有个坑,我踩过——数据场最多只有8个字节。有些刚入行的同事总想一次塞几十个字节进去,结果发现根本发不出去。为什么只有8字节?因为CAN总线设计之初就是为实时控制用的,短帧意味着低延迟、高可靠性。你想想看,安全气囊的触发信号,能等它慢慢传完几十个字节吗?
小技巧:如果数据超过8字节,可以用多帧传输,或者考虑CAN FD(灵活数据速率)协议,它支持最多64字节的数据场。
2.4 仲裁机制
仲裁机制是CAN总线最巧妙的设计之一。当多个节点同时发送时,怎么决定谁先发?靠ID优先级。ID值越小,优先级越高。仲裁过程是这样的:
- 所有节点同时发送帧起始位(显性)
- 接着发送ID位,逐位比较
- 如果某个节点发送隐性位(1),但总线上是显性位(0),说明有更高优先级的节点在发送
- 该节点立即停止发送,转为接收模式
- 优先级最高的节点继续发送,不受影响
我曾经调试过一个项目,发现某个ECU总是抢不到总线。查了半天,原来是它的ID设成了0x7FF——标准帧里最大的ID,优先级最低。说白了,它就是个「老好人」,谁都能把它挤下去。后来我们把ID改小,问题就解决了。
注意:ID的分配不是随意的。整车厂通常有统一的ID分配规范,比如动力系统用0x000-0x1FF,车身系统用0x200-0x3FF。乱设ID会导致总线冲突,严重时可能引发安全风险。
2.5 错误处理机制
CAN总线的错误处理机制,可以说是它最可靠的地方。它定义了五种错误类型:
- 位错误:发送节点监控总线,发现发送的电平和总线上的不一致
- 填充错误:连续5个相同电平后,没有插入相反电平
- CRC错误:接收节点计算的CRC与发送的不一致
- 形式错误:帧格式不符合规范
- 应答错误:发送节点没有收到应答信号
每个节点都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。错误多了,节点会进入三种状态:
| 状态 | 条件 | 行为 |
|---|---|---|
| 错误主动 | TEC < 128 且 REC < 128 | 正常发送,检测到错误时发送主动错误帧 |
| 错误被动 | TEC > 127 或 REC > 127 | 只能发送被动错误帧,且发送前要等待8个隐性位 |
| 总线关闭 | TEC > 255 | 完全断开与总线的连接,不再发送任何数据 |
我记得有一次在实验室测试,一个ECU反复进入总线关闭状态。查了三天,最后发现是它的晶振频率偏差太大,导致位时序不对。嗯,这里要提醒大家——CAN总线的位时序配置非常关键,采样点通常设在75%-85%的位置,太靠前或太靠后都会增加误码率。
避坑指南:我曾经因为忘记配置终端电阻,导致整个CAN网络在高速通信时频繁报错。后来养成了习惯——每次搭建测试环境,第一件事就是检查终端电阻和位时序参数。
好了,CAN总线协议的核心内容就这些。说实话,它虽然诞生于上世纪80年代,但至今仍是车载网络的中流砥柱。你把它吃透了,后面学CAN FD、车载以太网都会轻松很多。下一章我们聊聊CAN总线的安全威胁,那才是真正刺激的部分。