📚 学习目标:读完本文,你将理解CAN的五种帧类型,掌握数据帧的详细结构,理解位填充机制,以及遥控帧、错误帧、过载帧的作用。

⏱️ 预计学习时间:25-30分钟

📋 前置知识:建议先阅读前两篇文章,了解CAN基础概念和物理层知识


1. 写在前面

数据链路层不关心电压,它关心的是位(Bit)和帧(Frame)

如果说物理层解决了"怎么把0和1发出去"的问题,那么数据链路层解决的就是"如何把这些0和1组织成有意义的报文"的问题。


2. CAN 的五种帧类型

CAN 规定了五种帧类型:

帧类型 用途
数据帧 发送设备主动发送数据(广播式)。两种格式:标准格式(11 位 ID)和扩展格式(29 位 ID)
遥控帧 接收设备主动请求发送方的数据(请求式)。两种格式:11 位 ID 和 29 位 ID
错误帧 某个设备检测出错误时,向全总线"报警"
过载帧 接收设备通知其尚未做好接收准备
帧间隔 用于将数据帧及遥控帧与前面的帧分离开

2.1. 数据帧

这是最常用的帧,负责携带真正的协议数据。总线上 90% 以上都是该类型的帧。

2.1.1. 数据帧结构解析

段名 描述
空闲段 - 总线为隐性电平 1,所有节点都不操作总线。当总线出现连续 11 个隐性 1 后,认为总线空闲
帧起始段 SOF (Start of Frame) 显性 0,破坏总线空闲状态,告诉所有人:我要开始说话了
仲裁段 ID 11 位,注:禁止高 7 位全为隐性电平 1
RTR (Remote Transmission Request) 用于区分数据帧还是遥控帧,数据帧为显性电平 0,遥控帧为隐性电平 1。RTR 位也算作仲裁段,也就是相同 ID 的数据帧的优先级大于遥控帧
控制段 IDE (ID Extension) 用于区分标准格式还是扩展格式,标准格式固定位显示 0,扩展格式为隐性 1
r0:保留位 显性 0
DLC (Data Length Code) 数据长度,范围为 0-8。对于遥控帧,DLC 指的是请求的数据长度
数据段 - 数据内容,长度与 DLC 对应
CRC 段 CRC 对所有的数据位进行 CRC 计算,包括帧起始、仲裁段、控制段、数据段
CRC 界定符 必须是隐性电平
ACK 段 ACK 槽 发送方发送完毕后,释放总线,隐性电平 1,接收方若接收正确需要在此位回复显性电平 0,此时发送方读取 ACK 槽为 0,则表示收到 ACK
ACK 界定符 接收方释放电平,隐性电平
结束段 EOF (End of Frame) 7 个隐性 1

2.1.2. 补充说明

  1. 扩展格式中也存在 SOF
  2. 扩展格式中,SRR 作用是替代 RTR,为隐性 1
  3. 对于数据帧,标准格式和扩展格式的前 11 位相同,由于数据帧 RTR 为显性电平 0,扩展帧的 SRR 为隐性电平 1,标准格式的优先级高于扩展格式。若标准格式是遥控帧,标准帧的 IDE 为显性电平 0,扩展帧为隐性电平 1,仍是标准帧的优先级高

2.2. 遥控帧

遥控帧基本上与数据帧类似,有几个点需要注意:

  • RTR 区分是遥控帧还是数据帧
  • 遥控帧没有数据段
  • DLC 表示请求发送的数据长度

为什么有数据帧了还要遥控帧?
对于一些使用频率较低的帧,一直广播比较占总线资源,不广播的话在需要使用的时候又无法获取,所以出现了遥控帧,当某节点需要该报文信息时,通过广播的方式发送遥控帧,告诉发送方我需要这一帧的内容,那么发送方就发送这一帧的内容。

但是在实际项目中很少使用该帧,倾向于定时发送周期报文。


2.3. 错误帧

总线上所有的节点都会检测总线的数据,一旦发现位错误、填充错误、CRC 错误、格式错误、应答错误等,这些设备便会发送错误帧来破坏数据,同时终止当前的发送设备。

