DBC系列之DBC格式与属性说明(1)
作者:互联网
快速导航
摘要
DBC是DataBase CAN的缩写,代表CAN的数据库文件,在此文件中详细定义了CAN通信的相关信息,比如消息名,消息ID,信号名,信号的布局等等。CAN网络的通讯就是依据这个文件的描述进行的,虽然现在有其他通讯方式,比如以太网也在用于车载通讯,但就目前而言,DBC的作用还是很强大的。
DBC文件是根据Vector公司的DBC File Format Documentation文件中描述的格式生成的。下面是关于DBC中的一些符号描述。
1. DBC模板
下图中是一个DBC的模板样式,以文本格式打开后的部分信息如下:
2. 通用描述
2.1 关键字
关键字 | 对象类型 |
---|---|
BU_ | 网络节点 |
BO_ | 报文 |
SG_ | 信号 |
EV_ | 环境变量 |
对于表中的关键字如何使用可能现在还不太清楚,但是请勿着急,请继续往下阅读。
2.2 数据类型
与C语言类似,DBC文件中对属性的值也有数据类型的区分,下表中式DBC文件中可选择的数据类型。
符号 | 类型 |
---|---|
unsigned_interger | 无符号整型 |
singed_integer | 有符号整型 |
double | 双精度浮点数 |
char_string | 字符串 |
C_identifier | C语言变量名 |
对于表中前四种不明白的,请自行百度C语言中数据类型,此处不作解释,仅解释一下C_indentifier。C_identifiers必须以字母字符或下划线开始,并可以由字母、数字字符和下划线组成。如:Abc_string, acb_123_string
2.3 语法描述
DBC文件中使用扩展的BNF表示法来进行语法描述。
BNF是指Backus-Naur-Format(巴斯科范式),是一种描述计算机语言语法的符号规则,详细解释请参见百度百科。点此直达!
符号 | 含义 |
= | =左侧的名称使用右侧的语法进行定义,简单说就是赋值 |
; | 使用分号结束一个定义 |
| | 垂直条表示替代选项 |
[ … ] | 反括号内的定义是可选的(0次或一次) |
{ … } | 大括号内的定义可以重复(0次或多次) |
( … ) | 括号用于定义分组元素 |
’ … ’ | 连字符中的文本必须按照定义进行显示 |
(* … *) | 表示注释 |
3. DBC整体格式
整个DBC文件的格式为:
DBC_file =
version
new_sysmbols
bit_timing {*已废弃但仍需要*}
nodes
value_tables
messages
message_transmitters
environment_variables
environment_variables_data
signal_types
comments
attribute_definitions
sigtype_attr_list
attribute_defaults
value_descriptions
category_definitions {*已废弃*}
categories {*已废弃*}
filter {*已废弃*}
signal_type_refs
signal_groups
signal_extended_value_type_list;
3.1 必须部分和非必须部分
必须部分 | 说明 | 非必须部分 | 说明 |
---|---|---|---|
bit_timing | 此部分是必须的但是通常为空 | signal_types | 一般的DBC不使用此部分, 本文不描述相关用法 |
nodes | 此部分是必须的,用于定义网络节点 | sigtype_attr_list | |
messages | 此部分定义报文和信号 | category_definitions | |
— | — | categories | |
— | — | filter | |
— | — | signal_type_refs | |
— | — | signal_extended_value_type_list |
3.2 符号定义的格式
DBC文件的头部包含了版本信息以及新的符号项
3.2.1 version的格式
version = ['VERSION' ' " ' { CANdb_version_string } ' " ' ];
例1:VERSION " "
例2:VERSION " v1.0 "
双引号中的内容可以为空,也可以用户自定义。
3.2.2 new_symbols的格式
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’貌似不太对,但是Vector官方文档是那样写的,这里暂且不管。
3.2.3 bit timing的格式
bit timing部分定义了网络的波特率以及BTR寄存器值,此部分已废弃,但是关键字 “BS_” 必须在DBC文件中出现。
bit_timing = 'BS_:' [ baudrate ' : ' BTR1 ' , ' BTR2 ] ;
baudrate = unsigned_integer ;
BTR1 = unsigned_integer ;
BTR2 = unsigned_integer ;
当前通常写成如下形式,波特率和BTR已不再使用
例:BS_ :
3.2.4 nodes的格式
节点定义了此网络中所有参与通讯的节点,节点定义必须是唯一的,命名方式同C语言。
nodes = 'BU_:' {node_name} ;
node_name = C_identifier ;
例:BU_ : ECU1 ECU2 ECU3 Tester
定义节点ECU1,ECU2,ECU3,以及Tester
3.2.5 messages的格式 [核心部分]
报文部分定义了集群中所有帧的名称以及其属性以及在帧上传输的信号
messages = {message} ;
message = BO_ message_id message_name ':' message_size transmitter {signal} ;
message_id = unsigned_integer ;
其中message_id在此网络中必须是唯一的,CAN ID可以是标准帧ID或者扩展帧ID,它们不同的地方在于帧ID的长度,标准帧的帧ID长度是11位,也就是帧ID的范围是000-7FF。扩展帧的帧ID长度是29位,也就是帧ID的范围是0000 0000-1FFF FFFF。具体的信息请查阅相关CAN协议规范。
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
例:BO_ 101 test_message2: 8 ECU2
定义报文test_message2, CAN ID为101(dec),DLC为8,发送方为ECU2
例:BO_ 103 test_message3: 8 ECU3
定义报文test_message3, CAN ID为102(dec),DLC为8,发送方为ECU3
3.2.6 signals的格式[核心部分]
报文的信号部分列出了放置在报文上的所有信号以及信号在报文的数据字段中的位置及其属性。
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 ;
其中多路复用器指示器指示该信号是正常信号、复用信号开关还是多路复用信号。
“M”(大写)字符将信号定义为多路复用器开关。单个消息中只有一个信号可以是多路复用器开关。
“m”(小写)字符后跟无符号整数将信号定义为由多路复用。
如果多路复用器信号的开关值等于其multiplexer_switch_value,则多路复用信号在消息中传输。
multiplexer_indicator = ' ' | 'M' | m multiplexer_switch_value ;
此项可以被省略。目前博主还没有遇到使用此参数的DBC,有兴趣的同学可以自行研究。
start_bit = unsigned_integer ;
signal_size = unsigned_integer ;
start_bit指定了信号在帧的数据段内的起始位,必须在(8*message_size-1)的范围内。signal_size 指信号的长度。
byte_order = '0' | '1' ;
0代表指intel格式,称为小端模式;1代表motorola格式称为大端模式,详细区别请参见后续文章,本文不作过多阐述。
value_type = '+' | '-' ;
+表示无符号数, -表示有符号数
facator与offset是用来将原始值与物理值之间进行转化,minumum与maximum表示信号的最大最小值,这四个参数均为为double类型
其中facator和offset参与计算的关系如下:
physical_value = raw_value * factor + offset
raw_value = (physical_value – offset) / factor
Tips: 所谓物理值就是我们期望使用的,原始值是报文数据段中携带的值。
unit为字符串,用来表示信号单位,没有单位则此项为空
receiver = node_name | 'Vector__XXX' ;
receiver和前面说到的transmitter一样,这里不再赘述了。
例1:
BO_ 100 test_message1: 8 ECU1
SG_ test_signal1: 8|2@1+ (1,0) [0|3] “” ECU2,ECU3
定义test_message1中的一个信号test_signal1, 起始位为8,长度为2,采用motorola格式,无符号整型,因子为1,偏移为0,最小最大值为0和3,没有单位,所以双引号中没有内容,接收方是ECU2和ECU3。
例2:
BO_ 101 test_message2: 8 ECU2
SG_ test_signal2: 10|5@1+ (1,-1) [0|31] “cm” ECU3
定义test_message2中的一个信号test_signal2, 起始位为10,长度为5,采用motorola格式,无符号整型,因子为1,偏移为-1,最小最大值为0和31,单位为cm,接收方是ECU3。
例3:
BO_ 102 test_message2: 8 ECU3
SG_ test_signal3: 3|16@0+ (1,0) [0|65535] “” ECU1,ECU2
定义test_message3中的一个信号test_signal3, 起始位为3,长度为16,采用intel格式,无符号整型,因子为1,偏移为0,最小最大值为0和65535,没有单位,所以双引号中没有内容,接收方是ECU1和ECU2。
3.2.7 value Encodings的格式
信号值描述定义了特定信号原始值的编码。
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值是为了告诉诊断,测试人员,相对于的值代表什么意思。
这个属性不是必须的,不是每个信号都需要。
3.2.8 environment variable的格式
在环境变量部分中,在系统仿真和总线仿真工具中使用的环境变量。
这个属性通常是用在总线仿真中。
environment_variables = {environment_variable}
environment_variable = 'EV_' env_var_name ':' env_var_type '[' minimum '|' maximum ']' unit initial_value ev_id access_type access_node {',' access_node } ';' ;
env_var_name = C_identifier ;
env_var_type = '0' | '1' | '2' ; (* 0=integer, 1=float, 2=string *)
minimum = double ;
maximum = double ;
initial_value = double ;
ev_id = unsigned_integer ; (* obsolete *)
access_type = 'DUMMY_NODE_VECTOR0' | 'DUMMY_NODE_VECTOR1' | 'DUMMY_NODE_VECTOR2' | 'DUMMY_NODE_VECTOR3' ; (* 0=unrestricted, 1=read, 2=write, 3=readWrite *)
access_node = node_name | 'VECTOR_XXX' ;
同value encodings一样,环境变量也可以有此定义
value_descriptions_for_env_var = 'VAL_' env_var_aname
{ value_description } ';' ;
本文不讨论总线仿真相关的属性,对此部分感兴趣的同学,请自行查阅相关资料。
3.2.9 signal 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。
Tips:细心的同学可能已经注意到,定义结束后有一个分号,在格式定义中是这样表示’;’,这表示语句末尾需要加分号。虽然我们现在都是使用工具修改DBC,但是博主在这里提一下。
简单说明下CheckSum和RollingCounter,CheckSum是校验和,会在发送报文前对组中的信号进行校验,然后将校验结果存在此信号中,RollingCounter是一个计数器,主要目的是预防帧丢失时候出现数据错误。在信号的接收端同样会进行E2E的检验,根据算法检查这两个信号。详细描述不在本文讨论范围之内。
3.2.10 comment的格式
注释部分包含对象注释。主要是说明信号的描述。
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"
例:CM_ “CAN communication matrix for power train electronics” ;
如果是这样写的话,注释会出现在Network的Comment中
3.2.11 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”
4 整体预览
前面基本上都每种属性都举了例子,但是显得比较分散,下面把整体放在一起,大家看一下整体的结构是怎么样的
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_ : ECU1 ECU2 ECU3 Tester
BO_ 100 test_message1: 8 ECU1
SG_ CheckSum_test_message1 : 7|8@0+ (1,0) [0|255] "" ECU2,ECU3
SG_ test_signal1: 8|2@1+ (1,0) [0|3] "" ECU2,ECU3
SG_ RollingCounter_test_message1: 63|4@0+ (1,0) [0|15] "" ECU2,ECU3
BO_ 101 test_message2: 8 ECU2
SG_ test_signal2: 10|5@1+ (1,-1) [0|31] "cm" ECU3
BO_ 103 test_message3: 8 ECU3
SG_ test_signal3: 3|16@0+ (1,0) [0|65535] "" ECU1,ECU2
CM_ SG_ 100 test_signal1 "The left door status" ;
CM_ "CAN communication matrix for power train electronics" ;
BA_DEF_ BO_ "GenMsgSendType" ENUM "Cyclic","Event";
VAL_ 100 test_signal1 0 "Off" 1 "On" 2 "Reserved" 3 "Invalid";
SIG_GROUP_ 100 test_message1_group 1 : CheckSum_test_message1 test_signal1 RollingCounter_test_message1 ;
将以上内容拷贝到文本中,修改文件后缀为.dbc,博主这里命名为test.dbc。打开后如下图:
Tips:注意关键字和属性定义是有先后顺序的,遵循的顺序就是文件头的new_symbols的顺序;再一个就是属性定义条目后面一定有分号,否则是会报错的。如果有手动修改DBC文本的同学,切记!!!
标签:定义,attribute,DBC,value,name,test,格式,signal,属性 来源: https://blog.csdn.net/p1456230/article/details/118407289