CAN数据帧

Tutorial: 卓越工程师 Category: 嵌入式 Published: 2026-10-23 11:05:29 Views: 0 Likes: 0 Comments: 0

180.1.3 CAN数据帧

本课只讲 CAN 帧的类型与 Classical CAN 数据帧的线上结构,没有打开、展示或修改源码,因此标题下不强行补代码。实际编程时主要填写标识符、帧格式、帧类型、DLC 和数据,SOF、CRC、ACK 等协议位由 CAN 控制器处理。

一、知识回顾

上一课已经说明,CAN 节点由应用程序、CAN 控制器和 CAN 收发器共同组成。应用程序交给控制器的只是“要发什么消息”;控制器还会为它补上仲裁、CRC 等协议字段,经收发器转换为 CANH/CANL 上的差分信号。

本课讨论的是 Classical CAN(经典 CAN)在线路上传输的帧。它和以前串口程序中自行约定的“帧头 + 长度 + 数据 + 校验 + 帧尾”有相似目的,但字段格式、位数和处理者都不同,不能把两种帧直接等同。

学习帧结构的意义在于理解:

  • 多个节点同时发送时,CAN 怎样依据标识符完成无破坏仲裁;
  • 接收节点怎样知道数据有多少字节,并检查传输是否出错;
  • 哪些字段由程序填写,哪些字段由 STM32 的 bxCAN 外设自动生成;
  • 为什么“发送函数返回成功”“总线上出现 ACK”“应用程序处理了数据”是三个不同层面的结果。

二、帧类型

2.1 帧类型概览

视频中所谓“57 个小分支”是转录错误。Classical CAN 总线上需要认识的是以下 5 种帧类型:

帧类型主要作用是否携带应用数据
数据帧(Data frame)发送某个标识符对应的数据是,0~8 字节
远程帧(Remote frame)请求其他节点发送同一标识符的数据帧否
错误帧(Error frame)节点检测到协议错误时破坏当前帧,使所有节点知道本次传输无效否
过载帧(Overload frame)请求延迟下一帧的开始;现代控制器中很少由应用层直接接触否
帧间隔(Interframe space)隔开前后两帧,为下一次总线访问建立边界否

数据帧和远程帧又可以采用 11 位标识符的基本/标准格式,或 29 位标识符的扩展格式。本课程使用 STM32F103 的 Classical CAN 控制器,后文先以最常用的 11 位标准数据帧 为主。

2.2 数据帧的构成与作用

如果应用程序在 UART 字节流上自行设计协议,常会加入帧头、长度、数据、校验和帧尾。这些字段帮助接收程序寻找边界、确认长度和检查内容,但它们都是开发者自定义的应用层格式。

CAN 数据帧并不是这一格式的固定翻版。一个标准 CAN 数据帧在线路上依次包含:

帧起始 → 仲裁段 → 控制段 → 数据段 → CRC 段 → ACK 段 → 帧结束

其中:

  • 应用程序/驱动主要设置标识符、标准或扩展格式、数据帧或远程帧、DLC 和数据;
  • CAN 控制器负责发送 SOF、参与逐位仲裁、生成并校验 CRC、插入/删除填充位、处理 ACK 和错误状态;
  • CAN 收发器只负责控制器逻辑电平与 CANH/CANL 差分电平之间的转换,它不理解“温度”“命令”等业务含义。

因此,“辅助字段保证传输准确”只能作为直观概括。CRC 能检测许多传输错误,ACK 能确认至少有接收节点正确看到了帧,但它们都不能单独保证业务数据一定被目标程序采用或处理。

2.3 数据帧的构成解析

视频复习的 AA BB 示例是以前课程中的自定义串口/应用层帧,不是 CAN 总线在线路上固定存在的格式。按视频给出的字段,可整理为:

