目录
- CAN总线和DBC格式
- 1. CAN总线
- 1.1 CAN总线的组织结构
- 1.2 CAN的信号结构
- 2. DBC格式
- 2.1 通用描述
- 2.2 DBC文件的结构
- 3. DBC文件官方示例
- 3. DBC文件官方示例
CAN总线和DBC格式
1. CAN总线
控制器局域网总线(CAN,Controller Area Network)一般被我们称为CAN总线,常用于汽车各不同原件之间的通信。
1.1 CAN总线的组织结构
CAN节点一般由MCU控制器、CAN控制器和CAN收发器组成。
CAN的信号传递介质为一股双绞线,双绞线由一条CAN-High和一条CAN-Low组成,这两条线的电势差用来表征CAN的总线值,在CAN通讯中,低电平代表的是显性电平,高电平代表的是隐性电平
发送节点通过使总线的电平产生变化,将其信息传输到CAN总线上。接收节点通过监听总线的电平,将总线的信息读入接收器上。
CAN总线的数据按照协议以报文的形式发送,并广播到网络中的所有结点。对于每个节点,无论报文是否是发送给自己都进行接收。
1.2 CAN的信号结构
CAN通讯的结构是基于帧的,CAN的帧分为两种:标准帧和扩展帧。这也分别对应着两个不同的协议:CAN2.0A和CAN2.0B。帧结构如下图:
以下是帧结构的组成部分:
-
帧起始。帧起始是一个显性位电平,当总线空闲时,发送节点发送一个显性电平,所有的接收节点同步于该帧起始位。这一个显性电平的发出代表着一帧信号的开始。
-
仲裁段。任何CAN节点在任何时刻都可以向总线发送数据,但总线同一时刻只能发送一帧消息,因此总线在同一时刻接受多个帧时需要通过帧的仲裁段来决定优先级。在进行裁决的时候,依据就是信号的ID,总线会对ID进行逐位的比较,比较的过程中显性电平胜出,隐形电平退出发送。
在进行裁决的时候,依据就是信号的ID,总线会对ID进行逐位的比较,比较的过程中显性电平胜出,隐形电平退出发送。
仲裁段的ID越小,优先级越高。仲裁段中除了ID外,还有RTR,这个位是为了区分数据帧和远程帧的。如果在一帧消息内,ID都是完全一样的,数据帧的优先级高于远程帧。 -
控制段。两种类型的帧控制段的长度都是六位,在标准帧中的控制段包含IDE,保留位r0以及数据长度DLC;在扩展帧中的控制段包含保留位r0,r1以及数据长度DLC。
-
数据段。数据段根据需要传输的数据长度传输相应的字节,但最大不能超过8byte。
-
CRC段。CRC中文的意思是循环冗余校验,其目的就是要对这一帧信号中前面的部分进行校验,以保证数据传输的正确性,校验的部分包括:帧起始、仲裁段、控制段以及数据段。
-
ACK段。这一段和CRC是相关的,上一段进行了CRC校验的比对,如果CRC校验结果没有问题的话,接收节点会在总线发送一个显性电平。
-
帧结束。和一开始的帧起始相呼应,帧结束是由七个连续的隐性电平组成。
2. DBC格式
DBC(Database CAN)是一种由Vector公司定义的一种网络通信文件格式,是CAN总线数据库文件。CAN总线中传输的二进制帧信号不利于分析报文的具体内容,DBC最基础的作用就是帮助解释二进制的帧信号,以便分析报文信息。
这里附上DBC的官方文档:DBC file Format Documentation v1.05
2.1 通用描述
2.1.1关键字
下面的表格给出了DBC文件中用于标识对象类型的DBC关键字。关键字的具体含义在后面会说到。
关键字 | 对象类型 |
---|---|
BU_ | 网络节点 |
BO_ | 报文 |
SG_ | 信号 |
EV_ | 环境变量 |
SIG_GROUP_ | 信号组 |
VAL_TABLE_ | 数值表 |
2.1.2数据类型
DBC文件对属性值由数据类型的区分,下表为DBC文件中可选的数据类型。
符号 | 类型 |
---|---|
unsigned_interger | 无符号整型 |
singed_integer | 有符号整型 |
double | 双精度浮点数 |
char_string | 字符串 |
C_identifier | C语言变量名 |
其中C_identifiers
必须以字母字符或下划线开始,并可以由字母、数字字符和下划线组成。如:Abc_string
, acb_123_string
。
2.1.3 语法描述
DBC文件中使用扩展的巴斯科范式(Backus-Naur-Format, BNF)表示法来进行语法描述。如下表所示:
符号 | 含义 |
---|---|
= | =左侧的名称使用右侧的语法进行定义,简单说就是赋值 |
; | 使用分号结束一个定义 |
∣ \vert ∣ | 垂直条表示替代选项 |
[ … ] | 反括号内的定义是可选的(0次或一次) |
{ … } | 大括号内的定义可以重复(0次或多次) |
( … ) | 括号用于定义分组元素 |
’ … ’ | 连字符中的文本必须按照定义进行显示 |
(* … *) | 表示注释 |
2.2 DBC文件的结构
DBC文件的整体结构如下所示:
version
new_symbols
bit_timing (*已废弃但仍需要*)
nodes
value_tables
messages
message_transmitters
environment_variables
environment_variables_data
signal_types
comments
attribute_definitions
sigtype_attr_list
attribute_defaults
attribute_values
value_descriptions
category_definitions (*已废弃*)
categories (*已废弃*)
filter (*已废弃*)
signal_type_refs
signal_groups
signal_extended_value_type_list
extended_multiplexing ;
描述DBC文件基本通信的文件主要有以下几个:
- Bit_timing
这部分是必须的,但通常为空。。
- nodes
这部分是必须的,定义了网络节点。
- messages
这部分定义了报文和信号。
以下部分未在普通DBC文件中使用。此处仅为完整起见对其进行定义:
- signal_types
- sigtype_attr_list
- category_definitions
- categories
- filter
- signal_type_refs
- signal_extended_value_type_list
官方文档中写道:
DBC files that describe the CAN communication and don’t define any additional
data for system or remaining bus simulations don’t include environment variables.
这段话的具体含义我没太搞懂,但总之就是很多DBC文件没有环境变量的意思。
2.2.1 符号定义的格式
这部分是DBC格式的重点。
1. version和new symbol的格式
CBD文件的开头是version和new symbol组成的标头。versiond的格式为:
version = ['VERSION' '"' { CANdb_version_string } '"' ];
双引号中的内容可以为空,也可以用户自定义。
举例:VERSION " "
或VERSION "1.0"
new symbol的格式为:
new_symbols = [ '_NS' ':' ['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_'] ];
符号定义关键字为NS_
。在DBC文件里第一个new symbol通常为NS_
,但不知为何官方文档给出的为_NS
。
2. bit timing的格式
波特率关键字为BS_
。波特率部分定义了网络的波特率以及BTR寄存器值,此部分已废弃,但是关键字 “BS_” 必须在DBC文件中出现。因此在文件中一般只有一个单独的BS_
。
3. nodes的格式
节点的关键词为BU_
。节点定义了此网络中所有参与通讯的节点,每个节点定义必须是唯一的,命名方式同C语言。
nodes = 'BU_:' {node_name} ;
node_name = C_identifier ;
举例:BU_ : ECU1 ECU2 ECU3 Tester
4. messages的格式(重点)
报文的关键词为BO_
。报文定义了集群中所有帧的名称以及其属性以及在帧上传输的信号。其中message_id在此网络中必须是唯一的,CAN ID可以是标准帧ID或者扩展帧ID,它们不同的地方在于帧ID的长度,标准帧的帧ID长度是11位,也就是帧ID的范围是000-7FF。扩展帧的帧ID长度是29位,也就是帧ID的范围是00000000-7FFFFFFF。
messages = {message} ;
message = BO_ message_id message_name ':' message_size transmitter {signal} ;
message_id = unsigned_integer ;
BO_ message_id为报文的CAN ID,在DCB文件中为十进制,注意有时需要换算为对应的十六进制ID。
message_name = C_identifier ;
message_name命名规则与C语言相同。
message_size = unsigned_integer ;
message_size也就是所谓的DLC,是无符号整型数,单位是Byte,其规定了报文数据域的字节数。标准CAN最大支持8个Byte,CANFD最大支持64个Byte.
transmitter = node_name | ‘Vector__XXX’ ;
transmitter表示报文发送的节点,该节点必须是在nodes部分定义中的某个节点,或者是 ‘Vector__XXX’
。
‘Vector__XXX’
这个字符串的意思是,如果某个报文没有指定发送节点,则必须设置为 ’Vector_XXX’.
举例:BO_ 100 test_message1: 8 ECU1
定义报文test_message1, CAN ID为100(dec),DLC为8,发送方为ECU1。
5. signals的格式
信号的关键字为SG_
。报文的信号部分列出了放置在报文上的所有信号以及信号在报文的数据字段中的位置及其属性。
signal = ‘SG_' signal_name multiplexer_indicator ' : ' start_bit ' | ' signal_size ' @ ' byte_order value_type ' ( ' factor ' , ' offset ' ) ' ' \[ ' minimum ' | ' maximum ' \] ' unit receiver {',' receiver} ;
signal_name = C_identifier ;
上面定义的signal_name对于同一个报文内的信号必须是唯一的。
multiplexer_indicator = ' ' | [m multiplexer_switch_value] [M] ;
其中多路复用器指示器指示该信号是正常信号、复用信号开关还是多路复用信号。“M”(大写)字符将信号定义为多路复用器开关。单个消息中只有一个信号可以是多路复用器开关。
“m”(小写)字符后跟无符号整数将信号定义为由多路复用。
如果多路复用器信号的开关值等于其multiplexer_switch_value,则多路复用信号在消息中传输。(这一项不常见)
start_bit = unsigned_integer ;
signal_size = unsigned_integer ;
start_bit指定了信号在帧的数据段内的起始位,必须在(8*message_size-1)的范围内。signal_size 指信号的长度。
byte_order = '0' | '1' ;
1代表指intel格式,称为小端模式;0代表motorola格式称为大端模式。
value_type = '+' | '-' ;
+表示无符号数, -表示有符号数
factor = double ;
offset = double ;
facator与offset是用来将原始值与物理值之间进行转化,物理值就是我们希望使用的,原始值是报文中记录的值。minumum与maximum表示信号的最大最小值,这四个参数均为为double类型
其中facator和offset参与计算的关系如下:
physical_value = raw_value * factor + offset
raw_value = (physical_value – offset) / factor
从上式中可以看出factor不得为0。
unit为字符串,用来表示信号单位,没有单位则此项为空。
receiver = node_name | 'Vector__XXX' ;
receiver和前面的transmitter一样。
举例:
BO_ 101 test_message2: 8 ECU2
SG_ test_signal2: 10|5@1+ (1,-1) [0|31] “cm” ECU3
定义test_message2中的一个信号test_signal2, 起始位为10,长度为5,采用Intel格式,无符号整型,因子为1,偏移为-1,最小最大值为0和31,单位为cm,接收方是ECU3。
6. value Encodings的格式
信号值的关键字为VAL_
。信号值描述定义了特定信号原始值的编码。
value_descriptions = { value_descriptions_for_signal | value_descriptions_for_env_var } ;
value_descriptions_for_signal = 'VAL_' message_id signal_name { value_description } ';' ;
举例:VAL_ 100 test_signal1 0 “Off” 1 “On” 2 “Reserved” 3 “Invalid” ;
定义message ID 为100的报文中test_signal1的encodings,0的含义是off,1的含义是on,2的含义保留,3表示无效值。
实际上encoding值是为了告诉诊断,测试人员,相对于的值代表什么意思。
这个属性不是必须的,不是每个信号都需要。
7. environment variable的格式
环境变量的关键字为EV_
。此部分略过,因为一般只在系统仿真和总线仿真工具中使用的环境变量。
8. signal group的格式
信号组的关键字为SIG_GROUP_
。信号组用于定义消息中的一组信号。信号组的概念属于功能安全端对端保护(E2E)中的部分,其中的一个目的就是一个组的信号必须共同更新。
signal_groups = 'SIG_GROUP_' message_id signal_group_name repetitions ':' { signal_name } ';' ;
signal_group_name = C_identifier ;
repetitions = unsigned_integer ;
举例:
SIG_GROUP_ 100 test_message1_group 1 : CheckSum_test_message1 test_signal1 RollingCounter_test_message1 ;
定义CAN ID为100的报文中的信号组test_message1_group, repetitions为1,其中的信号包含CheckSum_test_message1,test_signal1,RollingCounter_test_message1。
9. comment的格式
注释的关键字为CM_
。注释部分包含对象注释。主要是说明信号的描述。
comments = {comment} ;
comment = 'CM_' (char_string | 'BU_' node_name char_string | 'BO_' message_id char_string | 'SG_' message_id signal_name char_string | 'EV_' env_var_name char_string) ';' ;
举例:
CM_ SG_ 100 test_signal1 “The left door status” ;
定义帧100中的信号test_signal1的描述为"The left door status"
10. user defined attribute的格式
在DBC中,除了规定的属性以外,还可以有用户自己定义的属性,但是同样需要遵守一定的规则。
用户定义的属性必须使用具有属性默认值的属性定义来定义这些附加属性。对于每个具有为属性定义值的对象,必须定义属性值条目。如果没有为对象定义属性值条目,则该对象的属性值是该属性的默认值。
属性采用如下方法定义:
attribute_definitions = { attribute_definition } ;
attribute_definition = 'BA_DEF_' object_type attribute_name attribute_value_type ';' ;
object_type = '' | 'BU_' | 'BO_' | 'SG_' | 'EV_' ;
attribute_name = '"' C_identifier '"' ;
attribute_value_type = 'INT' signed_integer signed_integer |
'HEX' signed_integer signed_integer |
'FLOAT' double double |
'STRING' |
'ENUM' [char_string {',' char_string}]
attribute_defaults = { attribute_default } ;
attribute_default = 'BA_DEF_DEF_' attribute_name attribute_value
';' ;
attribute_value = unsigned_integer | signed_integer | double |
char_string ;
属性值的定义方法:
attribute_values = { attribute_value_for_object } ;
attribute_value_for_object = 'BA_' attribute_name (attribute_value |
'BU_' node_name attribute_value |
'BO_' message_id attribute_value |
'SG_' message_id signal_name attribute_value |
'EV_' env_var_name attribute_value)
';' ;
举例:
定义一个所有报文都具有的属性
BA_DEF_ BO_ “GenMsgSendType” ENUM “Cyclic”,“Event” ;
因为发送类型是针对报文而言的,所有使用的是BO_,如果是针对信号的,那就使用SG_, GenMsgSendType是定义的属性名字,ENUM指的是枚举类型,它包含两个类型:"Cyclic"和 “Event”
3. 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_
BS_:
BU_: Engine Gateway
BO_ 100 EngineData: 8 Engine
SG_ PetrolLevel : 24|8@1+ (1,0) [0|255] "l" Gateway
SG_ EngPower : 48|16@1+ (0.01,0) [0|150] "kW" Gateway
SG_ EngForce : 32|16@1+ (1,0) [0|0] "N" Gateway
SG_ IdleRunning : 23|1@1+ (1,0) [0|0] "" Gateway
SG_ EngTemp : 16|7@1+ (2,-50) [-50|150] "degC" Gateway
SG_ EngSpeed : 0|16@1+ (1,0) [0|8000] "rpm" Gateway
CM_ "CAN communication matrix for power train electronics
*******************************************************
implemented: turn lights, warning lights, windows";
VAL_ 100 IdleRunning 0 "Running" 1 "Idle" ; # CAN总线和DBC格式
## 1. CAN总线
控制器局域网总线(CAN,Controller Area Network)一般被我们称为CAN总线,常用于汽车各不同原件之间的通信。
### 1.1 CAN总线的组织结构
CAN节点一般由MCU控制器、CAN控制器和CAN收发器组成。
CAN的信号传递介质为一股双绞线,双绞线由一条CAN-High和一条CAN-Low组成,这两条线的电势差用来表征CAN的总线值,在CAN通讯中,低电平代表的是显性电平,高电平代表的是隐性电平
![CAN总线的拓扑结构](CAN%E6%80%BB%E7%BA%BF%E6%8B%93%E6%89%91%E7%BB%93%E6%9E%84.jpeg)
发送节点通过使总线的电平产生变化,将其信息传输到CAN总线上。接收节点通过监听总线的电平,将总线的信息读入接收器上。
CAN总线的数据按照协议以报文的形式发送,并广播到网络中的所有结点。对于每个节点,无论报文是否是发送给自己都进行接收。
### 1.2 CAN的信号结构
CAN通讯的结构是基于帧的,CAN的帧分为两种:标准帧和扩展帧。这也分别对应着两个不同的协议:CAN2.0A和CAN2.0B。帧结构如下图:
![CAN帧结构](%E5%B8%A7%E7%BB%93%E6%9E%84.webp)
以下是帧结构的组成部分:
1. **帧起始**。帧起始是一个显性位电平,当总线空闲时,发送节点发送一个显性电平,所有的接收节点同步于该帧起始位。这一个显性电平的发出代表着一帧信号的开始。
2. **仲裁段**。任何CAN节点在任何时刻都可以向总线发送数据,但总线同一时刻只能发送一帧消息,因此总线在同一时刻接受多个帧时需要通过帧的仲裁段来决定优先级。在进行裁决的时候,依据就是信号的ID,总线会对ID进行逐位的比较,比较的过程中显性电平胜出,隐形电平退出发送。![Alt text](%E4%BB%B2%E8%A3%81%E6%AE%B5%E6%A0%BC%E5%BC%8F.webp)在进行裁决的时候,依据就是信号的ID,总线会对ID进行逐位的比较,比较的过程中显性电平胜出,隐形电平退出发送。![Alt text](%E4%BB%B2%E8%A3%81%E6%AE%B5%E4%BC%98%E5%85%88%E7%BA%A7%E6%AF%94%E8%BE%83.webp)仲裁段的ID越小,优先级越高。仲裁段中除了ID外,还有RTR,这个位是为了区分数据帧和远程帧的。如果在一帧消息内,ID都是完全一样的,数据帧的优先级高于远程帧。
3. **控制段**。两种类型的帧控制段的长度都是六位,在标准帧中的控制段包含IDE,保留位r0以及数据长度DLC;在扩展帧中的控制段包含保留位r0,r1以及数据长度DLC。![Alt text](%E6%8E%A7%E5%88%B6%E6%AE%B5%E7%BB%93%E6%9E%84.webp)
4. **数据段**。数据段根据需要传输的数据长度传输相应的字节,但最大不能超过8byte。![Alt text](%E6%95%B0%E6%8D%AE%E6%AE%B5.webp)
5. **CRC段**。CRC中文的意思是循环冗余校验,其目的就是要对这一帧信号中前面的部分进行校验,以保证数据传输的正确性,校验的部分包括:帧起始、仲裁段、控制段以及数据段。
6. **ACK段**。这一段和CRC是相关的,上一段进行了CRC校验的比对,如果CRC校验结果没有问题的话,接收节点会在总线发送一个显性电平。![Alt text](ACK%E6%AE%B5.webp)
7. **帧结束**。和一开始的帧起始相呼应,帧结束是由七个连续的隐性电平组成。
## 2. DBC格式
DBC(Database CAN)是一种由Vector公司定义的一种网络通信文件格式,是CAN总线数据库文件。CAN总线中传输的二进制帧信号不利于分析报文的具体内容,DBC最基础的作用就是帮助解释二进制的帧信号,以便分析报文信息。
这里附上DBC的官方文档:[DBC file Format Documentation v1.05](http://mcu.so/Microcontroller/Automotive/dbc-file-format-documentation_compress.pdf)
### 2.1 通用描述
**2.1.1关键字**
下面的表格给出了DBC文件中用于标识对象类型的DBC关键字。关键字的具体含义在后面会说到。
| 关键字 | 对象类型 |
| ---- | ---- |
| BU_ | 网络节点 |
| BO_ | 报文 |
| SG_ | 信号 |
| EV_ | 环境变量 |
| SIG_GROUP_ |信号组|
| VAL_TABLE_ | 数值表 |
**2.1.2数据类型**
DBC文件对属性值由数据类型的区分,下表为DBC文件中可选的数据类型。
|符号 |类型|
| ---- | ---- |
unsigned_interger |无符号整型
singed_integer |有符号整型
double |双精度浮点数
char_string| 字符串
C_identifier |C语言变量名
其中`C_identifiers`必须以字母字符或下划线开始,并可以由字母、数字字符和下划线组成。如:`Abc_string`, `acb_123_string`。
**2.1.3 语法描述**
DBC文件中使用扩展的巴斯科范式(Backus-Naur-Format, BNF)表示法来进行语法描述。如下表所示:
符号 |含义
| ---- | ---- |
= |=左侧的名称使用右侧的语法进行定义,简单说就是赋值
;| 使用分号结束一个定义
$\vert$ |垂直条表示替代选项
[ … ]| 反括号内的定义是可选的(0次或一次)
{ … } |大括号内的定义可以重复(0次或多次)
( … )| 括号用于定义分组元素
’ … ’ |连字符中的文本必须按照定义进行显示
(* … *)| 表示注释
### 2.2 DBC文件的结构
DBC文件的整体结构如下所示:
```DBC_file =
version
new_symbols
bit_timing (*已废弃但仍需要*)
nodes
value_tables
messages
message_transmitters
environment_variables
environment_variables_data
signal_types
comments
attribute_definitions
sigtype_attr_list
attribute_defaults
attribute_values
value_descriptions
category_definitions (*已废弃*)
categories (*已废弃*)
filter (*已废弃*)
signal_type_refs
signal_groups
signal_extended_value_type_list
extended_multiplexing ;
描述DBC文件基本通信的文件主要有以下几个:
- Bit_timing
这部分是必须的,但通常为空。。
- nodes
这部分是必须的,定义了网络节点。
- messages
这部分定义了报文和信号。
以下部分未在普通DBC文件中使用。此处仅为完整起见对其进行定义:
- signal_types
- sigtype_attr_list
- category_definitions
- categories
- filter
- signal_type_refs
- signal_extended_value_type_list
官方文档中写道:
DBC files that describe the CAN communication and don’t define any additional
data for system or remaining bus simulations don’t include environment variables.
这段话的具体含义我没太搞懂,但总之就是很多DBC文件没有环境变量的意思。
2.2.1 符号定义的格式
这部分是DBC格式的重点。
1. version和new symbol的格式
CBD文件的开头是version和new symbol组成的标头。versiond的格式为:
version = ['VERSION' '"' { CANdb_version_string } '"' ];
双引号中的内容可以为空,也可以用户自定义。
举例:VERSION " "
或VERSION "1.0"
new symbol的格式为:
new_symbols = [ '_NS' ':' ['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_'] ];
符号定义关键字为NS_
。在DBC文件里第一个new symbol通常为NS_
,但不知为何官方文档给出的为_NS
。
2. bit timing的格式
波特率关键字为BS_
。波特率部分定义了网络的波特率以及BTR寄存器值,此部分已废弃,但是关键字 “BS_” 必须在DBC文件中出现。因此在文件中一般只有一个单独的BS_
。
3. nodes的格式
节点的关键词为BU_
。节点定义了此网络中所有参与通讯的节点,每个节点定义必须是唯一的,命名方式同C语言。
nodes = 'BU_:' {node_name} ;
node_name = C_identifier ;
举例:BU_ : ECU1 ECU2 ECU3 Tester
4. messages的格式(重点)
报文的关键词为BO_
。报文定义了集群中所有帧的名称以及其属性以及在帧上传输的信号。其中message_id在此网络中必须是唯一的,CAN ID可以是标准帧ID或者扩展帧ID,它们不同的地方在于帧ID的长度,标准帧的帧ID长度是11位,也就是帧ID的范围是000-7FF。扩展帧的帧ID长度是29位,也就是帧ID的范围是00000000-7FFFFFFF。
messages = {message} ;
message = BO_ message_id message_name ':' message_size transmitter {signal} ;
message_id = unsigned_integer ;
BO_ message_id为报文的CAN ID,在DCB文件中为十进制,注意有时需要换算为对应的十六进制ID。
message_name = C_identifier ;
message_name命名规则与C语言相同。
message_size = unsigned_integer ;
message_size也就是所谓的DLC,是无符号整型数,单位是Byte,其规定了报文数据域的字节数。标准CAN最大支持8个Byte,CANFD最大支持64个Byte.
transmitter = node_name | ‘Vector__XXX’ ;
transmitter表示报文发送的节点,该节点必须是在nodes部分定义中的某个节点,或者是 ‘Vector__XXX’
。
‘Vector__XXX’
这个字符串的意思是,如果某个报文没有指定发送节点,则必须设置为 ’Vector_XXX’.
举例:BO_ 100 test_message1: 8 ECU1
定义报文test_message1, CAN ID为100(dec),DLC为8,发送方为ECU1。
5. signals的格式
信号的关键字为SG_
。报文的信号部分列出了放置在报文上的所有信号以及信号在报文的数据字段中的位置及其属性。
signal = ‘SG_' signal_name multiplexer_indicator ' : ' start_bit ' | ' signal_size ' @ ' byte_order value_type ' ( ' factor ' , ' offset ' ) ' ' \[ ' minimum ' | ' maximum ' \] ' unit receiver {',' receiver} ;
signal_name = C_identifier ;
上面定义的signal_name对于同一个报文内的信号必须是唯一的。
multiplexer_indicator = ' ' | [m multiplexer_switch_value] [M] ;
其中多路复用器指示器指示该信号是正常信号、复用信号开关还是多路复用信号。“M”(大写)字符将信号定义为多路复用器开关。单个消息中只有一个信号可以是多路复用器开关。
“m”(小写)字符后跟无符号整数将信号定义为由多路复用。
如果多路复用器信号的开关值等于其multiplexer_switch_value,则多路复用信号在消息中传输。(这一项不常见)
start_bit = unsigned_integer ;
signal_size = unsigned_integer ;
start_bit指定了信号在帧的数据段内的起始位,必须在(8*message_size-1)的范围内。signal_size 指信号的长度。
byte_order = '0' | '1' ;
1代表指intel格式,称为小端模式;0代表motorola格式称为大端模式。
value_type = '+' | '-' ;
+表示无符号数, -表示有符号数
factor = double ;
offset = double ;
facator与offset是用来将原始值与物理值之间进行转化,物理值就是我们希望使用的,原始值是报文中记录的值。minumum与maximum表示信号的最大最小值,这四个参数均为为double类型
其中facator和offset参与计算的关系如下:
physical_value = raw_value * factor + offset
raw_value = (physical_value – offset) / factor
从上式中可以看出factor不得为0。
unit为字符串,用来表示信号单位,没有单位则此项为空。
receiver = node_name | 'Vector__XXX' ;
receiver和前面的transmitter一样。
举例:
BO_ 101 test_message2: 8 ECU2
SG_ test_signal2: 10|5@1+ (1,-1) [0|31] “cm” ECU3
定义test_message2中的一个信号test_signal2, 起始位为10,长度为5,采用Intel格式,无符号整型,因子为1,偏移为-1,最小最大值为0和31,单位为cm,接收方是ECU3。
6. value Encodings的格式
信号值的关键字为VAL_
。信号值描述定义了特定信号原始值的编码。
value_descriptions = { value_descriptions_for_signal | value_descriptions_for_env_var } ;
value_descriptions_for_signal = 'VAL_' message_id signal_name { value_description } ';' ;
举例:VAL_ 100 test_signal1 0 “Off” 1 “On” 2 “Reserved” 3 “Invalid” ;
定义message ID 为100的报文中test_signal1的encodings,0的含义是off,1的含义是on,2的含义保留,3表示无效值。
实际上encoding值是为了告诉诊断,测试人员,相对于的值代表什么意思。
这个属性不是必须的,不是每个信号都需要。
7. environment variable的格式
环境变量的关键字为EV_
。此部分略过,因为一般只在系统仿真和总线仿真工具中使用的环境变量。
8. signal group的格式
信号组的关键字为SIG_GROUP_
。信号组用于定义消息中的一组信号。信号组的概念属于功能安全端对端保护(E2E)中的部分,其中的一个目的就是一个组的信号必须共同更新。
signal_groups = 'SIG_GROUP_' message_id signal_group_name repetitions ':' { signal_name } ';' ;
signal_group_name = C_identifier ;
repetitions = unsigned_integer ;
举例:
SIG_GROUP_ 100 test_message1_group 1 : CheckSum_test_message1 test_signal1 RollingCounter_test_message1 ;
定义CAN ID为100的报文中的信号组test_message1_group, repetitions为1,其中的信号包含CheckSum_test_message1,test_signal1,RollingCounter_test_message1。
9. comment的格式
注释的关键字为CM_
。注释部分包含对象注释。主要是说明信号的描述。
comments = {comment} ;
comment = 'CM_' (char_string | 'BU_' node_name char_string | 'BO_' message_id char_string | 'SG_' message_id signal_name char_string | 'EV_' env_var_name char_string) ';' ;
举例:
CM_ SG_ 100 test_signal1 “The left door status” ;
定义帧100中的信号test_signal1的描述为"The left door status"
10. user defined attribute的格式
在DBC中,除了规定的属性以外,还可以有用户自己定义的属性,但是同样需要遵守一定的规则。
用户定义的属性必须使用具有属性默认值的属性定义来定义这些附加属性。对于每个具有为属性定义值的对象,必须定义属性值条目。如果没有为对象定义属性值条目,则该对象的属性值是该属性的默认值。
属性采用如下方法定义:
attribute_definitions = { attribute_definition } ;
attribute_definition = 'BA_DEF_' object_type attribute_name attribute_value_type ';' ;
object_type = '' | 'BU_' | 'BO_' | 'SG_' | 'EV_' ;
attribute_name = '"' C_identifier '"' ;
attribute_value_type = 'INT' signed_integer signed_integer |
'HEX' signed_integer signed_integer |
'FLOAT' double double |
'STRING' |
'ENUM' [char_string {',' char_string}]
attribute_defaults = { attribute_default } ;
attribute_default = 'BA_DEF_DEF_' attribute_name attribute_value
';' ;
attribute_value = unsigned_integer | signed_integer | double |
char_string ;
属性值的定义方法:
attribute_values = { attribute_value_for_object } ;
attribute_value_for_object = 'BA_' attribute_name (attribute_value |
'BU_' node_name attribute_value |
'BO_' message_id attribute_value |
'SG_' message_id signal_name attribute_value |
'EV_' env_var_name attribute_value)
';' ;
举例:
定义一个所有报文都具有的属性
BA_DEF_ BO_ “GenMsgSendType” ENUM “Cyclic”,“Event” ;
因为发送类型是针对报文而言的,所有使用的是BO_,如果是针对信号的,那就使用SG_, GenMsgSendType是定义的属性名字,ENUM指的是枚举类型,它包含两个类型:"Cyclic"和 “Event”
3. 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_
BS_:
BU_: Engine Gateway
BO_ 100 EngineData: 8 Engine
SG_ PetrolLevel : 24|8@1+ (1,0) [0|255] "l" Gateway
SG_ EngPower : 48|16@1+ (0.01,0) [0|150] "kW" Gateway
SG_ EngForce : 32|16@1+ (1,0) [0|0] "N" Gateway
SG_ IdleRunning : 23|1@1+ (1,0) [0|0] "" Gateway
SG_ EngTemp : 16|7@1+ (2,-50) [-50|150] "degC" Gateway
SG_ EngSpeed : 0|16@1+ (1,0) [0|8000] "rpm" Gateway
CM_ "CAN communication matrix for power train electronics
*******************************************************
implemented: turn lights, warning lights, windows";
VAL_ 100 IdleRunning 0 "Running" 1 "Idle" ;