当节点检测到总线错误时,有两种情况(主动错误/被动错误在后文会详细描述):

  • 向总线发送连续 6 个显性电平 0,故意违反位填充规则,会使得总线无法正常传输信号(主动错误
  • 向总线发送连续 6 个隐性电平 1,不会影响别人通讯(被动错误

最后再发送 8 个隐性电平 1,给总线一点"喘息时间",让大家重回起跑线。

为什么会有错误重叠部分?

当节点 A 检测到错误时,不一定总线上所有的节点都检测到错误了,可能还有些报文在正常发送。譬如节点 B 要发送 01xxx,当发送到 1 时,回读发现是 0,发现位错误,发送连续 6 个显性电平 0。此时可以看到总线上实际上有 8 个显性电平 0。若此时还有节点 C 也在检测总线,发现连续 6 个 0 后,以为出现了填充错误,也要报错,发送连续 6 个显性电平 0,那总线上就有 12 个显性电平 0。若还有节点 efg 等,最迟也就是连续检测到填充错误后上报错误。所以会有错误标志重叠,且最多是 6 个。

节点A0 0 0 0 0 0 1 1 1  1  1  1  1  1
节点B0 1 0 0 0 0 0 0 1  1  1  1  1  1  1  1
节点C0 0 0 0 0 0 0 0 0  0  0  0  1  1  1  1  1  1  1  1
时间轴------------------------------------------------------->
       1 2 3 4 5 6 7 8 9 10 11 12  

问题:节点A处于被动错误中,节点B发现总线错误,进入主动错误,此时会发送连续6个0,其他节点也会检测到填充错误,然后继续发送主动错误,那么节点A在这个过程中是如何表现的?


2.4. 过载帧

接收方因来不及处理缓冲区的报文,其可以发出过载帧,延缓发送方的数据,以平衡总线负载,避免数据丢失。与错误帧相同的帧格式,但是不会增加错误计数。

注意 1:现代的 CAN 总线上基本上不会出现过载帧,因为 MCU 处理速度很快,对于 CAN 报文处理比较快,而且存在邮箱、FIFO 等机制,所以无需过载帧。

注意 2:虽然过载帧也是 6 个显性电平,但是不会出现填充错误。因为错误帧发生在报文中间(数据段、CRC 段等),在这些地方才会有填充错误。而过载帧发生在报文结束后的间隙,在帧间隔期间,此时位填充不生效。


2.5. 帧间隔

将数据帧、远程帧与前面的任何帧(数据、遥控、错误、过载帧)分隔开。

为什么是 3 个间隔?

无论前面是错误帧、数据帧、遥控帧、过载帧,我们可以看出,最后 8 位都是隐性电平,而总线空闲时要起 11 个隐性电平,刚好是 11 个隐性电平,之后就是总线空闲状态,节点可以发送报文。若在间隔期间检测到显性电平,则认为是过载帧,之后也是如此,需要再等 11 个隐性电平才可以发送报文。

延迟发送什么时候生效?

在被动错误状态下,发送方发送完消息后,需要额外等待 8 个隐性电平。


3. 位填充机制

上面我们描述了 CAN 帧的五种类型,出现如下情况怎么办?

  • 我们发送的报文内容如果就是 0x00000000,那 CAN 线上如何区分这是数据还是错误帧呢?
  • 若内容是 0xFFFFFFFF,出现了连续 11 个隐性电平,是总线空闲了么?
  • CAN 是异步通信,没有时钟线,如果总线一直是一种状态,接收双方晶振如果有误差,是否能够准确接收数据?因此引入了位填充机制

3.1. 规则

发送方每发送连续 5 个相同电平后,自动追加一个相反电平的填充位。接收方检测到填充位,会自动移除填充位,恢复原始数据。

3.2. 作用

  • 防止数据波形长时间不变化,防止位读取不准确(若没有填充位,连续发送 64 个 1,如果波特率有一点偏移,采样时机出错,导致读取的数据出现问题)
  • 跳变还可以再同步,使得采样更加精确
  • 区分数据(遥控)帧和错误帧,过载帧上位填充不生效
  • 保持数据流活跃,防止被误认为总线空闲

3.3. 提示

填充规则是在控制器自动完成的,作用范围是 SOF 开始到 CRC 段结束。ACK 槽为 0,前后的界定符都是 1,必然存在跳变,否则就是出错,所以不会在 CRC 段之后出现位填充错误。CAN 控制器一般是集成到芯片内部的,属于片上外设,STM32 中的 bxCAN、RH850 中 RSCAN-FD 等,包括协议解析、仲裁、CRC、填充机制都在控制器中由硬件自动完成。

示例:发送 10000011110,总线上实际是 1000001111100


4. 总结

通过本文,我们了解了:

CAN的五种帧类型:数据帧、遥控帧、错误帧、过载帧、帧间隔

数据帧的详细结构:从SOF到EOF的完整解析

位填充机制:为什么需要位填充,如何工作

各种帧的作用:什么时候使用哪种帧


5. 下篇预告

了解了帧结构,接下来我们要学习CAN最核心的机制:仲裁机制错误处理。这是理解CAN如何实现多主通信和错误恢复的关键。

下一篇《【CAN通信进阶】数据链路层(下):仲裁机制与错误处理》 将深入讲解:

  • 非破坏性仲裁机制
  • 优先级规则
  • 错误检测与恢复
  • Bus Off机制

敬请期待!


6. 互动时间

  • 你对哪种帧类型最感兴趣?
  • 位填充机制理解了吗?
  • 在实际项目中遇到过帧格式相关的问题吗?

欢迎在评论区留言,我会及时回复!


专栏目录:

  1. ✅ 【CAN通信入门】万字长文带你理解CAN:从汽车"减肥"说起
  2. ✅ 【CAN通信进阶】物理层:两根线如何传输0和1?
  3. ✅ 【CAN通信进阶】数据链路层(上):帧结构全解析(本文)
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