CAN 帧结构:总线上到底传了什么
从 SOF 到 EOF,逐段读懂经典 CAN 数据帧、仲裁、CRC 与 ACK。
更新于 2026-11-05
控制器局域网(CAN)是一条广播总线。所有节点挂在同一对双绞线 CAN_H 与 CAN_L 上,经典意义上没有地址:每一帧所有节点都能看见,由接收端自行判断标识符是否关心。总线只有两种状态,显性(逻辑 0,存在差分电压)与隐性(逻辑 1,不驱动差分)。显性位会覆盖隐性位,这既是仲裁的物理基础,也是应答机制的基础。典型做法是在两端各接 120 欧姆终端电阻;经典 CAN 的速率通常在 125 kbit/s 到 1 Mbit/s 之间,具体取决于线缆长度与采样点配置。
数据帧以一个显性 SOF 位开始,让所有接收端完成硬同步。随后是仲裁场:11 位标识符(扩展帧为 29 位,分为基本 ID 与扩展 ID)加上用来区分数据帧与远程帧的 RTR 位。控制场包含 IDE、保留位和 DLC 数据长度码。经典 CAN 里 DLC 直接表示 0 到 8 个字节;CAN FD 把同一个字段当作索引,最大可对应 64 字节。位填充会在连续五个相同位之后插入一个相反位,帮助接收端保持时钟同步,作用范围从 SOF 一直覆盖到 CRC 序列结束。
从 SOF 到 EOF 逐段读
载荷之后是 15 位 CRC(CAN FD 为 17 位)、隐性的 CRC 界定符,以及 ACK 应答位。发送方把 ACK 位发成隐性,任何正确收到该帧的节点都会把它拉成显性,于是发送方知道至少有一个监听者理解了这一帧,但不需要知道是谁。EOF 是七个隐性位,之后还有一小段帧间隔才能开始下一帧。当两个节点同时发送时,双方一边发标识符一边回读总线:第一个出现「一方隐性、另一方显性」的位置就决定了胜者,败者立刻转为接收方。这叫非破坏性仲裁,获胜帧不会被破坏,总线带宽不会浪费在冲突重发上。
错误处理由硬件完成。检测到位错误、填充错误、CRC 错误或格式错误的节点会发出错误帧并累加计数器;反复出问题会让节点从主动错误状态退到被动错误状态,最终进入总线关闭(bus-off)。这也解释了为什么终端电阻缺失或波特率不一致,表现往往是「报文随机丢失」而不是干脆不通信。帧本身不带名称、单位或换算,只有一个标识符和最多八字节原始数据。把这些字节变成工程量,正是 DBC 数据库要做的事情,也是本系列下一篇的主题。
字段一览
- SOF —— 一个显性位,帧起始与硬同步
- 仲裁场 —— 11 位或 29 位标识符加 RTR,数值越小优先级越高
- 控制场 —— IDE、保留位、DLC(经典 CAN 为 0–8 字节)
- 数据场 —— 原始载荷字节,含义由 DBC 的 SG_ 行描述
- CRC —— 15 位校验加界定符
- ACK —— 接收方把应答位拉为显性;EOF 与帧间隔收尾
逐步查看经典 CAN 数据帧的各个字段
从原始字节到信号
ID 0x1F0 DLC 8 DATA 12 34 00 7A 00 00 00 00
^^^^ DBC 的 SG_ 行说明每一位代表什么实际工作中很少手工解码报文。通常是载入 DBC 文件,选中与标识符匹配的报文,让工具对每条信号依次应用起始位、长度、字节序、符号位、factor 与 offset。但理解帧布局仍有价值:它能解释为什么波特率设错就一帧都收不到,为什么经典 CAN 的 8 字节是硬上限,以及为什么同一报文里两条信号重叠时总线本身毫无察觉。工具只能展示数据库描述的内容,无法判断描述本身是否写错,所以诊断信息和原始值同样值得看。
在查看器里试一试
打开示例文件,或拖入自己的 DBC/A2L 文件。解析完全在本浏览器进行,不会上传任何内容。
打开查看器常见问题
标识符越小就一定优先吗?
对标准数据帧是的:显性位覆盖隐性位,因此数值最小的标识符赢得仲裁。
DLC 就是字节数吗?
经典 CAN 中 DLC 直接表示 0–8 字节;CAN FD 中 DLC 是编码值,最大可对应 64 字节。