[车联网] CAN总线与DBC详解

[车联网] CAN总线与DBC详解

0 序

1 CAN总线-概述

1.0 简介

CAN是控制器局域网络(Controller Area Network, CAN)的简称,是一种 ISO 国际标准化的、能够实现分布式实时控制的串行通信网络。

应用领域:其广泛应用于汽车、工业自动化/工业控制、机器人等现场控制领域中进行数据传输。

发展历程

1986年,德国Bosch公司为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种串行数据通信协议。

1993年11月,国际标准化组织ISO正式颁布了关于CAN总线的ISO11898标准。

该标准成为国际上应用最广泛的现场总线之一。

企业支持情况:目前CAN得到了Motorola、Intel、 Philips 、Siemens、NEC等公司的支持。

传输介质:它使用双绞线来传输信号,是世界上应用最广泛的现场总线之一。

核心特性:CAN协议的特性包括:完整性的串行数据通讯、提供实时支持、传输速率高达1Mb/s、同时具有11位的寻址以及检错能力。

此外,CAN协议还支持功能安全应用,具有高可靠性、抗干扰能力强、支持多节点等优点。

报文格式:CAN协议支持两种报文格式,标准格式为11位标识符,扩展格式为29位标识符,支持多种传输速率和数据长度,满足不同应用场景的需求。

1.1 优点

传输速度高。传输速度最高到1Mbps,通信距离最远到10km,无损位仲裁机制,多主结构。近些年来,CAN控制器价格越来越低。

低成本:ECUs通过单个CAN接口进行通信,布线成本低。

高集成:CAN总线系统允许在所有ECUs上进行集中错误诊断和配置。

可靠性:该系统对子系统的故障和电磁干扰具有很强的鲁棒性,是汽车控制系统的理想选择。

高效率:可以通过id对消息进行优先级排序,以便最高优先级的id不被中断。

灵活性:每个ECU包含一个用于CAN总线收发芯片,随意添加CAN总线节点。

CAN总线分层模型

CAN-Bus规范定义了:物理层、数据链路层、应用层(CANopen、DeviceNet等)。

应用层可自行设计,支持多主通信模式。

CAN总线协议也涵盖了 ISO 规定的 OSI 基本参照模型中的传输层、数据链路层及物理层。

CAN 协议中关于 ISO/OSI 基本参照模型中的传输层、数据链路层及物理层,具体定义:

数据链路层分为 MAC 子层和 LLC 子层, MAC 子层是 CAN 协议的核心部分。数据链路层的功能是将物理层收到的信号组织成有意义的消息,并提供传送错误控制等传输控制的流程。具体地说,就是消息的帧化、仲裁、应答、错误的检测或报告。数据链路层的功能通常在 CAN 控制器的硬件中执行。

在物理层定义了信号实际的发送方式、位时序、位的编码方式及同步的步骤。具体地说,信号电平、通信速度、采样点、驱动器和总线的电气特性、连接器的形态等均未定义(驱动器及总线的电气特性等在博世公司的 CAN 规格书中没有定义。但在 CAN 的 ISO 标准(ISO11898、ISO11519-2 等)中分别定义了总线及驱动器的电气特性等 ),这些必须由用户根据系统需求自行确定。

CAN协议的标准、版本

CAN协议经过ISO标准化后有2个标准: ISO11898标准、IS011519-2标准。两种标准对于数据链路层的定义相同,但物理层不同。

CAN 1.0/2.0 : (2套标准的主要区别)

ISO11898 是针对通信速率为125Kbps~1Mbps的高速(总线)通信标准(闭环);

IS011519-2是针对通信速率为125Kbps以下的低速(总线)通信标准(开环);

CAN总线使用两根线链接各个节点,分别是CAN_High和CAN_Low两根,数据的0和1是由总线点位差来判断的。

其中总线电平分为显性和隐性两种电平,显性表示逻辑0,隐性表示逻辑1,符合总线上执行线与功能。

由上图可以清楚的看到IS011899高速标准中,隐性时CAN_High和CAN_Low电位相同,电位差0V,表示逻辑1;显性时CAN_High电位高于CAN_Low电位,电位差为2.0V,表示逻辑0。

而低速IS011519-2标准中,显性时CAN_High电位低于CAN_Low电位,电位差为-1.5V,表示逻辑1;隐性时CAN_High电位高于CAN_Low电位,电位差为3.0V,表示逻辑0。

CAN FD:数据段速率已经可以提升到8Mbps(实际工程中常用2Mbps),有效负载带宽也提升到64 bytes。

CAN XL:数据段速率据说可以稳定达到10Mbps,有效负载带宽进一步拓展到2048 bytes。

Kbps:总线的通信速率,指的是位速率(比特率)。

比特率和波特率不是一回事:单位时间内,通信线路上传输的二进制位的数量,其基本单位是 bps 或者 b/s (bit per second)。

1.2 CAN总线网络

简单的CAN总线网络

CAN总线网络主要挂在CAN_H和CAN_L,各个节点通过这两条线实现信号的串行差分传输.

CAN 总线电平分为显性和隐性两种电平,显性表示逻辑0,隐性表示逻辑1,符合总线上执行线与功能。

为了避免信号的反射和干扰,还需要在CAN_H和CAN_L之间接上120欧姆的终端电阻。为什么是120Ω?因为电缆的特性阻抗为120Ω,为了模拟无限远的传输线。

复杂的CAN总线网络

1.3 CAN收发器(Transceiver)

CAN收发器(Transceiver)的作用: 负责逻辑电平和信号电平之间的转换。

即:从CAN控制芯片输出逻辑电平到CAN收发器;然后,经过CAN收发器【内部转换】将逻辑电平转换为差分信号输出到CAN总线上,CAN总线上的节点都可以决定自己是否需要总线上的数据。

具体的引脚定义如下:

1.4 报文发送过程

CAN节点设备-报文发送的过程

发送请求。

当用户请求发送CAN报文时,最终会调用Can_Write()接口,完成报文发送的请求动作

该接口有一个返回值,表示发送请求成功与否。

如果发送请求成功,返回E_OK;

如果发送请求不成功,返回E_NOT_OK。

E_OK表示什么意思呢?意思是说:【CAN驱动(CanDriver)】有可用的缓存空间(RAM),请求发送的报文信息已被成功地放入【CAN驱动缓存区】

注意,此时还没有发送到CAN BUS,这只是完成了发送请求 (如下绿色框图)

当发送的报文信息被成功添加到【驱动缓存区】以后,这些报文就时刻准备发送到【总线】。

我们知道,一个网段内可以有多个节点,每个节点都等着发送各自缓存区中的报文,【谁先发送呢】?

答:通过仲裁决定哪个节点可以使用CAN BUS,仲裁赢的节点,获取总线使用权,进而发送报文。

谁发送的报文优先级高(CAN ID越小,优先级越高)谁就可以抢占总线使用权 (可阅读: CAN总线仲裁原理)

当网段内的某个节点获取总线使用权以后,就开始发送【缓存区】中最高优先级的报文。

发送节点为了获悉自己所发报文信息是否正确,在使用Tx Pin发送的同时,使用Rx Pin接收(CAN总线是串行总线)。

当然,总线上的其他节点(处于监听状态的节点)也会通过CAN BUS接收总线上的报文。

发送节点,边发送边接收的过程图示:

发送节点按照CAN报文格式发送各个位域,发送节点发送ACK Field(ACL Slot、ACK Delimiter)时,2 Bit均发送隐性位(Recessive,1)。

当接收节点接收到ACK Field的第1个Bit(ACK Slot,ACK应答槽)时,接收节点将其置为显性位(Dominant,0)

由于"线与原则"(显性位覆盖隐性位),所以————CAN BUS上,ACK Slot = 0,这个动作称为应答(Acknowledgement)

