CAN 帧格式 -- 帧类型、仲裁与位填充

1. CAN 帧类型总览

CAN 协议定义了 4 种帧类型:

帧类型用途
数据帧(Data Frame)发送节点向其他节点传输数据
远程帧(Remote Frame)请求其他节点发送数据(已较少使用)
错误帧(Error Frame)节点检测到总线错误时发送
过载帧(Overload Frame)接收节点需要更多处理时间时发送

数据帧是最常用的帧类型,本教程重点讲解。


2. 数据帧结构详解

一个标准数据帧由以下字段组成:

SOF | 仲裁场 | 控制场 | 数据场 | CRC 场 | ACK 场 | EOF
 1bit | 11/29bit | 6bit | 0-8字节 | 16bit | 2bit | 7bit

2.1 帧起始(SOF, Start of Frame)

  • 1 bit 显性电平
  • 所有节点通过 SOF 实现位同步
  • 表示一帧的开始

2.2 仲裁场(Arbitration Field)

仲裁场包含 CAN ID 和 RTR 位:

帧类型CAN ID 长度RTR 位总长度
标准帧(CAN 2.0A)11 bit1 bit12 bit
扩展帧(CAN 2.0B)29 bit1 bit30 bit
  • CAN ID:标识报文的身份,数值越小,优先级越高
  • RTR(Remote Transmission Request):
    • 数据帧:RTR = 显性(0)
    • 远程帧:RTR = 隐性(1)

2.3 控制场(Control Field)

字段长度说明
IDE1 bit标识符扩展位(0=标准帧,1=扩展帧)
r01 bit保留位
DLC4 bit数据长度码(0-8)

2.4 数据场(Data Field)

  • 0-8 字节数据
  • 这是 CAN 2.0 的硬性限制 —— 最多只能携带 8 字节有效数据
  • 字节顺序:高位字节先发送

思考:8 字节的限制对高层协议(如 CANOpen SDO 传输大于 4 字节的数据)有什么影响?答案是:需要分段传输。

2.5 CRC 场(CRC Field)

  • 15 bit CRC + 1 bit CRC 定界符
  • 用于检测传输错误
  • 发送方计算 CRC,接收方验证

2.6 ACK 场(Acknowledgment Field)

  • ACK 槽(1 bit)+ ACK 定界符(1 bit)
  • 接收方在 ACK 槽位置发送显性电平,表示"我收到了"
  • 如果发送方在 ACK 槽读到隐性电平,说明没有节点收到此帧

2.7 帧结束(EOF, End of Frame)

  • 7 bit 隐性电平
  • 表示一帧的结束

3. 仲裁机制(重点)

3.1 为什么需要仲裁?

当多个节点同时尝试发送时,总线不能冲突。CAN 使用 CSMA/CD+AMP(带仲裁的载波监听多路访问/碰撞检测)机制来解决这个问题。

3.2 仲裁过程

规则:逐位仲裁,ID 越小,优先级越高。

过程图解:

时间 →
节点 A (ID=0x100): 0 0 0 1 0 0 0 0 0 0 0 ...  (发送 0x100)
节点 B (ID=0x200): 0 1 0 0 0 0 0 0 0 0 0 ...  (发送 0x200)
─────────────────────────────────────────────
总线实际值:         0 0 0 1 0 0 0 0 0 0 0 ...  (显性覆盖隐性)
                      ↑
                   节点 B 发送隐性(1)
                   但读到显性(0) → 退出发送

详细步骤:

  1. 节点 A 和节点 B 同时开始发送
  2. 第 1 位:都是 0(显性),双方都继续
  3. 第 2 位:A 发 0(显性),B 发 1(隐性)
  4. B 读到 0(显性),但自己发的是 1(隐性) → B 知道有更高优先级的节点在发送 → B 立即停止发送,转为接收模式
  5. A 继续完成发送

