Chapter 03 · CAN 总线 / 汽车电子

数据帧格式

一条 CAN 报文在总线上究竟长什么样?逐字段拆解标准帧与扩展帧,理解 SOF、仲裁场、控制场、数据场、CRC、ACK 与 EOF,以及巧妙的位填充规则。

课程进度19%

关键概念

SOF (Start of Frame, 帧起始)
数据帧的第一位,固定为一个显性位(0)。总线空闲时呈隐性,SOF 的下降沿(隐→显)使全网所有节点在此刻做硬同步,对齐各自的位时钟,为后续逐位仲裁奠定时序基础。
仲裁场 (Arbitration Field)
包含标识符和 RTR 位,是决定优先级的字段。标准帧为 11 位 ID + RTR;扩展帧为 11 位基础 ID + SRR + IDE + 18 位扩展 ID + RTR,共 29 位 ID。多个节点竞争时在此逐位仲裁,ID 数值小者胜出。
RTR (Remote Transmission Request)
远程请求位。RTR=0(显性)表示数据帧(本帧携带数据);RTR=1(隐性)表示远程帧(请求其他节点发送同 ID 的数据)。当数据帧与远程帧 ID 相同同时竞争时,RTR=0 的数据帧优先级更高,故数据帧胜出。
IDE (Identifier Extension)
标识符扩展位,区分帧格式。IDE=0(显性)为标准帧(11 位 ID);IDE=1(隐性)为扩展帧(29 位 ID)。因显性优先,当标准帧与扩展帧基础 ID 相同时标准帧胜出。IDE 位于控制场(标准帧)或仲裁场(扩展帧)中。
DLC (Data Length Code, 数据长度码)
控制场中的 4 位,指示数据场字节数。经典 CAN 中 DLC=0~8 表示 0~8 字节(DLC>8 仍视为 8 字节数据)。接收方据此知道要读取多少数据字节。CAN FD 扩展了 DLC 编码以表示 12/16/20/24/32/48/64 字节。
CRC 场 (Cyclic Redundancy Check)
15 位 CRC 序列 + 1 位 CRC 界定符(隐性)。发送方对 SOF 到数据场的所有位用 CAN 特定生成多项式计算 CRC,接收方独立重算并比对。CRC 是 CAN 五重错误检测中最强的一层,可检出突发错误和大量随机错误,误检率极低。
ACK 场 (Acknowledgement, 应答场)
2 位:ACK 槽 + ACK 界定符。发送方在 ACK 槽发送隐性;任何正确接收(CRC 校验通过)的节点会在此槽覆写一个显性位,发送方读回显性即知"至少有一个节点收到了"。若无节点应答(读回隐性),发送方判定 ACK 错误并重发。注意:ACK 只表示"有人收到",不表示"目标收到"。
位填充 (Bit Stuffing)
为保证接收方能持续做位再同步,CAN 规定:发送方每连续发送 5 个相同电平的位,就自动插入一个相反电平的填充位。接收方检测到 5 连同即知下一位是填充位并丢弃。这保证位流中总有足够的电平跳变供时钟恢复。位填充作用于 SOF 到 CRC 序列之间;CRC 界定符、ACK、EOF 不填充。

标准数据帧的完整结构

下图逐字段展示一个 11 位 ID 的标准数据帧,从 SOF 到 EOF 的全部组成。

CAN 标准数据帧(Standard Frame, 11-bit ID) ══════════════════════════════════════════════════════════════ ┌─┬───────────┬───┬───┬───┬────┬──────────┬────────┬──┬──┬───┐ │S│ 11-bit ID │RTR│IDE│r0 │DLC │ Data 0-8 │ CRC │AK│ │EOF│ │OF│ │ │ │ │(4) │ (0-64) │ (15+1) │ │ │ │ └─┴───────────┴───┴───┴───┴────┴──────────┴────────┴──┴──┴───┘仲裁场← 控制场 →数据场 │ CRC场 │ACK│ EOF 仲裁场 : SOF(1) + ID(11) + RTR(1) 决定优先级 控制场 : IDE(1) + r0保留(1) + DLC(4) 描述帧属性/长度 数据场 : 0~8 字节 (由 DLC 指定) 实际负载 CRC场 : CRC序列(15) + CRC界定符(1,隐性) 差错校验 ACK场 : ACK槽(1) + ACK界定符(1,隐性) 接收确认 EOF : 7 个连续隐性位 帧结束标志 IFS : 帧间隔 ≥3 个隐性位 下一帧前的间隙 位序方向: ────────── 时间先后 ──────────▶ 仲裁时 ID 从最高位(ID10)先发,越先出现 ⇒ 越决定优先级

各字段位宽一览

字段标准帧位数扩展帧位数取值/含义
SOF 帧起始11固定显性(0)
标识符 ID1111(基础)+18(扩展)=29报文标签 + 优先级
RTR 远程请求11(SRR 代替+末尾 RTR)0=数据帧 1=远程帧
SRR 替代远程请求1扩展帧占位,隐性
IDE 扩展标志110=标准 1=扩展
r0 / r1 保留位12发送显性
DLC 长度码440~8 字节
数据场0~640~640~8 字节负载
CRC 序列1515循环冗余校验
CRC 界定符11隐性
ACK 槽 + 界定符22接收确认
EOF 帧结束777 个隐性位
标准帧 vs 扩展帧怎么选

