2. CAN协议基础:CAN数据帧结构、CAN远程帧、CAN错误帧、CAN过载帧、CAN帧间隔

各位工程师朋友,咱们今天聊聊CAN协议里最核心的几种帧结构。说实话,搞CAN通信这么多年,我见过太多人栽在帧格式的理解上。你想想看,连报文都发不对,还谈什么信号质量?

CAN总线上一共就五种帧:数据帧、远程帧、错误帧、过载帧,还有帧间隔。嗯,咱们一个一个来拆解。

2.1 CAN数据帧结构

数据帧,说白了就是用来发数据的。我个人习惯把它分成七段来看,这样好记:

  • 帧起始(SOF):1个显性位,告诉总线上其他节点「我要开始说话了」。
  • 仲裁段:包含11位(标准帧)或29位(扩展帧)的ID,还有RTR位、IDE位等。这里要注意,ID越小优先级越高。
  • 控制段:6位,包含IDE位、保留位和DLC(数据长度码)。DLC告诉你后面跟了多少字节数据。
  • 数据段:0~8字节,这就是你要传的实际数据。
  • CRC段:15位CRC校验码+1位CRC界定符。用来检查数据有没有传错。
  • ACK段:2位。发送节点发隐性位,接收节点如果收到正确的帧,就在ACK槽里拉成显性位。这就是「应答」。
  • 帧结束(EOF):7个隐性位,表示帧结束了。

重要提醒:标准帧和扩展帧的区别就在仲裁段。标准帧11位ID,扩展帧29位ID。我在项目里经常看到有人把扩展帧当标准帧用,结果ID冲突,总线直接罢工。

举个例子,假设你要发一个ID为0x123、带2字节数据的标准帧:

// 伪代码示意
SOF: 0 (显性)
仲裁段: ID=0x123 (二进制: 00100010011), RTR=0 (数据帧)
控制段: IDE=0 (标准帧), r0=0, DLC=0010 (2字节)
数据段: 0xAA, 0x55
CRC段: 15位CRC + 1位隐性界定符
ACK段: 发送方发隐性, 接收方拉显性
EOF: 7个隐性位

我的经验:调试时如果发现对方收不到数据,先查DLC对不对。我曾经有一次DLC设成了0,折腾了两小时才发现——数据长度是0,当然啥也收不到。

2.2 CAN远程帧

远程帧,说白了就是「我要数据,你给我发」。它和数据帧长得几乎一样,唯一的区别是RTR位为隐性(1)。

你想想看,远程帧没有数据段,但DLC字段必须填上你想要的数据长度。为什么?因为接收节点要根据DLC准备发送缓冲区。

避坑指南:我曾经遇到一个项目,A节点发远程帧请求B节点发数据,但B节点的DLC设的和A节点请求的不一致。结果B节点发出来的数据长度不对,A节点解析全乱套了。记住:远程帧的DLC必须和对应数据帧的DLC一致。

远程帧的应用场景其实不多。我个人习惯是:能用数据帧主动上报的,就别用远程帧去轮询。远程帧会增加总线负载,而且实时性不好控制。

2.3 CAN错误帧

错误帧,嗯,这玩意儿是CAN总线自己「纠错」的机制。当任何节点检测到总线错误时,就会发送错误帧。

错误帧由两部分组成:

  • 错误标志:6个连续相同极性的位(显性或隐性)。主动错误节点发6个显性位,被动错误节点发6个隐性位。
  • 错误界定符:8个隐性位。

CAN协议定义了五种错误类型:

错误类型 说明 我遇到的案例
位错误 发送节点监控总线,发现发送的位和总线上的位不一致 有一次总线终端电阻没接好,位错误满天飞
填充错误 连续6个相同极性的位出现(违反位填充规则) 某个节点晶振漂移,导致位时间不准
CRC错误 接收节点计算的CRC和发送的不一致 线束太长,信号衰减导致CRC经常错
形式错误 固定格式的位段出现非法电平 EOF必须是7个隐性位,有人发了显性位
应答错误 发送节点没收到ACK显性位 总线上只有一个节点,自己发自己收,没应答

核心要点:错误帧不是用来「报告错误」的,它是用来「破坏当前帧」的。一旦错误帧发出,当前正在传输的帧就被强制终止,所有节点都会丢弃这个帧。这就是CAN的「错误自愈」机制。

2.4 CAN过载帧

过载帧,说白了就是「我忙不过来,你慢点」。它和错误帧长得有点像,但用途完全不同。

过载帧的结构:

  • 过载标志:6个显性位。
  • 过载界定符:8个隐性位。

什么时候会发过载帧?两种情况:

  1. 接收节点内部条件没准备好,比如接收缓冲区满了。
  2. 在帧间隔期间检测到显性位(这属于「被动过载」)。

我的建议:过载帧在实际项目中用得很少。如果你发现总线上频繁出现过载帧,别急着调协议——先查查接收节点的处理速度是不是太慢了。我曾经优化过一个项目,把中断处理函数从50μs优化到10μs,过载帧就再也没出现过。

2.5 CAN帧间隔

帧间隔,嗯,就是两帧之间的「休息时间」。它保证了总线上的节点有足够的时间准备接收下一帧。

帧间隔的结构:

  • 间歇场:3个隐性位。
  • 总线空闲:任意长度的隐性位(直到有节点开始发送)。

对于被动错误节点,帧间隔还会多一个「挂起传输场」(8个隐性位)。这是为了让被动错误节点「闭嘴」一会儿,别老抢总线。

注意:帧间隔不是「可选的」,它是协议强制要求的。我曾经见过有人把两帧之间的间隔设成0,结果总线直接崩溃——因为节点根本没时间处理上一帧的数据。

好了,五种帧结构都讲完了。你想想看,CAN协议其实就靠这五种帧在跑。数据帧传数据,远程帧要数据,错误帧纠错,过载帧控流,帧间隔做隔离。搞懂了这些,CAN总线通信的基础就算打牢了。

下一章咱们聊聊CAN的位时序和同步机制——那才是真正影响信号质量的关键。