AA BB | 00 01 | 05 | CRC(2 字节) | 55 66
帧头    数据长度   数据    校验字段       帧尾
字段示例长度示例含义
帧头2 字节固定为 AA BB,帮助接收程序寻找一帧的开头
数据长度2 字节00 01 表示后面有 1 字节数据;这里还隐含了该自定义协议规定的字节序
数据1 字节视频示例值为 05,即十进制 5
CRC2 字节按该自定义协议指定的算法和覆盖范围计算;只知道“2 字节”还不能确定具体算法
帧尾2 字节固定为 55 66,帮助检查一帧的结束位置

正确顺序是“帧头 → 长度 → 数据 → CRC → 帧尾”,原笔记把帧尾提前列在长度之前属于整理错误。更重要的是,这些固定值和字段长度只对当时约定的协议有效,不能推广成所有串口协议,更不能拿它们代替 CAN 控制器生成的帧格式。

2.4 其他帧类型简介

  • **数据帧:**发送一个 CAN 标识符所代表的数据,是课程实验中最常使用的类型。数据字段可以为 0 字节,并非必须至少有 1 字节。
  • **远程帧:**原笔记的“遥控帧”是术语识别错误。它不是用来承载“遥控指令”,而是以某个标识符请求相应数据帧;它没有数据段。CAN FD 已取消远程帧,本节说的是 Classical CAN。
  • **错误帧:**CAN 控制器发现位错误、填充错误、CRC 错误、格式错误或 ACK 错误等情况时,按协议发送错误标志。它不是应用程序正常发送的一包“错误通知数据”。
  • **过载帧:**形式上与活动错误标志相似,用于推迟下一数据帧或远程帧的开始;应用程序通常不直接构造它。
  • **帧间隔:**上一帧结束到下一帧开始之间的协议间隔,不是带业务负载的普通“帧”。其中的间歇(Intermission)至少包含 3 个连续隐性位。

三、数据帧

3.1 数据帧的构成

11 位标识符的标准数据帧可以按下面的顺序阅读:

┌─────┬────────────────┬────────────────┬──────────────┬──────────────────┬────────────┬─────────┐
│ SOF │ 仲裁段          │ 控制段          │ 数据段        │ CRC 段           │ ACK 段    │ EOF     │
│ 1位 │ ID 11位 + RTR  │ IDE+r0+DLC(4位)│ 0~64位       │ CRC 15位+界定符 │ 槽+界定符 │ 7位     │
└─────┴────────────────┴────────────────┴──────────────┴──────────────────┴────────────┴─────────┘

这里的 7 个段才是标准 CAN 数据帧的协议结构;不存在 UART 示例里的固定 AA BB 帧头或 55 66 帧尾。

若数据长度为 N 字节,标准数据帧的名义长度为 44 + 8N 位,所以 8 字节标准数据帧为 108 位;扩展数据帧为 64 + 8N 位。这个长度没有计入位填充,也没有计入帧间隔,因此不能直接用“108 ÷ 位率”当作所有 8 字节帧的实际总线占用时间。

从 SOF 到 CRC 序列末尾采用位填充规则:发送端每出现 5 个连续同值位,就插入 1 个相反值的填充位,接收端再自动删除。填充位用于制造同步边沿,不属于字段的名义位数;若接收端在应出现相反位的位置仍看到相同电平,就会检测到填充错误。

3.2 数据帧各段功能

段标准数据帧中的长度功能主要由谁处理
帧起始 SOF1 位用 1 个显性 0 表示帧开始,并让节点在总线由空闲隐性变为显性时同步控制器发送/检测
仲裁段12 位11 位标识符决定消息含义与仲裁优先级;RTR 区分数据帧和远程帧程序配置,控制器逐位仲裁
控制段6 位IDE、保留位 r0 和 4 位 DLC,说明格式及数据长度程序配置,控制器编码/解析
数据段0~64 位携带 0~8 字节业务数据程序提供/读取
CRC 段16 位15 位 CRC 序列用于检错,随后 1 位 CRC 界定符形成格式边界控制器自动计算/校验
ACK 段2 位ACK 槽供接收节点确认正确接收,ACK 界定符结束该段各节点控制器共同完成
帧结束 EOF7 位7 个连续隐性位表示数据帧结束控制器发送/检测

