3. CAN数据链路层:帧结构与仲裁机制

数据链路层,说白了就是CAN协议最核心的“交通规则”。它规定了数据怎么打包、怎么抢路权、怎么纠错。我做了这么多年车身稳定系统,遇到的大部分通信问题,根源都在这一层。

3.1 标准帧与扩展帧

CAN总线上的报文,主要有两种格式:标准帧和扩展帧。它们的区别,关键就在ID的长度。

特性 标准帧 (CAN 2.0A) 扩展帧 (CAN 2.0B)
ID长度 11位 29位
仲裁场结构 ID + RTR + IDE + r0 ID + SRR + IDE + 扩展ID + RTR + r1 + r0
数据场最大长度 8字节 8字节
帧间隔 3位 3位
应用场景 传统车身控制、简单传感器 多节点、复杂网络(如动力总成、ADAS)

我个人习惯,在车身稳定系统(ESC)这类实时性要求高的场景,尽量用标准帧。为什么?因为11位ID足够区分ESC、转向、制动这些核心节点,而且帧短,传输快。扩展帧虽然地址空间大,但仲裁场多了SRR和IDE位,帧长度增加,会挤占总线带宽。

避坑指南: 我曾经在一个项目中,为了“预留未来扩展”,把所有节点都配成了扩展帧。结果发现,ESC的周期报文(10ms周期)经常因为帧太长,跟其他报文撞车,导致丢帧。后来我强制把ESC、ABS这类高优先级节点改回标准帧,问题立刻解决。

3.2 仲裁机制:CSMA/CR

CAN总线没有主节点,所有节点都能随时发数据。那冲突了怎么办?靠CSMA/CR——载波监听多路访问/冲突解决。

说白了,就是“先听后说,边说边听”。每个节点在发送前,先监听总线是否空闲。如果空闲,就开始发。发送的同时,还在监听总线上的电平。

关键来了:CAN总线是“线与”逻辑。显性电平(逻辑0)会覆盖隐性电平(逻辑1)。所以,如果两个节点同时发,谁的ID更小(显性位更多),谁就能继续发,另一个节点自动退出发送,转为接收。

核心结论: ID越小,优先级越高。在车身稳定系统中,ESC的报文ID通常设为0x100左右,而车窗、灯光这类舒适性节点,ID往往在0x500以上。这样,紧急的制动指令永远能抢到总线。

你想想看,如果ESC和车窗同时发报文,ESC的ID是0x100(二进制:00100000000),车窗是0x500(二进制:10100000000)。在仲裁场的第一位,ESC发0,车窗发1,显性电平覆盖隐性,车窗立刻退出发送。整个过程,在几个微秒内完成,不会丢数据。

3.3 位填充机制

位填充,是为了保证时钟同步。CAN总线没有单独的时钟线,接收节点靠跳变沿来同步。如果连续出现5个相同的电平,接收节点就可能失步。

规则很简单:发送节点在连续发送5个相同位后,自动插入一个相反的电平位。接收节点收到后,自动把这个填充位去掉。

  • 填充规则: 每5个连续相同位,插入1个相反位
  • 填充范围: SOF、仲裁场、控制场、数据场、CRC场
  • 不填充范围: ACK场、EOF、帧间隔
注意: 位填充不是随便加的。如果数据场里连续出现5个0,发送节点必须插入一个1。接收节点收到后,必须把这个1去掉,才能还原原始数据。我曾经调试过一个ESC报文,发现接收到的数据总是多一位,排查了半天,才发现是位填充没处理好。

3.4 错误帧与错误处理

CAN总线有5种错误类型,每种都有对应的检测机制。我把它整理成一张表,方便你对照。

错误类型 检测机制 触发条件
位错误 发送节点比较发送电平与总线电平 发送的位与监听到的位不一致
填充错误 接收节点检测填充规则 连续6个相同位出现
CRC错误 接收节点计算CRC并与发送CRC比较 CRC校验不匹配
格式错误 接收节点检测固定格式位 固定位(如EOF、ACK)电平错误
ACK错误 发送节点检测ACK槽 ACK槽未被接收节点置为显性

一旦检测到错误,节点会立即发送错误帧。错误帧由6个显性位(主动错误)或6个隐性位(被动错误)组成,强制中断当前报文,通知所有节点丢弃该帧。

嗯,这里要注意:错误帧不是随便发的。每个节点有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。错误越多,计数器越大。当TEC或REC超过127时,节点从“主动错误”状态变为“被动错误”状态,只能发隐性错误帧,不能主动干扰总线。如果TEC超过255,节点直接进入“总线关闭”状态,彻底退出通信。

经验之谈: 我曾经在ESC的台架测试中,发现总线偶尔出现大量错误帧。用CAN分析仪一抓,发现是某个传感器节点的TEC一直在涨。后来查出来,是那个节点的CAN收发器供电不稳,导致发送电平异常。换了一个带过压保护的收发器,问题解决。所以,硬件设计上,收发器的电源质量,直接影响错误率。

3.5 本章知识结构图

下面这张图,把数据链路层的核心逻辑串起来了。你可以把它当作一个快速索引。

CAN数据链路层核心结构 CAN数据链路层核心结构 帧结构 仲裁机制 位填充 错误处理 标准帧 (11位ID) 扩展帧 (29位ID) CSMA/CR (线与仲裁) 每5位插入1个相反位 5种错误类型 错误帧 (6位显性/隐性) 关键指标 • 标准帧:47位 • 扩展帧:67位 • 仲裁优先级:ID越小越高

这张图把帧结构、仲裁、位填充、错误处理四个模块串起来了。你可以看到,标准帧和扩展帧是帧结构的两个分支,仲裁机制靠CSMA/CR实现,位填充保证时钟同步,错误处理则通过错误帧和计数器来维护总线健康。

在实际的车身稳定系统开发中,我建议你把这张图打印出来,贴在工位上。遇到通信问题,先定位是哪个模块出的问题,再深入排查。这样效率会高很多。