即: 接收节点应答发送节点,告知发送节点,其发送的报文已被成功接收 (如下所示)

接收节点收到隐性("1")的Ack Slot时,将其置为显性("0"),这个动作由接收节点的Tx Pin触发。

提示:

Ack动作由Controller完成,不是Transceiver;

总线上可能有多个接收节点,只要其中一个应答(Ack),发送节点就认为数据发送成功;

当总线上没有节点应答发送节点时(即:总线上只有一个节点),发送节点检测到Ack Slot为隐性("1"),会发出错误帧(Acknowledgment Error),同时,发送节点的TEC累加,之后发送节点尝试重传。所以,TEC很快会达到128,进入Error Passive模式。注意,如果一直是Acknowledgment Error,TEC不会再累加,不会进入Bus Off。

当发送节点的发送报文被其他节点成功接收以后,发送节点就会将这个信息反馈给对应的User,告诉请求发送的User,这个过程就是Tx Comfirmation。这个反馈途径有两种:

中断方式,成功将一帧报文发送到总线,且被其他节点有效接收以后,发送节点进入发送完成中断例程,调用User注册的回调接口

比如:CanIf_TxConfirmation(),CanIf在进一步调用目标上层Xx_TxComfirmation 回调接口告知User发送结果。

Polling方式,CAN驱动的Main函数周期性(eg:5ms)的检测是否有报文被成功发送

如果有,则调用目标User的Xx_TxConfirmation(),告知其请求发送报文被接收的结果,即:已被其他节点成功接收,且被应答。

1.5 报文接收过程

什么是Rx Indication呢?CAN BUS上有节点发送报文,就有目标节点接收报文,当接收节点接收到所需的报文以后,需要将接收的信息给到目标User (如下所示)

如何通知目标节点呢?两种方式:

中断方式,当接收节点成功接收到一帧CAN报文以后,程序进入接收完成中断例程,在接收完成中断例程中,会通过上层注册好的Call Back(eg:CanIf_RxIndication())将接收的报文信息送给目标上层。

Polling方式,【CAN驱动】的Main主函数不断地查询是否有报文接收,如果有,则调用Xx_RxIndication()将接收信息送给目标User处理。

如上,将接收报文信息通知到目标User的过程就是Rx Indication。

1.6 CAN信号表示

CAN总线采用不归零码位填充技术。

也就是说,CAN总线上的信号有两种不同的信号状态,分别是: 显性的(Dominant)逻辑0和隐形的(recessive)逻辑1,信号每一次传输完后不需要返回到逻辑0(显性)的电平。

显性电平与隐性电平的解释:

CAN的数据总线有两条,一条是黄色的CAN_High,一条是绿色的CAN_Low。

当没有数据发送时,两条线的电平一样都为2.5V,称为静电平,也就是隐性电平。

当有信号发送时,CAN_High的电平升高1V,即3.5V,CAN_Low的电平降低1V,即1.5V。

按照定义的:

CAN_H-CAN_L < 0.5V 时候为隐性的,逻辑信号表现为"逻辑1" - 高电平。

CAN_H-CAN_L > 0.9V 时候为显性的,逻辑信号表现为"逻辑0" - 低电平。

1.7 CAN信号传输

发送过程:CAN控制器将CPU传来的信号转换为逻辑电平(即: 逻辑0-显性电平 或者 逻辑1-隐性电平)。CAN收发器(发射器)接收逻辑电平之后,再将其转换为差分电平输出到CAN总线上。

接收过程:CAN发射器(接收器)将CAN_H 和 CAN_L 线上传来的差分电平转换为逻辑电平输出到CAN控制器,CAN控制器再把该逻辑电平转化为相应的信号发送到CPU上。

1.8 CAN数据传输

CAN总线传输的是CAN帧,CAN的通信帧分成5种,分别为:数据帧、远程帧、错误帧、过载帧和帧间隔。

数据帧根据仲裁段长度的不同,而分为:标准帧(2.0A)和扩展帧(2.0B)。

位填充:在 CAN 总线中,为了确保足够的转换以保持同步,在相同极性的 5 个连续位(bit)之后使用位填充。

下面以 标准格式来进行说明,先看下面标准格式的帧的图示:

在某些文档中,将 CAN 帧分为以下部分:

Header ( H ): 由 Start of Frame (SOF) 、 Arbitration Field、 Control Field 组成。

Data field ( D ): 即数据域

CRC field ( R ):即 CRC 域的 CRC 部分。其内容由 CAN 控制器在运行时计算,因此不能由应用程序直接修改。

Unstuffed trailer ( U ): 由 CRC delimiter、the ACK slot、the ACK delimiter、the End of Frame (EOF) field. 组成。

特别说明:位填充

BOSCH CAN2.0 规范规定,DATA FRAME 或 REMOTE FRAME 中的位字段 START OF FRAME,ARBITRATION FIELD,CONTROL FIELD,DATA FIELD 和 CRC SEQUENCE 都需要通过比特填充的方法编码。

每当发送器在要发送的比特流中检测到相同值的五个连续比特时,则:自动在实际发送的比特流中插入一个相反的比特位,这种方法被称为位填充。

DATA FRAME 或 REMOTE FRAME 的剩余位字段 CRC DELIMITER,ACK FIELD 和 END OF FRAME 是固定格式,不需要填充。

ERROR FRAME 和 OVERLOAD FRAME 也是固定格式,不通过位填充方法编码。

消息中的比特流根据不归零法(Non-Return-to-Zero,NRZ)进行编码。

这意味着在总比特时间内,生成的比特电平要么是“显性”要么是“隐性”。

下图为一个填充示意图:

在使用比特填充的字段中,相同极性的六个连续比特(111111或000000)被认为是错误。

当检测到错误时,节点可以发送主动错误标志。

主动错误标志由 6 个连续的比特位的显性电平组成,这违反了位填充规则。

位填充方案的一个副作用是,接收到的消息中的少量位错误可能会破坏解填充过程(接收器需要去除填充位),从而导致大量错误在解填充消息中传播。

这降低了 CRC 针对原始错误提供的保护级别。

该协议的不足之处已经在 CAN FD 帧中得到了解决,具体方法是:通过使用固定填充比特和记录插入的填充比特数的计数器的组合。

帧长度

在位填充之后,CAN 帧的大小将增大。填充位本身可以是五个连续相同位中的第一个。

因此,在最坏的情况下,每四个原始位有一个填充位。帧大小可以使用如下公式表示:

s:由控制域中 DLC 定义的数据域的长度

8s:数据域的 比特位 数

47:从 SOF 开始到帧间隔(3个比特位的隐性电平),除去数据域部分(8s 单独表示)

8s + 47:表示填充之前帧的大小。

34:根据规范的要求,可能受到位填充的位的数量。去除了不可填充的部分和某些固定位。在最坏情况下,原数据除了第一个 4 位后,在每个 4 位后增加 1 位(所以分子减去 1)

帧起始

由一个显性位(低电平)组成,发送节点发送帧起始,其他节点同步于帧起始;

帧结束

由7个隐形位(高电平)组成。

仲裁段

只要总线空闲,总线上任何节点都可以发送报文,如果有两个或两个以上的节点开始传送报文,那么就会存在总线访问冲突的可能。但是CAN使用了标识符的逐位仲裁方法可以解决这个问题。

CAN总线控制器在发送数据的同时监控总线电平:

如果电平不同,则:停止发送并做其他处理。

如果该位位于仲裁段,则:退出总线竞争;

如果位于其他段,则:产生错误事件。

假设节点A、B和C都发送相同格式、相同类型的帧,如标准格式数据帧,它们竞争总线的过程是:

帧ID越小,优先级越高。