SOF 是显性位,即逻辑 0。总线空闲时保持隐性 1,所以 SOF 产生的跳变既标记一帧开始,也为各节点的位时序提供同步边沿。

3.3 仲裁段: ID与rtr值

标准数据帧的仲裁段由 11 位标识符和 1 位 RTR 组成。

1. 标识符不是天然的设备地址

CAN 标识符首先描述“这条消息是什么”,同时决定它参与仲裁时的优先级;它不天然等于发送节点地址,也不天然等于接收节点地址。总线上的所有节点都能看到报文,各接收控制器再通过过滤器决定是否把某个 ID 交给软件。项目可以自行规定某个 ID 只有一个节点发送,但那是上层通信设计,不是 CAN 帧格式自动赋予的“身份证号”。

标准标识符范围是 0x000~0x7FF,因为 11 位最多表示十进制 2047。视频举出的 0x888 超过 0x7FF,不能作为 11 位标准 ID;它可以落在 29 位扩展 ID 的数值范围内。

2. 数值越小,仲裁优先级越高

发送节点在发送每一位的同时监视总线。显性 0 会覆盖隐性 1;某节点发出隐性位却读回显性位,就知道自己输掉仲裁并停止本次发送。由于 ID 从高位开始发送,数值更小的 ID 会更早给出显性 0,因此优先赢得总线。这种退出不会破坏胜出帧,失败节点可在总线重新空闲后再次尝试。

3. RTR 区分数据帧和远程帧

  • 数据帧的 RTR 为显性 0;
  • 远程帧的 RTR 为隐性 1。

如果同一 ID 的数据帧和远程帧同时竞争,总线在 RTR 位置呈现显性 0,所以数据帧优先。远程帧没有数据段,它只是请求同一 ID 的数据帧;其 DLC 应与所请求数据帧的数据长度一致。

3.4 控制段: IDE、DLC与数据⻓度

原笔记后文多次写成 DRC,正确名称是 DLC(Data Length Code,数据长度码)。

对本课的 11 位标准帧,控制段共 6 位:

IDE(1位) | r0(1位) | DLC(4位)
  • IDE = 0 表示基本/标准格式,使用 11 位标识符;
  • r0 是保留位,发送时由控制器按规范处理,应用程序不要拿它传业务信息;
  • DLC 表示后续数据段含多少字节。Classical CAN 数据帧的有效负载为 0~8 字节,课程编程时 DLC 应使用 0~8。

DLC 是 4 位字段,物理上能编码 0~15,但在 Classical CAN 中 9~15 不会把数据段扩展到 9~15 字节;一些经典 CAN 规范还规定接收器不应仅因 DLC 大于 8 就报告错误。实际使用 STM32F103 bxCAN 时,应按硬件接口要求把数据长度限制在 0~8。CAN FD 对 DLC 使用另一套映射,才能表示最长 64 字节,这不是本课 F103 bxCAN 的帧格式。

扩展帧的结构不能简化成“把标准帧的 11 位 ID 直接换成 29 位”。29 位标识符由 11 位基础部分和 18 位扩展部分组成,二者之间还插有 SRR、IDE;此时 RTR 也位于扩展标识符之后。也就是说:

  • 标准帧中,仲裁段为 11 位 ID + RTR,IDE 位在控制段开头;
  • 扩展帧中,仲裁段包含 11 位基础 ID + SRR + IDE + 18 位扩展 ID + RTR,控制段随后为 r1 + r0 + DLC。

课程说“IDE 为 1 对应 29 位扩展帧”的结论正确,但理解位图时必须同时注意上述字段位置变化。

3.5 数据段与CRC段

数据段

  • 数据长度由 DLC 决定,为 0~8 字节,也就是 0~64 位;0 字节数据帧是合法的。
  • 每个数据字节都按最高有效位(MSB)先发送。
  • 数据段才是应用程序真正提供的负载,但 ID + 数据 的业务含义仍由项目协议自行约定。

CRC 段

CRC 段包含 15 位 CRC 序列和 1 位隐性的 CRC 界定符。原笔记所说“把前面所有数据位相加”不正确:CRC 是把 SOF、仲裁段、控制段和数据段组成的位序列按生成多项式进行模 2 除法,余数形成 CRC 序列;Classical CAN 使用的 15 位 CRC 生成多项式为:

[ x^{15}+x^{14}+x^{10}+x^8+x^7+x^4+x^3+1 ]

发送控制器自动生成 CRC,接收控制器自动复算并比较,STM32 程序不需要手工拼出线上 CRC 字段。CRC 界定符不是“没有意义的占位符”:它必须为隐性,用来分隔 CRC 序列和 ACK 段;若该固定格式位被检测为显性,控制器会判定格式错误。

硬件 CRC 保护的是一帧在 CAN 链路上的传输。若固件升级文件被拆成许多帧,应用仍可能需要对分包序号、总长度或完整镜像另做校验;不能因为每帧有 CAN CRC,就认为整个文件传输一定完整且顺序正确。

3.6 ACK段与帧结束

ACK 段由 ACK 槽和 ACK 界定符各 1 位组成:

  1. 发送节点在 ACK 槽发送隐性 1;
  2. 正确接收到该帧且能够参与总线通信的接收节点,会在同一位置发送显性 0;
  3. 发送节点若读到显性 0,便知道至少有一个节点无帧级错误地收到了报文;
  4. 所有节点在 ACK 界定符处都应发送/看到隐性 1。

ACK 只证明“至少有一个节点正确接收了协议帧”,并不说明是哪一个节点,也不保证目标应用已经通过过滤器接收、读走或成功处理业务数据。即使一帧随后被接收过滤器丢弃,只要节点在协议层正确接收,它仍可参与 ACK。因此需要业务结果确认时,应另设计响应报文、序号或超时机制。

若发送节点在 ACK 槽仍读到隐性 1,会检测到 ACK 错误,并通常依据控制器状态再次发送。只有一个正常模式节点的 CAN 网络没有其他节点提供 ACK,因此即使接线端接正确也可能不断重发;调试时应检查另一节点是否上电、位率和位时序是否一致、是否处于静默/总线关闭状态,以及收发器和 CANH/CANL 接线是否正常。

帧结束 EOF 由 7 个连续隐性位组成。它后面还有帧间隔,其中间歇至少为 3 个隐性位;这 3 位不属于数据帧的 EOF,也不计入前文 44 + 8N 的名义帧长。

最后把程序员最需要把握的边界归纳为:

程序提供:ID、标准/扩展格式、数据/远程类型、DLC、数据
硬件处理:SOF、逐位仲裁、位填充、CRC、ACK、EOF、错误检测与重发状态
应用另管:消息含义、目标节点、分包、超时、业务应答、整包校验

参考资料

  • 课程配套 CAN总线入门书:核对第 8 章的五种帧类型、数据帧七个段、标准帧/扩展帧位图、DLC、CRC、ACK、EOF,以及远程帧结构。
  • ST 官方 RM0008 参考手册:核对 STM32F103 bxCAN 的标准数据帧 44 + 8N 位、扩展数据帧 64 + 8N 位及 0≤N≤8。
  • CAN in Automation 官方 Classical CAN 说明:核对标识符的消息内容/优先级含义、广播方式、ACK、29 位扩展标识符和 3 位 Intermission。
  • CAN in Automation 官方 CAN 术语表:核对远程帧、RTR、DLC、ACK 槽/界定符和错误类型等术语。