(1)
协议种类 | CAN | CAN FD |
最大波特率 | 1M/s | 8M/s |
常用波特率 | 500k/s | 5M/s |
硬件成本 | 较低 | 较高 |
(1)CAN标准帧和扩展帧的数据段0-8Byte
(2)CANFD的标准帧和扩展帧数据段长度是0-64Byte
CAN有 1:数据帧,远程帧 , 错误帧,扩展帧
CAN FD 有数据帧 错误帧 扩展帧
如下图所示,other higher speed 指的是数据段,这也是CANfd比较神奇的地方,就是说在SOF-DLC区间内以较低的速率发送数据,而在数据段波特率突然提升,CRC-END阶段又恢复低速率运行。
CANfd在软件开发阶段,需要配置两种不同的波特率以适应数据段和其他段不同的波特率。
CANFD标准帧格式
1:SOF帧开始:
帧中段说明 | 位数 | 性质与说明 | CAN标准帧 与CANfd扩展帧 |
极性 |
SOF |
1bit | 表明帧起始位 | 都具有 | 四种不同的帧格式中都是显性0 |
RRS/RTR/SRR | 1bit | 远程请求代替位 | CAN标准帧中叫RTR(远程请求位) CAN扩展帧中叫SRR,代替远程请求位, |
标准数据帧是:显性 标准遥控帧(远程帧)是隐形 CANFD扩展帧是隐性 canfd标准帧 |
IDE | 1bit | 拓展帧标识位 | 用来标识该帧是否为拓展帧 | CAN和CANfd是一样的 |
FDF/R0/低18bit最高bit | 1bit | CANFD标志位 标准帧r0保留位,一定要维持0的显性状态 can扩展帧的低18bitID的最高位 |
用来标识是否为是CANfd帧 |
下面这两张图,分别给出了CAN帧和CANFD 帧的标准形式和扩展形式
给大家提出几个问题
1:请总结 CANFD扩展帧格式与标准帧格式的不同
2:总结CAN 帧标准格式和扩展格式之间的区别和联系
3:总结CAN标准格式和CANFD标准格式之间的区别和联系
4:总结CAN 扩展格式和CANfd扩展格式之间的区别和联系
注意点,我们可以观察到CAN帧和CANFD帧,DLC都为4bit,CAN帧最大发送字节为8Byte,4bit能完全表示。
但是CANFD的DLC,也只有4bit,4bit最大能表示十进制数15。fd最大发送字节为64该如何表示
前8bit是和传统CAN一样的 |
||||
二进制 | 表示数据段长度(Byte) | |||
1 | 0 | 0 | 1 | 12 |
1 | 0 | 1 | 0 | 16 |
1 | 0 | 1 | 1 | 20 |
1 | 1 | 0 | 0 | 24 |
1 | 1 | 0 | 1 | 32 |
1 | 1 | 1 | 0 | 48 |
1 | 1 | 1 | 1 | 64 |
前4个,二进制数值每增加1,代表长度+4。第5位+8,第6个+16,第7个+32。成倍增加
延伸一下,如果我们使用设备,模拟发送CAN_FD帧,DLC必须要是(0-8||12||16||20||24||32||48||64)
如果有人告诉你,他设计的CAN_fd帧数据段长度为15,只能说明这个人是完全不懂CAN_FD的。
通过以上的比较,我们能大致得出来,CAN标准帧&CAN拓展帧,CANFD标准帧和CANFD拓展帧,CAN标准远程帧&CAN拓展远程帧。下图也表示了,他们之间的关系。
首先总结所有帧结构的相同点:
(1)只要是CAN/CANfd帧,[SOF----ID(11bit)],任何帧之间的结构都一样。
(2)只要是CAN/CANfd帧 [DLC---CRC),任何帧之间的结构都一样。
(3)只要是CAN/CANfd帧(CRC-EOF],任何帧之间的结构都一样。
首先总结所有帧结构的不同点:
我想了一下,感觉无论从那一方面开始介绍帧的不同点都显得比较杂乱。我们尝试从CAN帧的发展历史来代入进来理解,从实际应用角度去切入。这会让我们更加理解为什么各种CAN帧之间的不同,以及为什么不同。
首先来看,最简单的CAN标准数据帧 sof+(11bitID)+RTR(远程标志位:1隐形代表:远程帧)+IDE(拓展帧标致位:1=是拓展帧)+r0+DLC+Data+CRC(15bit)+CRC界定符+ACK(1bit)+ACK界定符+EOF(7bit隐形位)
首先CAN被最开始定义出来时,规范的设计者,先设计了 帧起始+仲裁段+控制段+数据段+CRC段+ACK段+帧结束段。的结构模式
帧起始段,暂时只要理解为一个位的显性位。
仲裁段。一开始设计了11Bit,位,最大能表示0x7EF(2031个ID细心的同学发现了,不对啊!11bit最大不是能表示0x7FF,这是因为11位ID,的高7bit不能全置1的原因导致的),ID段首先被发送到CAN总线上。接收节点根据事先设定,决定接收或者不接受这个帧。
当节点决定接收这个文件后,立马就要接收控制段的信息,假设CAN被开发出来的时候,控制段的前三位都是预留位,程序对该段信息直接忽略,开始接收DLC,和数据段(这才是我们需要的最重要的信息),接收完数据段后,程序开始接收CRC校验段(校验范围sof--接收的数据段最后一个字节)。然后自己开始计算CRC。最后判断 (接收的CRC) =(自身计算的CRC),来决定是否在ACK端应答。最后发送帧结束标志。至此一个帧算是正式的发送且被成功接收。
以上过程都很完美。一直过了好几年,出现了以下两种情况:
(1)汽车电子发展的越来越快,一个总线上挂载的节点越来越多,ID数量不够用了(本质上0x7EF(2031个ID是够用的)但是实际应用中 为了维持系统的稳定性,不会依次选取所有的ID),这是需要扩展ID,于是大家坐一起商量了一下,决定把ID再增加18BIT。就如图所示:扩展之后532676607位,绝对是够用了。
这还让我想到了通讯界一个很有意思的问题,就是IP地址,当初设计ip地址的时候,ip地址为4个Byte,也就是4294967295个IP可以用,出去一些特定用途的IP外(如广播,组播用途),其他IP都可以分配给个人或公司团体,大家都认为这些IP地址以及足够使用了,结果没想到互联网仅仅过了几十年的发展,目前这些IP已经快分配完了。于是大家又是想出了CIDR,又是想出了IPV6协议(也就是6个Byte的ip)。
说上面一段的原因,我是想说,很多时候,在制定标准时,好像很合理,但是随着技术的发展很多事情的发展,会大大出乎最初的意料。有时防患于未然,虽然要牺牲掉一部分性能和效率,很多时候也不失为一种合理的选择。
(2)总线上的负债率的不断提升(这里解释下,总线负债率,可以简单理解成在单位时间内(如1s),有数据的段所占用的时间 / 总线上有数据的段所占用的时间+空闲的段占用的时间)如1s内有一半的时间是有数据段,一半时间是没有数据段。那么总线的负载率就是50%。工程师们就开始研究,如何在不影响通讯的情况下,减少总线负载率。于是CAN远程帧便应用而生。远程帧的全称是远程请求帧。帧结构只包括帧头(帧起始段+仲裁段+控制段)。
它应用的场景如下:如锁车系统,当锁车系统接收到钥匙上的锁车信号时,锁车系统必须要知道发动机状态是否已经关闭,车速是否为0,车上所有灯是否关闭。这些条件不满足时(现在好多车型甚至能够判断车内是否还有人,发出信号的钥匙是否在车内),必须不能锁车。但是平常情况下,锁车系统根本不需要去接收这些信号。故工程师们便想出了,利用远程请求帧。
工作过程如下:
当收到锁车信号时,发送相关请求帧(假设发动机状态和车速信号在0x121帧上,车灯信号在0x345帧上),锁车系统发出这些帧的帧头,当发动机系统或车灯系统接收到这些远程请求帧后,会立即把这些信号发送出来(比如周期100ms发送10帧)。此时锁车系统就能够知道,锁车条件是否满足了。
但是我们想一下,远程请求帧,能不能和请求的帧,帧头是一模一样的,不能。我们从其他需要接收,发动机状态和车速信号在0x121,车灯信号在0x345的模块去考虑,假如我们发送远程请求帧头和被请求数据的帧头一样,就会导致混乱,其他模块根本没有请求这些数据,怎么自己就发出来了?
于是还记得,我们上一段介绍can数据帧时的“假设CAN被开发出来的时候,控制段的前三位都是预留位,程序对该段信息直接忽略”这就起到作用了,工程师们于是就将从左往右的第一个bit,命名为RTR,于是顺带着又将第二个bit位命名为IDE位。第三位依然保留称为r0。
此时看似万事大吉了,可是注意看细节,最新的CAN数据帧标准中,把11位ID和RTR位,都算到了仲裁段中去了。是不是意味着,远程帧和数据帧是可以兼容的,且数据帧比远程帧的优先级要高
:RTR在can标准数据帧中,是0(显性)。在远程帧是1(隐性)
这样做的好处在于,假如远程请求帧会连续发送三帧,但是目标模块反应很快,在第二帧远程请求帧刚刚发出来的时候,被请求的数据帧同时发出。此时把RTR放在仲裁段,就可以知道,返回的数据帧优先级更高。这时远程请求帧就因为仲裁失败,停止发送。返回的数据帧优先级高,继续发送。
此时看第二个问题,我们已经将预留位的第一位设置为RTR标志位,那么现在来解决11位ID不足的问题
此时又有问题有来了,can扩展数据帧已经定义好了,那么还要不要把CAN的扩展远程请求帧也定义出来。
我们初步的方案是将11位ID,扩展为(11+18)=29Bit,最简单的方法是不是在箭头处,直接添加18Bit,直接组合成29Bit的仲裁段。这样做的看起来并不存在什么问题!
但是还是兼容性的问题,直接在11bit后添加18bitID, 的情况下CAN标准数据帧和CAN扩展数据帧同时存在于一条can总线上,我问大家一个问题
can标准数据帧ID=0x001; id二进制为 0000 0000 001
can扩展数据帧的ID=0x001;id的二进制为 0000 0000 0000 0000 0000 0000 0000 1
根据仲裁从最高位开始的协议,明显的CAN扩展帧的优先级更高,进一步思考,
can标准数据帧ID=0x001; id二进制为 0000 0000 001
can扩展数据帧的ID=0x3FFF;id的二进制为 0000 0000 0001 1111 1111 1111 1111 1
can扩展数据帧0x3FFF的优先级比can标准数据帧ID=0x001的优先级还要高。这明显不是我们想要的。我们设计CAN扩展帧就是为了弥补ID不够用的作用的,理想的情况下,
应该: can标准数据帧0x3EF的优先级>CAN扩展帧的0x...0001的,于是我们将IDE位移入SOF之后,直接先判断是否是扩展帧。是扩展帧直接仲裁失败,退出发送。
但是此时所有的软件工程师又立马要跳出来,全体反对了,你这么随心所欲的修改,把CAN标准帧的结构都改掉了,我要是想在原有的软件架构下,想再兼容CAN扩展帧,我连原先处理CAN标准帧的程序都要全部修改,反对反对!坚决反对!!!!!!
于是 我们尝试把18bit的放到r0之后,这样做又会有两个问题。
1:当标准数据帧的11Bit>扩展帧的前11Bit。时,此时标准帧的优先级将低于扩展帧
2:当标准远程帧的11Bit=扩展帧的前11Bit,时,因为扩展帧的RTR位必须为隐形,此时将导致,此种情况下,扩展帧的优先级大于标准帧的远程帧。
前11位相同的情况下,我们必须保证优先级:标准数据帧>标准远程帧>扩展数据帧>扩展远程帧
此时,我们又将扩展帧中RTR,放到18Bit的ID之后,这样的话,又会带来代码改动的问题,于是又在IDE前填充了一位,称为SRR(远程请求代替位),扩展帧中这一位必须为1(隐形位)。
真是历经九九八十一难,终于把扩展帧的结构给定下来了。
闲下来的工程师们,决定在对扩展帧的结构做一点优化。把r0这个不用的位,移动到RTR之后,又为了以后的扩展,又添加了 一个新的预留位,最终结构如下。