由于数据帧的RTR位为显性电平,远程帧为隐性电平。所以,帧格式和帧ID相同的情况下,数据帧优先于远程帧;由于标准帧的IDE位为显性电平,扩展帧的IDE位为隐形电平,对于前11位ID相同的标准帧和扩展帧,标准帧优先级比扩展帧高。

数据段

一个数据帧传输的数据量为0~8个字节,这种短帧结构使得CAN-bus实时性很高,非常适合汽车和工控应用场合下图所示。

数据量小,发送和接收时间短,实时性高,被干扰的概率小,抗干扰能力强。

归零编码(RZ)和不归零编码(NRZ)

无论是归零编码(return-to-zero,RZ)还是不归零编码(non-return to zero,NRZ),信号都是在正 (+V) 和负 (- V) 电压之间交替。

逻辑1 表示正电压下的信号,逻辑 0 表示负电压下的信号。

然而,在 NRZ 方法中,从逻辑 0 到逻辑 1 的转换(反之亦然),直接跨越零电压电平,而在 RZ 方法中,转换暂时停留在零电压电平上。如下图所示:

在光通信中,术语 RZ 和 NRZ 使用与以上含义不同,因为没有负光。

NRZ 意味着逻辑值 1 (光脉冲)的一个位在位周期的边界上改变它的值(从有光到无光、或反之亦然)。

相反,RZ 表示光脉冲比比特周期窄。在光信号中,逻辑 1 导通大约三分之一的位周期并且关闭大约三分之二。 逻辑 0 在比特周期的三分之二时间内保持关闭状态。

单极信号、双极信号、多级信号

双极信号(bipolar signal) 是一个三电压级的信号,通常在正电压和负电压之间摇摆。双极信号可以是 RZ 或 NRZ。在数字双极信号中,正电压和负电压交替出现。这导致输电线路上的零直流分量。

单极信号(unipolar signal) 是一种两级信号,通常在零级和正级之间波动。

单极信号被认为是一种开关信号,可以应用于电信号或光学信号。在电力传输中,假设统计上有相同数量的1和0,那么直流分量可能达到峰值正电压的一半。对于长距离传输,这种直流分量是不可取的。在光学传输中,单极信号也称为开关键控。

还有一类是多级信号。在这种情况下,可以使用几个电压电平(例如,8),每个电平对应8个代码中的一个。尽管多级信号由于其固有的编码压缩特性而具有很大的吸引力,但它们并不用于通信网络的传输。在光传输中,不存在多电平信号。

4B/5B, 8B/10B CODING

4B/5B 代码将 4 位转换成 16 个预定的 5 位代码之一。

因此,即使原始的 4 位代码是 0000,它也被转换为 5 位非全零代码。

此方法避免在任何代码中都包含所有零。

它也可以设计成连续模式避免某些字符串。

4B/5B 意味着转换后的初始 1 Gb/s 比特率由于增加了比特而增加到 1.25 Gb/s。

也就是说,有 25% 的开销带宽损失。

类似地,8B/10B 代码将 8 位转换成 256 个预定的 10 位代码之一。

带宽损失也是25%。

2 CAN DBC协议文件

2.1 CAN 总线拓扑图

2.2 CAN 闭环总线网络

CAN闭环通讯网络,是一种遵循ISO11898标准的高速、短距离网络。

它的总线最大长度为40m、通信速度为40m,通信速度最高位1Mbps。

总线的两端要求有一个120欧姆的电阻。

2.3 CAN 开环总线网络

CAN开环总线网络是遵循IDO11519-2标准的低速、远距离网络。

它的最大传输距离为1km、最高通讯速率为125kbps

两根总线是独立的、不形成闭环;

要求每根总线上各串联有一个2200欧姆的电阻。

2.4 CAN 报文的解析规则

通常是将接收到的16进制码流数据翻译成数值、字符串格式的数据,根据 dbc 文件中定义的规则来进行解析。

以CDCU_ICAN_Release.dbc为例来介绍:

版本(version)、新符号(NS)

波特率定义(BS_)

定义格式

BS_:[baudrate:BTR1,BTR2];

其中BS_为关键字,用于定义CAN网络的波特率;

[ ]内容表示为可选部分,可以省略,但关键字BS_:必须存在,省略则会出错。

网络节点定义(BU_)

定义格式:

BU_:Nodename1 Nodename2 Nodename3 ……

其中BU_为关键字,表示网络节点,格式中的Nodename1、Nodename2表示定义的网络节点名字,由用户自己定义;但需保证节点命名的唯一性。

报文帧定义(BO_)

定义格式:

BO_ MessageId(10进制数表示) MessageName: MessageSize Transmitter

(1)、BO_为关键字,表示报文;

(2)、MessageId为定义的报文ID,是以10进制数表示的;如例子中的996,代表报文ID为0x3E4;

(3)、MessageName表示该报文的名字,命名规则和C语言变量相同;

(4)、MessageSize表示该报文数据域字节数,为无符号整型数据;

(5)、Transmitter表示发送该报文的网络节点(发送节点);如果该报文没有指定发送节点,则该值需设置为”Vector__XXX”。

信号定义(SG_)

定义格式:

SG_ SignalName : StartBit|SignalSize@ByteOrder ValueType (Factor,Offset) [Min|Max] Unit Receiver

(1)SG_为关键字,表示信号;

(2)SignalName、 StartBit、 SignalSize分别表示该信号名、起始位、信号长度;

(3)ByteOrder表示信号的字节顺序(大小端):0代表Motorola格式(大端),1代表Inter格式(小端);

(4)ValueType 表示该信号的数值类型:+表示无符号数,-表示有符号数;

注:Java 的Long是8字节(64bit)的有符号数、其作为【有符号数】的取值范围:

[-2^ 63= -9223372036854775808 , +2^ 63 -1 = 9223372036854775807 ] = [1000000000000000000000000000000000000000000000000000000000000000, 0111111111111111111111111111111111111111111111111111111111111111]

注:Java 的Long,针对【长度为 64 bit、无符号数,且上报的信号bit流的第1位为1】的CAN信号情况,根据其取值范围可知、是装不下的。

(5)Factor表示系数因子,Offset表示偏移量;这两个值于该信号的原始值与物理值之间的转换。

计算方法:信号的物理值 = 总线的原始值 * 精度 + 偏移量

(6)Min|Max表示该信号的最小值和最大值,即指定了该信号值的范围;这两个值为double类型;

(7)Unit表示该信号的物理单位,为字符串类型;

(8)Receiver表示该信号的接收节点;若该信号没有指定的接收节点,则必须设置为” Vector__XXX”。

注解部分(CM_)

定义格式

CM_ Object MessageId/NodeName "Comment"

(1)、 CM_为关键字,表示注解信息;

(2)、 Object表示进行注解的对象类型,可以是节点“BU_”、报文“BO_”、消息”SG_”;

(3)、 MessageId/NodeName 表示进行注解的对象,若前面的对象类型是信号或者报文,则这里的值应为报文的ID(10进制数表示);若前面的对象类型为节点,则这里的值应为节点的名字;

(4)、 Comment表示进行注解的文本信息;

属性定义(BA_ / BA_DEF_/BA_DEF_DEF_)

在 DBC 文件中,BA_、 BA_DEF、BA_DEF_DEF 共同构成了属性定义系统,用于为 CAN 网络中的对象(协议 、网络、节点、消息、信号等)添加自定义属性。

定义格式:

BA_ “AttributeName” ObjectType ObjectID Value;

BA_DEF_ Object AttributeName ValueType Min Max;

BA_DEF_DEF_ AttributeName DefaultValue;

属性赋值

格式:BA_ “AttributeName” ObjectType ObjectID Value;

BA_ 关键字,属性赋值

AttributeName 属性名称

ObjectType 属性类型,BU_节点,BO_报文,SG_信号,或者为空表示全局属性

ObjectID 对象ID,BU_:节点名称,BO_:消息ID,SG_:消息ID+信号名

Value 具体的值

属性定义 / 属性默认值

定义格式:

BA_DEF_ Object AttributeName ValueType Min Max;

BA_DEF_DEF_ AttributeName DefaultValue;

(1)、 BA_DEF_为关键字,表示属性定义;

(2)、 Object表示属性定义的对象类型,可以是节点“BU_”、报文“BO_”、消息”SG_”、网络节点” ”(用空格表示)等;

定义属性类型,BU_节点,BO_报文,SG_信号,或者为空表示全局属性

(3)、 AttributeName表示进行定义的属性名字;

(4)、 ValueType表示属性值的类型,可以是整型、字符串、浮点型、枚举类型等;

可以是INT,FLOAT,STRING,ENUM,HEX

(5)、Min/Max表示属性值的上下最值,即指定了取值范围(字符串类型没有此项)。

(6)、 BA_DEF_DEF_为关键字,表示定义属性的初始值;

(7)、 DefaultValue表示该属性的初始值。

综合示例

网络总线类型 / 网络|通道 / ...

综合示例

# 定义节点属性,hex

BA_DEF_ BU_ "Address" HEX 0 255;

# 定义消息周期属性(整型)

BA_DEF_ BO_ "GenMsgCycleTime" INT 0 10000;

# 定义信号状态属性(枚举型)

BA_DEF_ SG_ "SignalStatus" ENUM "ENABLED","DISABLED","TEST_ONLY";

# 全局描述属性

BA_DEF_ "Description" STRING;

# 设置默认值

BA_DEF_DEF_ "Address" 0; #设置默认值为0

BA_DEF_DEF_ "GenMsgCycleTime" 100; # 消息周期默认100ms

BA_DEF_DEF_ "SignalStatus" "DISABLED"; #信号状态默认禁用

BA_DEF_DEF_ "Description" ""; # 全局描述默认空

# 属性赋值

BA_ "BusType" "CAN FD";

BA_ "ProtocolType" "CAN FD";

BA_ "DBName" "ADCAN";

BA_ "Baudrate" 500000;

BA_ "GenMsgCycleTime" BO_ 439 10;

BA_ "GenMsgSendType" BO_ 439 0;

BA_ "VFrameFormat" BO_ 439 14;

BA_ "GenMsgCycleTime" BO_ 1310 200;

BA_ "GenMsgSendType" BO_ 1310 0;

BA_ "VFrameFormat" BO_ 1310 14;

BA_ "GenMsgCycleTime" BO_ 1311 200;

BA_ "GenMsgSendType" BO_ 1311 0;

BA_ "VFrameFormat" BO_ 1311 14;

BA_ "GenMsgCycleTime" BO_ 440 10;

BA_ "Address" BU_ ECU1 7;

BA_ "GenMsgCycleTime" BO_ 0x101 200; #为消息0x101设置周期200ms

BA_ "GenMsgCycleTime" BO_ 0x102 100; #为消息0x102设置周期100ms

BA_ "SignalStatus" SG_ 0x101 VehicleSpeed "ENABLED"; #为车速信号启用

BA_ "Description" BU_ EngineControl "ECU v2.3"; #设置节点描述

数值表部分

定义格式

VAL_ MessageId SignalName N "DefineN" …… 0 "Define0";

(1)、VAL_为关键字,表示数值表定义;

(2)、 MessageId表示该信号所属的报文ID(10进制数表示);

(3)、 SignalName表示信号名;

(4)、 N “DefineN” …… 0 “Define0”表示定义的数值表内容,即该信号的有效值分别用什么符号表示

2.5 辨析:字节序(ByteOrder) := 大小端、比特序(bitOrder) := 正序/逆序

序:CAN报文中的字节序

数据在CAN报文中存放顺序

CAN每个报⽂可包含8Byte的字节数据域,在报⽂内数据的字节序和位序如下:

字节序:Byte0、Byte1、Byte2、Byte3、Byte4、Byte5、Byte6、Byte7

位序:bit7、bit6、bit5、bit4、bit3、bit2、bit1、bit0

CAN报文数据域的传输顺序

字节顺序:先传Byte0,最后传Byte7;

字节内位序:先传bit7,最后传bit0;

字节内始终采用 msb(大端位序),即:信号高有效位在字节内的高位, 信号低有效位在字节内的低位。

跨字节、单字节:

关于CAN报文,用Motorola,还是Intel格式,只在信号数据跨字节解析时,才有区别。单个字节数据没有区别。

LSB/MSB、lsb/msb

位序和字节序都有大端和小端,共有四种:

LSB:Least significant byte(CAN某个信号的最低字节/byte)

MSB:Most significant byte(CAN某个信号的最⾼字节/byte)

lsb:Least significant bit(CAN某个信号中某个字节的最低有效位/bit)

msb:Most significant bit(CAN某个信号中某个字节的最⾼有效位/bit)

扩展解释:

msb与lsb是存在于二进制BIT中的计算机名词,msb代表一组二进制中最高位(一般为符号位),lsb代表二进制中的最低位。

如:一个1字节的二进制数:(msb)100000000(lsb)

也可能是一个4字节的整型数据:(msb)100000000 100000000 100000000 100000000(lsb)

无论这组二进制数据多大,有多少位,最高位都是msb,最低位就是lsb。

一般这两个名词多用在通讯上,msb用来校验这组数据是否为负数,为1则负;lsb用来校验奇偶,为1则偶数

案例:

假设一个一字节的数0x9A转换成2进制为“1001 1010”,那么lsb与msb则应该是这样分布的:

字节序

Intel / Motorola MSB / Motorola LSB

Motorola格式/大端模式(0)

MSB存放在低字节单元,反映到矩阵图中就是以起始位为原点,自下而上填充。Motorola格式,MSB在LSB上面。

一个数值的最高字节(MSB)存储在内存的最低地址处,而最低字节(LSB)存储在内存的最高地址处。这种存储方式类似于人类阅读和书写数字的方式,即从左到右,高位在前

Intel格式/小端模式(1)

MSB存放在高字节单元,反映到矩阵图中就是以起始位为原点,自上而下填充。Intel格式,MSB在LSB下面。

高字节存放在高地址,低字节存放在低地址

跨字节

没有跨字节是看不出来这两种有啥区别的。来看个跨字节的例子:

当然这里只是为了解释这两个的区别,才把一个报文中的两个信号设置成不同的格式,实际项目中一般不会出现这种情况

案例

案例

比特序

小结

当信号在一个字节内实现(信号不跨字节)时,Intel模式和Motorola模式的信号字节顺序,完全一样:

信号的高位(msb)放在该字节的高位,信号的低位(lsb)放在该字节的低位。

当信号在多个字节内实现(信号跨字节)时,Intel模式和Motorola模式的信号字节顺序,明显不同:

Intel模式:信号的高位(MSB)放在高字节的高位,信号的低位(LSB)放在低字节的低位;

Motorola模式:信号的高位(MSB)放在低字节的高位,信号的低位(LSB)放在高字节的低位。

俗称:

小端模式 “低(低位字节)在前(低地址),高(高位字节)在后(高地址)”;

大端模式 “高(高位字节)在前(低地址),低(低位字节)在后(高地址)”。

不管是Intel模式,还是Motorola模式,起始位都该信号的低位(LSB)。

2.X Can 报文实际解析

案例1:(大端模式/Motorola/0)

使用can lin 串口工具抓取rawdata :

30 2E 71 00 00 00 00 00 00 00 00 25 49 15 00 00 00 01 10 00 00 00 00 00 00 00 00 00 00 00 0A 00 34 1D 07 41 D0 40 3C 3C 00 00 28 FF FF FF FF FF FF FF FE 00 00 00 00 00 00 00 00 00 00 00 00 00

