配景
迩来在项目中,同事遇到了一个dbc数据库剖析错误的题目:基于ekuiper 对can报文剖析,发实际际输出效果与预期差距较大。当时他第一反应是ekuiper的剖析规则有误,因此就没有跟踪下去了。因为之前我用过ekuiper的CAN报文剖析功能,是没有题目的。因此我更倾向于是他的dbc数据库有题目,于是研究了一下DBC文件剖析的规则,并实际验证。过程中也踩了一些坑,在此记载。盼望能资助到有必要的人。
DBC 数据库介绍
DBC是vector公司界说的can网络通讯文件格式。网上介绍的文章很多,有兴趣的朋友可以去搜索一下。本文的重要核心是剖析DBC信号部分,对于相干信息进行简略描述。
dbc文件一般包含了如下信息:
- 版本与新符号
- 波特率界说
- 网络节点的界说
- 报文帧的界说
- 信号的界说
- 注解部分
- 特征部分
- 数值表部分
版本与新符号
这两个参数一般在文件的开头,tag为VERSION和NS_。此中VERSION可以为空或自界说,NS_一般固定,不必要修改。如下:
- 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_:
[baudrate:BTR1,BTR2]; 含义如下:
- BS_为关键字,用于界说CAN网络的波特率;
- [ ]内容表示为可选部分,可以省略;
注:但关键字BS_:
必须存在,省略则会出错。如下:
网络节点的界说
格式为BU_: Nodename1 Nodename2 Nodename3 ……含义如下:。
- BU_为关键字,表示网络节点;
- Nodename1、Nodename2表示网络节点名字,由用户本身界说。通过网络节点方便地进行CAN网络的计划、开发和测试。如下:
报文帧的界说(重点)
格式为BO_ MessageId MessageName: MessageSize Transmitter含义如下:
- BO_,为关键字,表示报文;
- MessageId,报文ID,是以10进制数表示的;
- MessageName,报文的名字,定名规则和C语言变量相同;
- MessageSize,报文数据域字节数,为无符号整型数据,CAN 2.0为最大8字节,CAN FD 最大64字节;
- Transmitter,该报文的网络节点;如果该报文没有指定发送节点,则该值需设置为” Vector__XXX”。
如下:界说了一个报文ID为0x586的报文,报文名称为RVB_TVR_Debug2_FO, 报文长度仅7Byte,由EOCM_F_FO网络节点发出。
- BO_ 1414 RVB_TVR_Debug2_FO: 7 EOCM_F_FO
复制代码 信号的界说(核心)
格式为:SG_ SignalName (SigTypeDefinition) : StartBit|SignalSize@ByteOrder ValueType (Factor,Offset) [Min|Max] Unit Receiver含义如下:
- SG_为关键字,表示信号;
- SignalName表示该信号的名字;
- SigTypeDefinition是可选项,有3种格式:
a)空,表示普通讯号。
b)M,表示多路选择器信号。
c)m50,表示被多路选择器选择的信号,50,表示当M界说的信号的值等于50的时间,该报文使用此通路。
- StartBit、 SignalSize表示该信号起始位、信号长度,不同的字节序,StartBit含义不同;
- ByteOrder表示信号的字节顺序:0代表Motorola格式,1代表Inter格式;
- ValueType表示该信号的数值范例:+表示无符号数,-表示有符号数;
- Factor,Offset 表示因子,偏移量;这两个值用于信号的原始值与物理值之间的转换。转换如:物理值=原始值*因子+偏移量;
- Min|Max表示该信号的最小值和最大值,即指定了该信号值的范围;这两个值为double范例;
- Unit表示该信号的物理单位,为字符串范例;
- Receiver表示该信号的罗致节点;若该信号没有指定的罗致节点,则必须设置为” Vector__XXX”。
如下:界说了一个VBTOSLonPstn的普通讯号,它的起始值在bit7,长度为12。字节序为Motorola,有符号。因子为0.125,偏移为0。数值的范围为-256~255.875,单位是m,由Dummy_FO网络节点罗致。
- SG_ VBTOSLonPstn : 7|12@0- (0.125,0) [-256|255.875] "m" Dummy_FO
复制代码 注解部分,特征部分,数值表部分在dbc文件中属于非必须部分,本文不再进一步介绍。综上所述,我们得到最小的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
复制代码 案例分析
根据上面的dbc文件,我们进行如下示例分析。向can0网卡发送数据 cansend can0 586#d465737400000000,ekuiper输出以下效果:
- [
- {
- "VBBrkCntlAccel": 0,
- "VBTOSLatPstn": 87.125,
- "VBTOSLonPstn": -87.25,
- "VBTOSObjID": 0,
- "VBTOSTTC": 46.400000000000009
- }
- ]
复制代码 我们实验通过对dbc数据库文件的理解进行分析,看看是否与ekuiper的盘算效果一致。在分析前,我们必要相识几点内容:
- 位序
我们知道字节序是一个对象中的多个字节之间的顺序题目,比特序就是一个字节中的8个比特位(bit)之间的顺序题目。一般情况下系统的比特序和字节序是保持一致的。
比如:二进制数11010100,若比特序为大端msb,则最高有效比特位在高位,最低有效比特位在低位,那么它代表的值为0xd4;若比特序为lsb,则最高有效比特位在低位,最低有效比特位在高位,那么它代表的值为0x2b。CAN 总线协议中规定,位序都是大端模式,即 msb。
- motorola和inter字节序
在dbc文件剖析中,信号界说中有一个参数ByteOrder表示信号的字节顺序。分别为inter和Motorola两种格式。
- Intel格式跟小端格式一样,低地址代表低字节,高地址代表高字节。
- Motorola格式跟大端格式一样,低地址代表高字节,高地址代表低字节。
注:Motorola格式有2种表达方式,一种是Motorola_LSB,另一种是Motorola_MSB。Motorola_LSB的起始位是从低字节开始的,而Motorola_MSB的起始位是从高字节开始的。dbc文件默认表示Motorola_MSB表达方式,而CANdb++则是Motorola_LSB。
分析:
- 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;
- 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。</font color=blue>因为该信号为有符号数,因此最高位1,则表示该值为负。其原始值的补码为110101000110,则原始值为101010111010=-698。物理值=-698*0.125+0=-87.25。
同样的dbc文件,若由CANdb++进行剖析,如下。可知Startbit与dbc文件不一致。因为CANdb++默认是Motorola_LSB表达方式。
若我的内容对您有所资助,还请关注我的公众号。不定期分享干活,剖析案例,也可以一起讨论分享。
我的宗旨:
踩完您工作中的所有坑并分享给您,让你的工作无bug,人生尽是坦途。
总结
经过两天的查阅资料,以及咨询同事,算是熟悉了dbc数据库的剖析规则。盼望本篇文章,能够资助到各位小搭档。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |