CAN数据帧
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 |
| CRC | 2 字节 | 按该自定义协议指定的算法和覆盖范围计算;只知道“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 数据帧各段功能
| 段 | 标准数据帧中的长度 | 功能 | 主要由谁处理 |
|---|---|---|---|
| 帧起始 SOF | 1 位 | 用 1 个显性 0 表示帧开始,并让节点在总线由空闲隐性变为显性时同步 | 控制器发送/检测 |
| 仲裁段 | 12 位 | 11 位标识符决定消息含义与仲裁优先级;RTR 区分数据帧和远程帧 | 程序配置,控制器逐位仲裁 |
| 控制段 | 6 位 | IDE、保留位 r0 和 4 位 DLC,说明格式及数据长度 | 程序配置,控制器编码/解析 |
| 数据段 | 0~64 位 | 携带 0~8 字节业务数据 | 程序提供/读取 |
| CRC 段 | 16 位 | 15 位 CRC 序列用于检错,随后 1 位 CRC 界定符形成格式边界 | 控制器自动计算/校验 |
| ACK 段 | 2 位 | ACK 槽供接收节点确认正确接收,ACK 界定符结束该段 | 各节点控制器共同完成 |
| 帧结束 EOF | 7 位 | 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 位组成:
- 发送节点在 ACK 槽发送隐性
1; - 正确接收到该帧且能够参与总线通信的接收节点,会在同一位置发送显性
0; - 发送节点若读到显性
0,便知道至少有一个节点无帧级错误地收到了报文; - 所有节点在 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 槽/界定符和错误类型等术语。