通过 dbc 文件找到报文的定义

解析第1个signal:SG_ I_CDCU_KL15State

RawData:30 ------> 0011 0000 从第六位开始2个bit

7

6

5

4

3

2

1

0

0

0

1

1

0

0

0

0

值定义:

VAL_ 816 I_CDCU_KL15State 0 "IG_OFF" 1 "LOCAL_IG_ON" 2 "REMOTE_IG_ON" 3 "Reserved" ;

1 ---> LOCAL_IG_ON

再解析信号: I_CDCU_SWITCH_Temp

SG_ I_CDCU_SWITCH_Temp : 319|8@0+ (1,-40) [-40|100] "degC" Vector__XXX

Rawdata:3C ---------> 00111100

I_CDCU_SWITCH_Temp的定义从第 319 开始、8个bit,rawdata 中找到对应的字节是第40个字节3C

第40个字节的二进制排列

319bit

318bit

317bit

316bit

315bit

314bit

313bit

312bit

0

0

1

1

1

1

0

0

根据公式计算出来对应的值:1*60-40=20;加上单位为20degC

案例2:(小端模式/Intel/1) 【必读】

DBC协议文件

1、如下是一个完整的、准确的Intel模式 CAN信号解析过程。

2、Intel模式信号:低位在右、高位在左;读取顺序:从右往左读。与之相对的是 摩托罗拉信号。

3、DBC的某个CAN帧的信号:

BO_ 1443 BMS_moduleTemperature02: 8 BMS

SG_ bms_moduleXTempSync02 : 0|4@1+ (1,0) [0|15] "" TBOX

SG_ bms_moduleXTempSensor7 : 8|9@1+ (0.5,-40) [-40|210] "℃" TBOX

SG_ bms_moduleXTempSensor8 : 17|9@1+ (0.5,-40) [-40|210] "℃" TBOX

SG_ bms_moduleXTempSensor9 : 26|9@1+ (0.5,-40) [-40|210] "℃" TBOX

SG_ bms_moduleXTempSensor10 : 35|9@1+ (0.5,-40) [-40|210] "℃" TBOX

SG_ bms_moduleXTempSensor11 : 44|9@1+ (0.5,-40) [-40|210] "℃" TBOX

SG_ bms_moduleXTempSensor12 : 53|9@1+ (0.5,-40) [-40|210] "℃" TBOX

0x5A3 = 1443

上报的CAN帧

rawdata : 0050D4408102050A

图片仅供参考,非实际CAN帧的准确瞬时截图

信号解析

0050D4408102050A :=

0000 0000

0101 0000

1101 0100

0100 0000

1000 0001

0000 0010

0000 0101

0000 1010

<---- bit编号:从0到X、从右至左、从上到下

↓ :字节地址(从上到下:低地址 => 高地址)

解析方法1:不反转法(适用于人眼直接阅读)

1101 0100 高位 <-- 低位 ↓

0100 0000 高位 <-- 低位 ↓

=> 00 1101010 => 106 => 13

解析方法2(小端字节序):每个字节分别以 8 bit 逆序反转1次,但字节之间的顺序不变(便于通过程序实现)

0010 1011

0000 0010

=> 010 1011 00 => 再反转1次(作用:还原顺序) => 00 1101 010 => 106*0.5-40=13

案例3:(大端模式/Motorola/0) 【必读】

DBC定义

BO_ 908 BCM_38C: 8 INFO_CAN

SG_ BCM_FLWINOpenDegree : 6|7@0+ (1,0) [0|127] "" VHR

SG_ BCM_FRWINOpenDegree : 14|7@0+ (1,0) [0|127] "" VHR

SG_ BCM_RLWINOpenDegree : 22|7@0+ (1,0) [0|127] "" VHR

SG_ BCM_RRWINOpenDegree : 30|7@0+ (1,0) [0|127] "" VHR

SG_ bcm_doorTopSwitchSts : 36|2@0+ (1,0) [0|3] "" VHR

SG_ BCM_VSPReq : 38|2@0+ (1,0) [0|3] "" VHR

SG_ BCM_FLWINReason : 43|4@0+ (1,0) [0|15] "" VHR

SG_ BCM_FRWINReason : 47|4@0+ (1,0) [0|15] "" VHR

SG_ BCM_RLWINReason : 51|4@0+ (1,0) [0|15] "" VHR

SG_ BCM_RRWINReason : 55|4@0+ (1,0) [0|15] "" VHR

SG_ BCM_RainAutoCloseWinFedb : 57|2@0+ (1,0) [0|3] "" VHR

SG_ BCM_RainAutoCloseWinResult : 59|2@0+ (1,0) [0|3] "" VHR

SG_ BCM_LockFaultReason : 63|4@0+ (1,0) [0|15] "" VHR

VAL_ 908 BCM_FLWINOpenDegree 0 "Inactive" 1 "0%(全关)" 101 "100%(全开)" 102 "reserve" 126 "reserve" 127 "Invalid" ;

VAL_ 908 BCM_FRWINOpenDegree 0 "Inactive" 1 "0%(全关)" 101 "100%(全开)" 102 "reserve" 126 "reserve" 127 "Invalid" ;

VAL_ 908 BCM_RLWINOpenDegree 0 "Inactive" 1 "0%(全关)" 101 "100%(全开)" 102 "reserve" 126 "reserve" 127 "Invalid" ;

VAL_ 908 BCM_RRWINOpenDegree 0 "Inactive" 1 "0%(全关)" 101 "100%(全开)" 102 "reserve" 126 "reserve" 127 "Invalid" ;

VAL_ 908 bcm_doorTopSwitchSts 0 "INACTIVE" 1 "OFF" 2 "ON" 3 " INVALID" ;

...

解析过程分析

canFrameId : 38c

canFrameContent : 7f7f010110110021

原始二进制 : 0111111101111111000000010000000100010000000100010000000000100001 即 : 01111111 01111111 00000001 00000001 00010000 00010001 00000000 00100001

01111111 : 7F

01111111 : 7F

00000001 : 01

00000001 : 01

00010000 : 10

00010001 : 11

00000000 : 00

00100001 : 21

以第1个信号(BCM_FLWINOpenDegree)为例,从第6位开始,读取7个字节。

解析方法2(大端字节序): 每个字节,按 8bit 逆序;再按 byte 逆序

1000010000000000100010000000100010000000100000001111111011111110 即 10000100 00000000 10001000 00001000 10000000 10000000 11111110 11111110

[00] 10000100

[08] 00000000

[16] 10001000

[24] 00001000

[32] 10000000

[40] 10000000

[48] 11111110

[56] 11111110

解析结果

BCM_FLWINOpenDegree | signal bits : 1111111 , reveresdSignalBits: 1111111, signalValue : 127, startBit : 0, bitLen : 7 | bigEndStartBit : 56

BCM_FLWINOpenDegree bigEndStartBit 的计算: 基于 DBC offest=6|bitLen=7

原始的起始位 = DbcReader.bigEndianLeastSignificantBitOffset( 6, 7) = 0

总字节数 = 8 byte

总bit数 = 8 byte * 8 bit/byte = 64 bit

原始位之前的字节数 x = 原始的起始位/8 = 0/8 = 0 byte (向下取整)

原始位之后的字节数 y = 总字节数 -1 -x = 8-1-0 = 7 byte

bigEndStartBit = 原始的起始位 + y*8 - x*8 = 0 + 7*8 - 0*8 = 56

BCM_FRWINOpenDegree | signal bits : 1111111 , reveresdSignalBits: 1111111, signalValue : 127, startBit : 8, bitLen : 7 | bigEndStartBit : 48