关键结论:

  • ID 值越小,在仲裁中越早赢得总线
  • 0x000 是最高优先级(这就是为什么 CANOpen 的 NMT 命令使用 COB-ID 0x000)
  • 仲裁过程无延迟、无数据损失 —— 失败的节点自动在下一帧重试

4. 位填充规则

4.1 什么是位填充?

CAN 规定:连续发送 5 个相同电平的位后,自动插入一个相反电平的位。

原始数据:  0 0 0 0 0 0 0 0  (连续 8 个 0)
填充后:    0 0 0 0 0 1 0 0 0 0 1 0  (每 5 个 0 后插入 1)

4.2 为什么需要位填充?

  1. 时钟同步:接收方通过电平跳变来同步时钟,长串相同位会导致失去同步
  2. 区分帧边界:SOF 是显性,前面至少有 3 个隐性位(帧间空间),位填充确保数据中不会出现类似 SOF 的长串隐性

4.3 哪些字段需要位填充?

字段是否位填充
SOF否
仲裁场是
控制场是
数据场是
CRC 场是
ACK 场否
EOF否

5. CAN ID 与 CANOpen COB-ID 的关系

在纯 CAN 层,只有 CAN ID(11-bit 或 29-bit)。

在 CANOpen 应用层,这个 ID 被称为 COB-ID(Communication Object Identifier),并被赋予了更丰富的语义:

COB-ID 结构(11-bit 标准帧):

  高 4 bit       |    低 7 bit
  ─────────────────────────────
  功能码         |    节点 ID
  (Function Code)|    (Node ID)
功能码(高 4 bit)COB-ID 范围CANOpen 功能
00000x000NMT(网络管理)
00010x080-0x0FFSYNC / TIME
00110x180-0x1FFPDO 1 TX
01000x200-0x27FPDO 1 RX
………
10110x580-0x5FFSDO TX(响应)
11000x600-0x67FSDO RX(请求)
11100x700-0x77FHeartbeat / Node Guarding

这就是 CANOpen 的核心设计 —— 通过预定义的 COB-ID 分配表,将不同的通信对象映射到不同的 CAN ID 上,利用 CAN 的仲裁机制实现优先级管理。


6. 扩展帧(CAN 2.0B)

扩展帧使用 29-bit 标识符,结构为:

SOF | 11-bit 基 ID | SRR | IDE | 18-bit 扩展 ID | 控制场 | ...
  • SRR(Substitute Remote Request):替代远程请求位,始终为隐性
  • IDE(Identifier Extension):标识符扩展位,扩展帧中为 1

CANOpen 主要使用标准帧(11-bit),因为 2048 个 COB-ID 已经足够大多数应用。


7. 关键知识点总结

知识点要点
数据帧字段SOF → 仲裁 → 控制 → 数据 → CRC → ACK → EOF
CAN ID 长度标准帧 11-bit(0x000-0x7FF),扩展帧 29-bit
仲裁规则ID 越小优先级越高,显性覆盖隐性
位填充连续 5 个相同位后插入相反位
数据限制最多 8 字节
COB-IDCAN ID 在 CANOpen 中的称呼,高 4 bit = 功能码,低 7 bit = 节点 ID

★ Insight ─────────────────────────────────────

  • CAN 仲裁的优雅之处在于:它不需要额外的时间槽或重传机制,仲裁与数据传输同时进行,失败的节点在第一个不同位就自动退出。
  • 8 字节数据限制是 CAN 的核心瓶颈,也是 CAN FD(64 字节)出现的原因。但在 CANOpen 中,这个限制通过 SDO 分段传输得到了巧妙解决。
  • COB-ID 的设计体现了"ID 即功能"的思想 —— 不需要额外的协议头来标识报文类型,CAN ID 本身就携带了语义信息。 ─────────────────────────────────────────────────

上一步 | 下一步

← 01-can-physical-layer.md —— CAN 物理层 → 03-socketcan-intro.md —— SocketCAN 入门

如果这篇文章对你有帮助,欢迎请我喝杯咖啡 ☕
Cygnus Yang 支付宝支付宝
Cygnus Yang 微信微信