标准帧 11 位 ID 提供 2048 个标识符,够绝大多数整车网络使用,帧更短、效率更高,是乘用车 CAN 的主流。扩展帧 29 位 ID 提供约 5 亿个标识符,主要用于需要结构化编码的商用车协议 J1939(把 29 位划分成优先级/PGN/源地址等字段,本教程第 13 章详解)。两者可在同一总线共存,靠 IDE 位区分。

位填充:保证时钟同步的巧思

CAN 是异步位流,接收方靠数据边沿再同步时钟。若数据恰好是一长串相同位(如 0x00 或 0xFF),就没有边沿可用。位填充强制插入跳变解决这一问题。

位填充规则:5 连同 ⇒ 插入 1 个相反位 原始位流: 0 0 0 0 0 ? 1 1 ... │ 连续 5 个 0 ⇒ 发送方自动插入 1 个 1 ▼ 总线位流: 0 0 0 0 0 1 1 1 ... ← 加粗 1 是填充位 ↑填充 接收方: 见到 5 连 0,知道下一位必是填充位 ⇒ 剥除 示例:数据 0xFF (1111 1111) 经位填充 1 1 1 1 1 0 1 1 1 ← 前 5 个 1 后插 0,再继续 (若接收方本应见 5 连 1 却见到第 6 个 1 ⇒ 填充错误!) 作用范围: SOF ~ CRC序列 (含 ID/控制/数据/CRC) 不填充 : CRC界定符、ACK场、EOF、帧间隔(这些是固定格式场)
位填充带来的副作用

位填充使一帧的实际位数不固定——最坏情况下每 5 位插 1 位,帧会比理论值长约 20%。计算最坏传输时间和总线负载时必须考虑填充位。此外,填充位也参与错误检测:若接收方在应填充处看到第 6 个相同位,就触发"填充错误"(详见第 5 章)。这把位同步与错误检测巧妙地统一在一个机制里。

四种帧类型

CAN 总线上流动的不只是数据帧,还有另外三种特殊帧,各司其职。

帧类型作用关键特征
数据帧 (Data Frame)携带实际数据从发送方广播到全网RTR=0,含 0~8 字节数据场
远程帧 (Remote Frame)请求某 ID 报文的持有者发送数据RTR=1,无数据场,DLC 指期望长度
错误帧 (Error Frame)检测到错误的节点主动破坏总线,通告出错6 个显性位(主动错误)违反位填充,第 5 章详解
过载帧 (Overload Frame)接收方尚未处理完、请求延迟下一帧格式类似错误帧,插在帧间隔期
远程帧已渐被弃用

远程帧(RTR=1)本意是"我想要某数据,请持有者发出来",但它存在语义歧义(多节点可能都持有同 ID)和实时性问题,现代车辆设计普遍改用周期性主动广播或 UDS 诊断请求来获取数据,远程帧已很少使用。许多 AUTOSAR 通信矩阵甚至明确禁用远程帧。理解它主要是为了看懂协议和历史代码。

用代码读一帧:数据结构映射

在 STM32 HAL 中,一帧的头部与数据分别用结构体描述,字段与上面的物理帧一一对应:

/* STM32 HAL 中的 CAN 发送头结构(对应帧的仲裁场+控制场)*/
CAN_TxHeaderTypeDef txHeader;

txHeader.StdId  = 0x123;              /* 11 位标准 ID(仲裁场)*/
txHeader.ExtId  = 0;                  /* 扩展帧才用 29 位 ID */
txHeader.IDE    = CAN_ID_STD;          /* IDE=0 标准帧 */
txHeader.RTR    = CAN_RTR_DATA;         /* RTR=0 数据帧 */
txHeader.DLC    = 8;                  /* 数据长度码:8 字节 */
txHeader.TransmitGlobalTime = DISABLE;

uint8_t data[8] = { 0x01, 0x02, 0x03, 0x04,
                   0x05, 0x06, 0x07, 0x08 };  /* 数据场 */

/* SOF / CRC / ACK / EOF / 位填充 全部由 CAN 控制器硬件
   自动生成和校验,软件只需填 ID、RTR、IDE、DLC 和数据 */
if (HAL_CAN_AddTxMessage(&hcan, &txHeader, data, &txMailbox) != HAL_OK) {
    /* 发送失败处理 */
}
本章小结

一个 CAN 数据帧按时间顺序由这些字段组成:SOF(1 位显性,硬同步)→ 仲裁场(标准帧 11 位 ID+RTR,扩展帧 29 位 ID)→ 控制场(IDE 区分标准/扩展、r0 保留、4 位 DLC 数据长度)→ 数据场(0~8 字节负载)→ CRC 场(15 位校验+界定符)→ ACK 场(发送方发隐性、接收方覆写显性表示"有人收到")→ EOF(7 个隐性位)。关键控制位:RTR=0 数据帧/1 远程帧,IDE=0 标准/1 扩展,显性优先决定同 ID 竞争胜负。位填充规定连续 5 个相同位后插入一个相反位(作用于 SOF~CRC 序列),既保证位时钟再同步,又参与错误检测。总线上有数据帧、远程帧、错误帧、过载帧四种帧,其中远程帧因语义问题已渐被弃用。在 STM32 HAL 中,软件只需填 ID/RTR/IDE/DLC 和数据字节,SOF/CRC/ACK/EOF 和位填充全部由控制器硬件自动完成。

⚒️ 配套开发者工具箱 · JSON / 正则 / 时间戳 / Cron 等 17 款免费在线工具