BCM_RLWINOpenDegree | signal bits : 1000000 , reveresdSignalBits: 0000001, signalValue : 1, startBit : 16, bitLen : 7 | bigEndStartBit : 40

BCM_RLWINOpenDegree bigEndStartBit 的计算: 基于 DBC offest=22|bitLen=7

原始的起始位 = DbcReader.bigEndianLeastSignificantBitOffset( 22, 7) = 16

总字节数 = 8 byte

总bit数 = 8 byte * 8 bit/byte = 64 bit

原始位之前的字节数 x = 原始的起始位/8 = 16/8 = 2 byte (向下取整)

原始位之后的字节数 y = 总字节数 -1 -x = 8-1-2 = 5 byte

bigEndStartBit = 原始的起始位 + y*8 - x*8 = 16 + 5*8 - 2*8 = 22+40-16 = 40

bcm_doorTopSwitchSts | signal bits : 01 , reveresdSignalBits: 10, signalValue : 2, startBit : 35, bitLen : 2 | bigEndStartBit : 27

BCM_VSPReq | signal bits : 00 , reveresdSignalBits: 00, signalValue : 0, startBit : 37, bitLen : 2 | bigEndStartBit : 29

BCM_FRWINReason | signal bits : 1000 , reveresdSignalBits: 0001, signalValue : 1, startBit : 44, bitLen : 4 | bigEndStartBit : 20

...

//dbc.DbcReader#bigEndianLeastSignificantBitOffset

/**

* Calculates the least significant bit offset for big endian byte order

* //计算大端字节序的最低有效位偏移量

*

* @param msb Most significant bit offset

* @param length signal length in bit

* @return lsb Least significant bit offset

*/

public static int bigEndianLeastSignificantBitOffset(int msb, int length) {

int lsb;

int pos;

int cpos;

int bytes;

pos = 7 - (msb % 8) + (length - 1);

if (pos < 8) {

/* msb pass a byte order */

lsb = msb - length + 1;

} else {

cpos = 7 - (pos % 8);

bytes = pos / 8;

lsb = cpos + (bytes * 8) + (msb / 8) * 8;

}

return lsb;

}

案例4:(大端模式/Motorola/0)

DBC文件

VERSION ""

NS_ :

NS_DESC_

CM_

BA_DEF_

BA_

VAL_

CAT_DEF_

CAT_

FILTER

BA_DEF_DEF_

EV_DATA_

ENVVAR_DATA_

SGTYPE_

SGTYPE_VAL_

BA_DEF_SGTYPE_

BA_SGTYPE_

SIG_TYPE_REF_

VAL_TABLE_

SIG_GROUP_

SIG_VALTYPE_

SIGTYPE_VALTYPE_

BO_TX_BU_

BA_DEF_REL_

BA_REL_

BA_DEF_DEF_REL_

BU_SG_REL_

BU_EV_REL_

BU_BO_REL_

SG_MUL_VAL_

BS_:

BU_: EOCM_F_FO Dummy_FO

BO_ 1414 RVB_TVR_Debug2_FO: 7 EOCM_F_FO

SG_ VBBrkCntlAccel : 45|12@0- (0.01,0) [-20.48|20.47] "m/s^2" Dummy_FO

SG_ VBTOSObjID : 35|6@0+ (1,0) [0|63] "" Dummy_FO

SG_ VBTOSTTC : 31|12@0+ (0.025,0) [0|102.375] "s" Dummy_FO

SG_ VBTOSLatPstn : 11|11@0- (0.125,0) [-128|127.875] "m" Dummy_FO

SG_ VBTOSLonPstn : 7|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO

发送CAN报文

根据上面的dbc文件,我们进行如下示例分析。向can0网卡发送数据 cansend can0 586#d465737400000000, ekuiper 输出以下结果:

[

{

"VBBrkCntlAccel": 0,

"VBTOSLatPstn": 87.125,

"VBTOSLonPstn": -87.25,

"VBTOSObjID": 0,

"VBTOSTTC": 46.400000000000009

}

]

我们尝试通过对dbc数据库文件的理解进行分析,看看是否与ekuiper的计算结果一致。在分析前,我们需要了解几点内容:

1、位序。我们知道: 字节序是一个对象中的多个字节之间的顺序问题;比特序就是一个字节中的8个比特位(bit)之间的顺序问题。

一般情况下系统的比特序和字节序是保持一致的。

比如:二进制数11010100,若比特序为大端msb,则:最高有效比特位在高位,最低有效比特位在低位,那么:它代表的值为0xd4;

若比特序为lsb,则:最高有效比特位在低位,最低有效比特位在高位,那么:它代表的值为0x2b。

CAN 总线协议中规定,位序都是大端模式,即 msb。

2、motorola和inter字节序在dbc文件解析中,信号定义中有一个参数ByteOrder表示信号的字节顺序。分别为inter和Motorola两种格式。

Intel格式跟小端格式一样,低地址代表低字节,高地址代表高字节。

Motorola格式跟大端格式一样,低地址代表高字节,高地址代表低字节。

注:Motorola格式有2种表达方式,一种是Motorola_LSB,另一种是Motorola_MSB。Motorola_LSB的起始位是从低字节开始的,而Motorola_MSB的起始位是从高字节开始的。

dbc文件默认表示Motorola_MSB表达方式;而CANdb++则是Motorola_LSB。

3、信号传输,都是以补码的形式传输

分析:

586#d465737400000000表示报文ID为0x586=1414,与RVB_TVR_Debug2_FO报文匹配。其中d465737400000000则为该报文的数据部分。

因为CAN总线协议规定,位序都是大端模式,即可得到下面的layout图。其中蓝色背景为数据内容,因为RVB_TVR_Debug2_FO报文长度仅有7Byte。

VBBrkCntlAccel信号的起始位bit45,且为Motorola字节序,则:bit45是信号VBBrkCntlAccel最高有效比特位。因此,信号内容如下。即信号原始值为000000000000、物理值=原始值*(0.01)+0 = 0

同理,可得到其它信号的layout如图。

VBTOSObjID原始值为000000,物理值=0*1+0=0;

VBTOSTTC原始值为011101000000,物理值=1856*0.025+0=46.4。至于最终的打印结果为什么是46.400000000000009,可以参考我的博客flaot 数据类型的一些坑(大数吃小数)。

VBTOSLatPstn原始值为01010111001,物理值=697*0.125+0=87.125。

VBTOSLonPstn原始值为110101000110。因为该信号为有符号数,因此最高位1,则表示该值为负。

其原始值的补码为110101000110,则:原始值为101010111010=-698。物理值=-698*0.125+0=-87.25。

同样的dbc文件,若由CANdb++进行解析,如下。可知Startbit与dbc文件不一致。因为CANdb++默认是Motorola_LSB表达方式。

案例5:Intel

Intel格式:Intel格式跟小端格式一样,低地址代表低字节,高地址代表高字节。比如一个信号Intel,它的起始位为3,长度为10,在dbc中它的排列顺序如下所示:

要注意其箭头的增长方向,这样我们在提取该信号的值为: Intel = (byte0 >> 3) + (byte1 << 5)

其中: (byte0 >> 3)为低字节的值,(byte1 << 5)为高字节的值。

案例6:Motorola_LSB

Motorola格式

Motorola格式跟大端格式一样,低地址代表高字节,高地址代表低字节。

与Intel不一样的是,Motorola格式有2种表达方式,一种是Motorola_LSB,另一种是Motorola_MSB,但实际上它们代表的数据结构是一样的,只是表达方式不一样而已

其中Motorola_LSB的起始位是从低字节开始的,而Motorola_MSB的起始位是从高字节开始的。

在dbc中,比如一个Motorola_LSB的信号MotorolaSignal,其起始位为10,长度为10,在dbc中,其排列顺序如下所示:

要注意其箭头的增长方向,这样我们在提取该信号的值为: MotorolaSignal= (byte1 >> 2) + (byte0 << 6)

其中(byte1 >> 2)为低字节的值,(byte0 << 6)为高字节的值。

如果该MotorolaSignal信号用Motorola_MSB表示,则:起始位为3,长度为10,但其值的计算方式跟Motorola_LSB是一样的。

案例7:大端模式 + 小端模式

以8 byte的CAN帧为例,其位序为下保持不变。

| 7 - 0 |

| 15 - 8 |

| 23 - 16 |

| 31 - 24 |

| 39 - 32 |

| 47 - 40 |

| 55 - 48 |

| 63 - 56 |

在.dbc描述中,一般只会给出某个信号的startbit及len,我们先以大端模式为例阐述这样的一个例子: startbit = 20, len = 15

那么大端的数据范围是

上图中38bit为lsb,20bit为msb,DBC描述是从msb->lsb方向描述一个信号,接下来看看小端是如何描述的

其中20bit是lsb,34bit为ms,所以小端格式下,DBC描述是从lsb->msb的方向描述一个信号

案例8:小端模式(Intel)

DBC中的CAN帧定义

BO_ 1300 BMS_metric: 8 BMS_EV

SG_ bms_SOC : 0|10@1+ (0.1,0) [0|100] "%" GW_R

SG_ bms_SOH : 10|10@1+ (0.1,0) [0|100] "%" GW_R

SG_ bms_SOE : 20|10@1+ (0.1,0) [0|100] "%" GW_R

SG_ bms_SOCActual : 30|10@1+ (0.1,0) [0|100] "%" GW_R

SG_ bms_maxChargeSOC : 40|7@1+ (1,0) [0|100] "" GW_R

SG_ BMS_BatterFaultLightContro : 47|1@1+ (1,0) [0|1] "" GW_R

SG_ BMS_BatteryTempLowLight : 50|1@1+ (1,0) [0|1] "" GW_R

SG_ BMS_NavigChrgPostFB : 51|3@1+ (1,0) [0|7] "" GW_R

SG_ bms_stEgyFlowSysDischRgn : 54|2@1+ (1,0) [0|3] "" GW_R

SG_ bms_stEgyFlowOBCAndBatt : 56|2@1+ (1,0) [0|3] "" GW_R

SG_ bms_BatteryWarmst : 61|3@1+ (1,0) [0|7] "" GW_R

SG_ bms_chargeFormstatus : 58|3@1+ (1,0) [0|7] "" GW_R

CAN帧

030000031e080348

信号计算结果(以bms_SOC信号为例)

小结:CAN总线/报文、DBC文件、CANdb++的字节序、位序(比特序)

Motorola格式:跟大端格式一样,低地址代表高字节,高地址代表低字节。

注:Motorola格式有2种表达方式,一种是Motorola_LSB,另一种是Motorola_MSB。Motorola_LSB的起始位是从低字节开始的,而Motorola_MSB的起始位是从高字节开始的。

CAN总线协议中规定,位序都是大端模式,即 msb first => 因此不需要区分; 但对字节序没有规定,就出现了两种情况:Motorola 和 Intel 格式。

字节内始终采用 msb(大端位序),即:信号高有效位在字节内的高位, 信号低有效位在字节内的低位。

dbc文件默认表示Motorola_MSB字节序;而CANdb++则是Motorola_LSB。

CANdb++默认是Motorola_LSB字节序

3 CAN-FD 总线协议

3.1 CAN 总线通信协议 ==> CAN FD 总线通信协议

CAN 总线通信也渐渐显现出来一些不足,主要有以下几方面:

(1)最高数据传输速率限制为1 Mbit/s,车载领域实际使用速率最高为500 Kbit/s,无法满足越来越高的数据吞吐量需求;

(2)每帧报文有效数据场为8 字节,仅占整帧报文信息不足50%;

(3)性能上难以应对Flexray、Ethernet 等新型车载总线的威胁。

市场对提升 CAN 总线性能的强烈需求使CAN-FD (Flexible Data rate)应运而生,CAN-FD发扬了CAN 的优点,并弥补了 CAN 的不足,其主要特性如下:

(1)采用与 CAN 通信相同的事件触发模式,软件容易开发和移植;

(2)最高数据传输速率达5Mbit/s,更好地满足要求高实时性、高数据传输速率的应用;

(3)每帧报文的有效数据长为 64 字节,占整帧报文信息超过70%;

(4)相比Flexray、Ethernet 等新兴总线的成本更低。

CAN与CAN-FD性能对比

| Frame Type | NO.Data Bytes | Arb.Bit-Rate | Opt.Bit-Rate | Avg.Bit-Rate | Frame Duration |

3.2 CAN-FD 的技术特点及应用领域

CAN-FD 通过改变帧结构和提高位速率等方法成功的把数据传输速率提高到了5Mbit/s,其基本原理如图所示。

CAN-FD 传输的基本原理

3.3 CAN-FD 的主要应用领域

(1)EOL(End-Of-Line)程序烧写:CAN 数据传输速率为500 Kbit/s;CAN-FD 数据传输速率为5 Mbit/s,约10 倍于CAN 传输速率。

(2)动力、底盘和安全系统,以及身份认证:数据场支持长达64 字节,避免数据非 必要的拆分。

(3)网关:提高网络数据传输速率达5 Mbit/s,提高了有效数据负载率。

3.4 CAN-FD 的设备、工具厂商

在车载应用领域,目前已有多家设备、工具厂商支持CAN-FD 总线协议,如维克多(Vector)、罗德与施瓦茨(R&S)和周立功(ZLG)等。

国外厂商以维克多为代表,其在工具体系的完整性方面更为领先。Vector 的工具体系完整的支持CAN-FD 的开发、测试、网络分析等全部功能。另外,其GL 系列总线记录仪也将在不远的将来支持CAN-FD 协议。

国内厂商以周立功为代表,其最新推出的四通道ZDS2024 示波器可以很好的支持 CAN-FD 协议,其关键特性包括:支持4 通道、模拟带宽高达200MHz、采样率每通道均为1GSa/s、21 种协议触发及解码、51 种参数测量及24 种参数同时测量统计。

3.5 位填充法

与CAN一样,填充位插入到SOF和数据场的末尾之间。插入的填充位数值是经过格雷码计算转换后的值,并且用奇偶校验位保护(Stuff Count)。

在CRC校验场中,填充位被放置在固定的位位置,这称为固定填充位(Fixed Stuff Bit FSB)。固定填充位的值是上一位的反码。

CRC校验场的第一位

每间隔4位添加一个固定填充位

3.6 CAN-FD帧类型

CAN-FD仅定义了数据帧,与传统CAN相比,取消了远程帧的支持。原因是在没有数据的情况下,远程帧没有必要改变数据段的比特率。

与CAN一样,数据帧分为“标准帧(11位ID)”和“扩展帧(29位ID)”格式。从BRS(Bit Rate Switch)到CRC分界符之间为可变速率。橙色表示与CAN的传输速度相同,蓝色表示可加速传输速度。

3.7 CRC-stuff count

CAN FD还在安全性上有了提高。为了避免位填充对CRC的影响,CAN FD在CRC场中增加了stuff count记录填充位的个数对应8的模,并用Grey Code表示,还增加了奇偶校验位。FSB(fixed stuff-bit)固定为前一位的补码。

Stuff Count由以下两个元素组成:

格雷码计算:CRC区域之前的填充位数除以8,得到的余数(Stuff bit count modulo 8)进行格雷码计算得到的值(Bit0-2)

奇偶校验:通过格雷码计算后的值的奇偶校验(偶校验)

3.8 CRC

随着数据场的扩大,为了保证信息发送的质量,CAN FD的CRC计算不仅要包括数据段的位,还包括来自SOF的Stuff Count和填充位。通过比较CRC的计算结果,可以判断接收节点是否能够正常接收。

在CAN中,CRC的位数是15位,而在CAN FD中,CRC场扩展到了21位,详见以下:

当传输数据为16字节或更少时:CRC 17位

当传输数据超过16个字节时:CRC 21位

3.9 CRC界定符

CRC界定符是表示CRC校验场的结束,是一个1位的常态隐性位。但是,在CAN FD中,考虑到节点之间的位的距离,在接收端允许最大2位时间。CAN FD帧的数据场(可变速段)是CRC界定符的第一位采样点。

3.10 ACK应答场

CAN FD的ACK应答场包括应答间隙和应答界定符,其构成和CAN是相同的。不同的是,在CAN中,应答场的长度是1位,但在CAN FD,接收节点利用2位时间将其识别为有效应答。

由从高速的数据场到慢速的仲裁场时,时钟切换会引起收发器相移和总线传播延迟。为了补偿其相移和延迟,相比传统的CAN,在CAN FD中多加了这额外的1位时间。在ACK之后,发送ACK界定符。这是一个表示ACK结束的分隔符,为是1位隐性位。

3.11 帧结尾

每一个数据帧均由一标志序列界定,这个标志序列由7个“隐性”位组成。CAN FD的帧结尾与CAN相同。

3.12 有关CRC的ISO CAN FD、non-ISO CAN FD兼容性问题

当前CAN FD协议有两个版本,为提高故障(错误)检测能力,新版本特别引入了一个3位填充位计数器和一个额外的奇偶校验位。此外,CRC计算方法也发生了变化。这些改进使最新的CAN FD协议与博世(BOSCH)开发的原始CAN FD协议不兼容。负责ISO的工作组已完成其文件,并已将其提交给DIS(国际标准草案)在进行投票程序。

为了避免误解,CiA建议使用术语“ISO CAN FD”和“non-ISO CAN FD”。所有符合ISO 11898-2:2015的产品都应称为“ISO CAN FD”。执行博世(BOSCH)原始CAN FD协议的产品应命名为“non-ISO CAN FD”,在这个过度阶段的产品主要目的是用于前期评估和开发,将来所有产品都将符合ISO标准。

请注意,早前一些供应商提供的组件或者工具是针对non-ISO CAN FD协议的,包括目前在售的部分CAN FD产品,CiA建议仅使用ISO CAN FD产品进行设计和开发,不过你可继续使用non-ISO CAN FD做评估和前期开发,因为协议的改变对于用户界面是不可见,但注意的是不能同一个网络混用non-ISO CAN FD和ISO CAN FD接口设备,这样会造成CAN总线错误无法完成发送和接收,如果仅仅是发送或接收传统的CAN帧将不会受到任何影响,幸运的是部分设备供应商提供的组件或者工具允许用户选择支持ISO或者non-ISO模式,这样能很好地在过渡时期帮助你完成工作。

3.13 波形实例

本实例使用 Kingst LA5016 usb 逻辑分析仪检测CAN FD数据通讯。LA5016的CAN FD解析模块,不仅可以解析CAN FD协议,同时也兼容CAN协议解析,以下几图是一个完整的数据包分析截图。从图中可以看到,CAN FD协议可以区分CAN FD及CAN协议,CAN FD协议将协议数据分析为 ID(协议id号), ExternId(扩展id), DLC(数据长度),Data(传输数据), StuffCount,CRC, ACK/NAK 。

协议解析参数设置:

数据包的ID号为0x010, RTR:false(数据帧), DLC:0x8(8个数据),Data:0x00~0x07,CRC为0x0C5E7(17位), ACK:应答。

圆形白点:逻辑数据。

方形白点:填充位。

3.X 参考文献

CAN-FD总线协议深度解析-简单易懂协议详解 - Zhihu

FAQ for CAN 网络

Q: CAN报文的DLC和DataLength的区别?

回顾一下: CAN报文的帧结构

区别1 : 表示的数值范围不同

DLC占4个bit,可表示的数值范围0-15;

Data 即 Data Length占64个字节;

区别2 : 表示的意义不同

DLC表示message报文的DLC。对于标准帧而言,DLC的长度最大为8

对于CAN-FD而言,Data Length的长度最大为64个字节,故有了以下映射表(来源: 蚂蚁小兵博客)

如果是CAN标准帧的时候,DLC和Data Length的值相同;

若是CAN-FD拓展帧时,DLC值表示范围0-15,Data Length表示的范围0-64,且当DLC<=8时,DLC和Data Length的值相同,当DLC>8时,需要满足上述的映射表。(如下图实例)

图: CANoe

Q: DBC文件的编辑与可视化工具? Vector CANdb++ Editor

图:Vector CANdb++ Editor

图:Vector CANdb++ Editor(管理手册)

图:Vector CANoe 内部集成了 Vector CANdb++ Editor

Q: CAN/CANFD的区别?

推荐文献

一文解析CAN和CANFD - CSDN

通信总线协议之CAN-FD协议详解 - CSDN

X 参考文献

CAN总线详解 - Wexin/STM32嵌入式开发

CAN DBC 解析规则 - CSDN 【推荐】

一文搞懂如何制作DBC文件 - Weixin

知识分享 | 读懂CAN DBC文件 - Zhihu

【AUTOSAR-CP-CAN-1】DataBase for Can——深入理解 DBC 通信矩阵 - CSDN

CAN信号值解析 - 百度文库

CAN协议解析 - Zhihu

关于CAN信号的大小端及分析 - CSDN 【推荐】

字节序之大小端与MSB和LSB - CSDN

CAN总线和DCB文件格式 - CSDN

一文搞懂系列——DBC数据库信号解析规则及案例 - Weixin/Linux开发经验分享 【强烈推荐】

CAN 报文字节排列顺序(Intel、Motorola_LSB、Motorola_MSB) - CSDN

CAN报文数据的取值与赋值 - CSDN 【推荐】

CAN总线位序与字节序 - CSDN 【推荐】

CAN位时序及相关参数 - Zhihu 【强烈推荐】

CAN 总线 之六 BOSCH CAN 比特位填充(编码规则)、归零编码(RZ)和不归零编码(NRZ) - CSDN 【强烈推荐】

CAN 总线 之四 BOSCH CAN2.0 Part A - CSDN 【强烈推荐】

CAN总线技术 - CSDN

DBC的故事 - 博客园 【强烈推荐】

DBC的故事(二)信号的有符号数与无符号数 - 博客园 【推荐】

CAN总线通信详解 - 百度文库/徐工集团控制研究所 【强烈推荐】

CAN总线详细讲解 - 百度文库 【强烈推荐】

CAN总线通信详解 (超详细配34张高清图) - Zhihu

CAN报文解析 - CSDN

【干货】CAN报文传输过程解析 - Zhihu

CAN总线通信之详解数据帧(Data Frame) - Zhihu

"现在最新的已经是CAN-FD协议了,数据域直接扩展到64字节,也就是理论最高位速率直接从1M提升到了8M"

CAN通信标准帧和扩展帧(全网最透彻解答) - CSDN

CAN总线数据解析(Intel格式) - 博客园

Can解析 - dxl.life 【强烈推荐】

详解CAN总线:CAN协议分层结构及功能 - CSDN

CAN通信基础:Tx Comfirmation、Rx Indication以及Ack - Zhihu

CAN报文的DLC和DataLength的区别 - CSDN

🌈 相关推荐

世界杯哪个小组没出过冠军
365bet注册指南

世界杯哪个小组没出过冠军

📅 08-01 👁️ 9629
幺的笔顺(笔画顺序)汉字幺的笔顺动画
365bet注册指南

幺的笔顺(笔画顺序)汉字幺的笔顺动画

📅 09-21 👁️ 9739