目录
1. CAN总线数据帧格式
2. 数据帧
2.1 帧起始
2.2 仲裁段
2.3 控制段
2.4 数据段
2.5 CRC 段
2.6 ACK段
2.7 帧结束
2.8 总结
3. 遥控帧
4. 错误帧
4.1 错误标志
4.1.1 主动错误标志
4.1.2 被动错误标志
4.2 错误界定符
5. 过载帧
6. 帧间隔
7. 位填充
1. CAN总线数据帧格式
帧类型 | 用途 |
数据帧 | 发送设备主动发送数据 |
遥控帧 | 接收设备主动请求数据(请求式) |
错误帧 | 某个设备检测出错误时向其他设备通知错误 |
过载帧 | 接收设备通知其尚未做好接收准备 |
帧间隔 | 用于将数据帧及遥控帧与前面的帧分离开 |
2. 数据帧
数据帧由 7 个不同的位场组成:帧起始、仲裁场、控制场、数据场、CRC 场、应答场、帧结尾。数据场的长度可以为 0。
上图D和R分别代表:显性(0):Dominant(D),隐性(1):Recessive(R)。
上图表示在灰色部分只能发显性电平“0”,紫色部分可以放显性电平“0”或者隐性电平“1”,白色部分表示只能发隐性电平“1”。
其中黄框框住的部分表示的是这一段波形占多少位,例如1,表示1位,11表示11位,数组并不代表高低电平,电平是通过颜色来区分的:
扩展格式是后来新增的,扩展格式增加了ID位数,能承载更多种类的ID,
2.1 帧起始
它标志数据帧和远程帧的起始,由一个单独的“显性”位组成。只在总线空闲时,才允许站开始发送(信号)。
这里帧起始为显性电平(逻辑0)的原因,我们之前也说过CAN总线默认电平位逻辑1,若是此时起始帧也是隐性电平(逻辑1),那么并不知道什么时候开始发送的数据,因为你的默认状态和帧起始状态一致都是隐性电平,因此帧起始必须是显性电平(逻辑0),作用是打破总线空闲,开始一帧数据:
2.2 仲裁段
仲裁段包括识别符和远程发送请求位(RTR)。
识别符:识别符的长度为 11 位。这些位的发送顺序是从 ID-10 到 ID-0。最低位是 ID-0。最高的 7 位(ID-10 到 ID-4)必须不能全是“隐性”。
RTR 位:该位在数据帧里必须为“显性”,而在远程帧(遥控帧)里必须为“隐性”。主要是为了区分数据帧和遥控帧。
同种帧格式下的ID不能相同,例如数据帧已经有一个ID为0x111,那么同数据帧格式下,就不能在取0x111,不过遥控帧还能取0x111,可以通过RTR位进行区分。
不过需要注意,相同ID的数据帧和遥控帧,数据帧的优先级大于遥控帧。
除此之外,仲裁段的表现形式,在标准格式和扩展格式下也不同:
仲裁段的ID主要是为了区分数据,并且还用于区分优先级,当多个设备同时发送时,根据仲裁规则,ID小的报文优先发送,ID打的报文等待下一次总线空闲在重试发送,
标准格式的 ID 有 11 个位。从 ID28 到 ID18 被依次发送。禁止高 7 位都为隐性。(禁止设定:ID=1111111XXXX)
扩展格式的 ID 有 29 个位。基本 ID 从 ID28 到 ID18,扩展 ID 由 ID17 到 ID0 表示。基本 ID 和标准格式的 ID 相同。禁止高 7 位都为隐性。(禁止设定:基本 ID=1111111XXXX)
2.3 控制段
控制场由 6 个位组成,包括数据长度代码和两个将来作为扩展用的保留位。所发送的保留位必须为“显性”。接收器可以接收由“显性”和“隐性”任意组合在一起的电平。
这里的两个保留位,其实已经被用掉一个了,那就是IDE,IDE原来是r1位,不过后来升级给使用掉了,现在IDE位主要是为了区分升级前的版本还是升级后的版本。
同样的,控制段在标准格式和扩展格式的构成也有所不同:
数据长度代码:数据长度代码指示了数据场中字节数量。数据长度字节数必须为0~8字节,但接收方对 DLC = 9~15 的情况并不视为错误。
数据字节数 | 数据长度码 | |||
DLC3 | DLC2 | DLC1 | DLC0 | |
0 | 显性电平 | 显性电平 | 显性电平 | 显性电平 |
1 | 显性电平 | 显性电平 | 显性电平 | 隐性电平 |
2 | 显性电平 | 显性电平 | 隐性电平 | 显性电平 |
3 | 显性电平 | 显性电平 | 隐性电平 | 隐性电平 |
4 | 显性电平 | 隐性电平 | 显性电平 | 显性电平 |
5 | 显性电平 | 隐性电平 | 显性电平 | 隐性电平 |
6 | 显性电平 | 隐性电平 | 隐性电平 | 显性电平 |
7 | 显性电平 | 隐性电平 | 隐性电平 | 隐性电平 |
8 | 隐性电平 | 显性电平 | 显性电平 | 显性电平 |
2.4 数据段
数据段可包含 0~8 个字节的数据。从 MSB(最高位)开始输出。
2.5 CRC 段
CRC 段是检查帧传输错误的帧。由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)构成。
2.6 ACK段
ACK 段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成。
ACK槽的作用就是应答,发送方发送一帧数据,但他如何判断到底有没有设备收到呢?这需要靠ACK位来实现,发送方在发完一帧的主要内容后,在应答这一位时发送方释放总线,总线回归默认状态(隐性1),如果接收方收到数据,就会在ACK槽这一位主动出击,把总线在拉开使总线呈现显性0的状态。
发送方那个释放总线后,在ACK槽会读取总线状态,如果发送方读取显性0,那就证明有接收方接收数据,把总线拉开了,呈现显性0的状态;如果发送方读取隐性1,发送方就会认为没人读取到总线数据,说明发送失败,发送方可以配置自动重发,也可以不管,总之发送方需要知道发送状态就行。
发送单元的 ACK 段:发送单元在 ACK 段发送 2 个位的隐性位。
接收单元的 ACK 段:接收到正确消息的单元在 ACK 槽(ACK Slot)发送显性位,通知发送单元正常接收结束。这称作“发送 ACK”或者“返回 ACK”。
发送 ACK 的是在既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元 (发送单元不发送 ACK)。所谓正常消息是指不含填充错误、格式错误、CRC 错误的消息。
2.7 帧结束
帧结束是表示该该帧的结束的段。由 7 个位的隐性位构成。
2.8 总结
帧起始:数据帧开始的段(默认隐性电平“0”)。
仲裁段:区分数据功能,相当于一个数据的 ID 号,根据 ID 区分不同功能数据,并且根据大小区分帧优先级(帧ID小的优先级最高;不同类型数据同ID,数据帧大于遥控帧)。
RTR:远程请求位,用于区分数据帧还是遥控帧。
SRR:替代RTR,协议升级留下的无意义的位。
在总线空闲态,最先开始发送消息的单元获得发送权。
多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平(逻辑0)最多的单元可继续发送。(这也就是为什么最小的优先级最高的原因)
数据帧和遥控帧的优先级:具有相同 ID 的数据帧和遥控帧在总线上竞争时,仲裁段的最后一位(RTR)为显性位的数据帧具有优先权,可继续发送。
标准格式和扩展格式的优先级:标准格式 ID 与具有相同 ID 的遥控帧或者扩展格式的数据帧在总线上竞争时,标准格式的 RTR 位为显性位的具有优先权,可继续发送。
控制段:用于指定数据段的长度,并且留下两个保留位(IDE,r0)。
IDE:扩展标志位,用于区分扩展格式还是标准格式。
r0/r1:保留位。
DLC:指示数据有几个字节。
数据段:数据内容,可发送0~8个字节的数据。
CRC段:用于检查帧是否在传输过程发生错误,校验数据帧是否正确。
ACK段:判断是否正常接收。
CRC/ACK界定符:为应答位前后发送方和接收方释放总线留下时间。
帧结束:数据帧结束的段。
这里说一下扩展格式和标准格式的区别,扩展格式的出现,是因为标准格式仲裁段的11位ID不够用了,因此进行扩展出了18位的ID,到时为了保证协议不会出现大的出入,因此对RTR位和IDE位进行了修改:
其中的SRR位,是替代的标准格式的RTR位(这里插一下,下面会想起介绍仲裁,这里简单提一下,仲裁是先比较ID,后比较RTR,所以RTR必须在所有ID的后面),这里因为又加了18位的ID,因此RTR需要移到这18位ID的后面,这样就空出来了SRR的位置且此位置必须是隐性电平1(为了保证标准格式的优先级高于扩展格式的设计)。
IDE位,也就是控制段留下的两个保留位中的一位,这时就排上了用场,以前的控制段时r0和r1,此时将r1位拿出,赋予其新功能IDE位,用于区分是标准格式还是扩展格式,标准格式为显性0,扩展格式为隐性1。这样当数据走到IDE位,就知道后续是按照标准格式去判断还是按照扩展格式去判断(这里需要注意的一点是扩展格式的RTR位以后保留位已经恢复的r1,个人认为这一位相当于为后续如果扩展ID也不够用了的时候,进行进一步拓展保留的,继续套娃)。
3. 遥控帧
接收单元向发送单元请求发送数据所用的帧。遥控帧由6个段组成,遥控帧没有数据帧的数据段,RTR为隐性电平1,其他部分与数据帧相同。
遥控帧相比于数据帧,数据帧是发送方,主动、连续、有间隔的向外广播数据,不过这样会出现要是发送方一直广播,但是接收方只是隔一会才要一个数据,这样会造成资源的浪费。
而遥控帧则是接收方主动请求发送方发送广播数据,接收方进行接收,不过这也会出现一个问题就是发送方需要等接收方给它发送请求,才会发送,要是需要高速处理的数据,会占用大量CPU资源。
因此遥控帧多适用于数据频率较慢的情况,数据帧多适用于发送方数据发送频率较快的情况。
4. 错误帧
用于在接收和发送消息时检测出错误通知错误的帧。一旦发现“位错误”或“填充错误”或“CRC错误”或“格式错误”或“应答错误” ,这些设备便会发出错误帧来破坏数据,同时终止当前的发送设备。错误帧由错误标志和错误界定符构成:
4.1 错误标志
包括主动错误标志和被动错误标志两种。
4.1.1 主动错误标志
处于主动错误状态的单元检测出错误时输出的错误标志。设备默认处于出于主动错误状态。
当设备检测到发生错误,会连续发送6个显性位“0”,显性是拉开总线,总选又一个被拉开,就必然处于显性状态(“线与”特性,“0”和“1”相遇时,肯定显示“0”),这样就会破坏掉总线数据,其他设备检测到数据错误就会抛弃当前数据(所有数据全抛弃),若是主动错误产生太过频繁,说明这个设备不太可靠,设备就会进入被动错误状态。
4.1.2 被动错误标志
处于被动错误状态的单元检测出错误时输出的错误标志。
当设备检测到发生错误,会连续发送6个隐性位。隐性就是不去碰总线,那么总线状态就不会发生变化,就不会总线上别人发的数据,只会破坏自己发的数据(仅抛弃自己的数据)。
4.2 错误界定符
由8个隐性位构成。
5. 过载帧
过载帧是用于接收单元通知其尚未完成接收准备的帧。当接收方收到大量数据而无法处理时,其可以发出过载帧,延缓发送方的数据发送,以平衡总线负载,避免数据丢失。过载帧由过载标志和过载界定符构成:
过载标志:6 个位的显性位。过载标志的构成与主动错误标志的构成相同。
过载界定符:8 个位的隐性位。过载界定符的构成与错误界定符的构成相同。
6. 帧间隔
帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间隔。
间隔:3 个位的隐性位。
总线空闲:隐性电平,无长度限制(0 亦可)。本状态下,可视为总线空闲,要发送的单元可开始访问总线。
延迟传送(发送暂时停止):8 个位的隐性位。只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。
7. 位填充
位填充是为防止突发错误而设定的功能。发送方每发送5个相同电平后,自动追加一个相反电平的填充位,接收方检测到填充位时,会自动移除填充位,恢复原始数据。
发送单元的工作:在发送数据帧和遥控帧时,SOF~CRC 段间的数据,相同电平如果持续 5 位,在下一个位(第 6 个位)则要插入 1 位与前 5 位反型的电平。
接收单元的工作:在接收数据帧和遥控帧时,SOF~CRC 段间的数据,相同电平如果持续 5 位,需要删除下一个位(第 6 个位)再接收。如果这个第 6 个位的电平与前 5 位相同,将被视为错误并发送错误帧。
举个例子:
举例一 | 举例二 | 举例三 | |
即将发送 | 100000110 | 10000011110 | 0111111111110 |
实际发送 | 1000001110 | 1000001111100 | 011111011111010 |
实际接收 | 1000001110 | 1000001111100 | 011111011111010 |
移除填充后 | 100000110 | 10000011110 | 0111111111110 |
位填充的作用:
增加波形的定时信息,利于接收方执行“再同步”,防止波形长时间无变化,导致接收方不能精确掌握数据采样时机。
举个例子,下面一句话“啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊”你告诉别人把听到的“啊”个数写下来,可能会出现多写或者少写的情况,但是“啊啊啊三啊啊啊三啊啊啊三啊啊啊三啊啊啊三”这样就能更加准去的知道实际发送的“啊”的数量,实际接收把“三”去掉就行了。
将正常数据流与“错误帧”和“过载帧”区分开,标志“错误帧”和“过载帧”的特异性。
保持CAN总线在发送正常数据流时的活跃状态,防止被误认为总线空闲。
CAN总线_时光の尘的博客-CSDN博客
CAN总线物理层特性详细分析-CSDN博客