CAN报文DBC解析的编程方法说明

2020-05-21 08:17:09 1081
主要内容

1. 概述
2. 我们要做一件什么事情
  • 在软件框架中的位置
  • DBC介绍
3. 我们怎么去做这件事情
  • 数据存储
  • 输入输出


1
概述
前面介绍过PEAK的所有CAN卡都有提供如下图所示这些二次开发包,非常适合于做二次开发。PCAN-Basic API除了DLL,也提供了C#, C++/MFC, C++/CLR,C++_Builder, Delphi, VB.NET, Java, and Python等的例程,这些例程里面都有实现硬件初始化,报文收发的功能;我们开发更高级的功能只需要在这个基础上来做开发即可。
菲益科
这篇文章介绍在收到报文之后,我们怎么根据DBC文件来解析报文,使报文不再仅仅是一连串十六进制的数,而是具有可读性的内容。
菲益科
接下来我们需要回答以下两个问题
  • 我们要做一件什么事情

  • 我们怎么去做这件事情



值得注意的是,文中提到了在CAN报文传输中,编码方式的区分(IntelMotorola),但限于篇幅,并没有这两种方式做进一步的说明,读者请自行查阅相关资料。

2
我们要做一件什么事情


2.1 DBC解析在软件框架中的位置

回顾一下之前的软件框架

菲益科
DBC解析属于收发报文之后的事情。再回顾一下之前在读取报文时候所用到的流程
菲益科
我们这里需要考虑的问题是在哪个位置解析我们的报文,总共有三个位置可以让我们对收到的报文进行解析,这里我们选择在第三个位置,因为在能实现功能的前提下,越靠后改,对整体的影响越小。
接下来我们要回答的问题是使用DBC去解析报文究竟是一件什么事情,也就是为什么DBC能把报文解析成可读性的内容

2.2 DBC介绍

我把DBC解析报文的过程当成一个映射的过程,也就是这种报文表示什么意思,已经在DBC文件中定义好了。
具体而言,DBC文件中定义了一系列的规则,收到这个ID就代表是这个报文(比如ABS类的),这个报文包含了什么信号(比如ABS的某个传感器状态),数据的第几位到第几位表示这个信号的值。我们根据这些规则来解析报文。所以我们接下来要回答的问题是,为了达到解析报文的目的,一个DBC文件中究竟有哪些规则。
回答这个问题,其实只要把几个规则罗列一下就好了,这将在最后的时候列举出来。在此之前,我们先从最后实现的事情入手,来说明这些规则是起什么作用的。

菲益科
右侧的那些“根据”就是从DBC文件解析出来的。为了让读者更进一步地了解这个内容。本文再以一个.dbc文件为例,来说明我们怎么从DBC文件中获取这些参数。
以记事本方式打开一个.dbc文件。首先是一些下图文件头,这个对DBC解析没什么用,读者可自行了解。
菲益科
接下来是一些什么报文包含哪些信号的说明。BO_ 表明这是一个报文,SG_ 表明这个报文所包含的信号,如果该报文有多个信号,则这里会有多行SG_ 我们所需要的绝大多数参数来源于这里。后面会继续介绍怎么读懂这些BO_ 和SG_
菲益科过了BO_ 和SG_之后接下来的BA_跟我们解析并没有多少关系,这里也就不继续介绍。
过了BA_之后,到了VAL_,这里是一些枚举型变量,说明了每个数值分别代表什么意思。
菲益科综上,我们需要关注其实是BO_ ,SG_以及VAL_这些行。
我们以各自的实例来说明
菲益科
菲益科
菲益科
至此,我们对DBC文件的内容已经有了大概的了解了,这里的了解指的是每个DBC的文件包含了哪些内容,这些内容是怎么对我们的报文解析起作用的。这里再列举如下
Ø 针对整个报文,有报文ID,报文名称,报文数据长度三个重要参数
Ø 针对信号,有信号名称,起始位,位长度,编码类型,数据类型,因子和偏移量,最大值最小值,单位
Ø 针对枚举型变量,有一系列的键值对

3
我们怎么去做这件事情


3.1 数据存储

有了前面的基础,我们就可以依据前面的流程图对报文进行解析了。再次说明如下
1) 读到一个报文,先获取报文ID
2) 打开DBC文件,顺序地读取BO_,发现ID匹配,知道是这个报文
3) 这个报文接下来的SG_,看看有多少信号
4) 每个信号根据起始位,位长度和编码类型十六进制的报文当中有用的位提取出来
5) 根据数据类型进行相应的解码
6) 根据因子和偏移量,将解码的数据再转化成的真实的数据
7) VAL_行进行对比,如果是枚举型变量,将相应数值转为有意义的字符串
8) 加上单位
事情到了这里已经很简单了,问题在于,我们不想要每次读一个报文都去打开DBC文件,而是希望把DBC的内容预先储存在程序当中,所以这里我们需要考虑怎么存储这些数据。
这其实是数据结构的知识,我们只需要搞清楚从属关系就好了。所谓从属关系,就是哪些参数是谁的。这里其实很直观的,我们有两个主体,一个是报文,一个是信号。信号从属于报文,编码方式等参数从属于信号。所以这里数据储存我们只需要做好以下几件事情:
  • 定义一个枚举类,这个类储存枚举型信号的名称和键值对。

  • 定义一个信号类。这个类包含了信号名称,起始位,位长度,编码类型,数据类型,因子和偏移量,最大值最小值,单位。如果是枚举信号,将枚举型信号的键值对也包含进来。

  • 定义一个报文类。这个类包含了报文的ID,报文名称,报文数据长度,以及报文所包含的信号列表。

  • 将报文类构建成一个报文列表。

最终的结果就是我们用一个报文列表把DBC文件的内容存储进来,读到报文要做相应解析时,只要比对十六进制报文跟报文列表的内容做相应的解析即可。

3.2 输入输出

有了前面的准备,接下来的事情就很顺理成章了。我们再来回顾最开始要做的事情。
这里采用逆序思考的方法来看我们怎么做,要做DBC解析,需要先有个已经储存了DBC文件信息的报文列表,要有这个列表,需要预先定义列表所需要的类以及有个DBC文件。然后我们再顺着把事情做一下,把上面的流程图拓展出来。
菲益科
根据这个图,我们可以很明显知道,我们需要做以下四件事情
1. 定义好的相关的类
  • 这些类的属性和方法根据DBC文件所包含的属性来确定

2. 编写一个函数,将给定DBC文件的内容转换成一个报文列表。
  • 输入为DBC文件路径,输出为报文列表。

  • 主要涉及的是文件读取内容,每一行的内容代表什么意思。

3. 编写一个函数,将指定的报文解析成可读性的内容
  • 输入为十六进制的报文和报文列表,输出为可读性的内容

  • 主要涉及的是文件列表中每个参数都有什么作用

4. 在相应的位置引用这个函数
行文至此,根据DBC文件解析十六进制报文的工作也已经完成了。
电话咨询
最新产品
技术支持
QQ客服