当前位置:   article > 正文

车辆CAN信号,依据DBC文件解析流程_dbc文件解析can报文

dbc文件解析can报文

CAN信号解析流程

1.车辆CAN对应dbc文件

DBC文件是一种用于描述CAN(Controller Area Network)数据通信协议的文件格式,DBC文件中包含了CAN数据的信号定义、编码方式、单位、范围等信息,可以用于解析和生成CAN数据帧。

一个DBC文件通常包含多个数据帧和信号定义,每个数据帧包含了一个或多个信号,每个信号描述了CAN数据的一个或多个位。

dbc文件一个数据包包含内容如下:

 一个信号包含的有效内容:

Name

信号名称

Startbit

信号起始位

Length

信号长度

Byte Order

信号字节序(即大小端)

Value Type

信号数据类型

Factor

信号倍率

Offset

信号偏移量

Minimum

信号最小值

Maximum

信号最大值

2.解析步骤

信号解析公式:

实际值 = (十进制值 * Factor)+ Offset;

十进制值:接收的CAN数据包中,将信号对应的bit位长度取出,所对应的十进制数据值

解析步骤:

  1. 获取信号所需信息

  2. 判断数据是否需进行字节序转换

  3. 获取信号的十进制值

  4. 判断十进制值是否需要向有符号,浮点型转化

  5. 根据公式进行计算信号实际值

补充说明:二进制数据中,通常将最右边的位称为最低位(LSB),最左边的位称为最高位(MSB)。因此,在二进制数据中,bit0通常是指最右边的位,也就是最低位。

LSB的全称是"Least Significant Bit",:意为最低有效位;LSB位于二进制数的最右侧。数据位的最低位。
MSB的全称是"Most Significant Bit",:意为最高有效位。MSB位于二进制数的最左侧。数据位的最高位。

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

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

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

3.解析精度说明

针对dbc信号不同类型信号解析的精度说明。

目前dbc信号数据类型有:

Unsigned

需精度控制,数量占比85%以上

Signed

需精度控制,数量占比10%左右

Double

正常数据类型解析

Float

正常数据类型解析

Unsigned、Signed需精度控制类型说明:

针对这两类的信号数据精度,可采用整形,浮点型。

针对这两类的信号数据精度要求浮点型,则有Float和Double如下考虑:

Float和Double同样是两种浮点数类型。其中Float占用4个字节(32位),Double占用8个字节(64位)。

在精度方面:Double类型的精度要比Float类型高。Double类型可以表示的范围更广,小数点后的位数也更多,因此可以更精确地表示小数。

在使用性能方面:由于Double类型占用的内存空间更大,因此在处理大量浮点数运算时,Double类型的计算速度会比Float类型慢。

推荐高性能计算使用:Float类型

推荐高精度计算使用:Double类型

4.示例

Signed类型解析:

接收数据包的值为:f4 fc 00 00 00 00 00 00 (此数据包为16进制)

1. 获取信号所需信息

  1. {
  2. "start_bit": 0,
  3. "bit_length": 16,
  4. "factor": 0.1,
  5. "offset": 0,
  6. }

2. 判断数据是否需进行字节序转换

考虑底层(mcu)是否统一发送格式,统一大端或者小端,请于底层进行确认!!

当前内容需进行大小端转换。

f4 fc 00 00 00 00 00 00 == 》》00 00 00 00 00 00 fc f4

3. 获取信号的十进制值

二进制数据中,通常将最右边的位称为最低位(LSB),最左边的位称为最高位(MSB)。因此,在二进制数据中,bit0通常是指最右边的位,也就是最低位。

将获取的数据转化为二进制;

根据:start_bit 以及 bit_length,从信号的 bit 0 位 开始,取出总长度为 16 的数据串,并且转化为十进制数据值。

4. Signed需要向有符号转化

此处需将无符号转化为有符号数据。

当前使用取反加1法进行转化,(此外还有符号位扩展法,补码表示法)

将十进制值 转化为 二进制 并且 进行取反加1法,再转化为十进制

即-780

5. 根据公式进行计算信号实际值

根据计算公式:即可得出 signal = (-780 * 0.1)+ 0.0 = -78.0

所以接收到 signal 数据值为 -78

Unsigned类型解析:

接收数据包的值为:cc 0c 00 00 00 00 00 00 (此数据包为16进制)

1. 获取信号所需信息

  1. {
  2. "start_bit": 1,
  3. "bit_length": 15,
  4. "factor": 0.01,
  5. "offset": 0,
  6. }

2. 判断数据是否需进行字节序转换

考虑底层(mcu)是否统一发送格式,统一大端或者小端,请于底层进行确认!!

当前内容需进行大小端转换。

cc 0c 00 00 00 00 00 00 ==》》00 00 00 00 00 00 0c cc

3. 获取信号的十进制值

二进制数据中,通常将最右边的位称为最低位(LSB),最左边的位称为最高位(MSB)。因此,在二进制数据中,bit0通常是指最右边的位,也就是最低位。

将获取的数据转化为二进制;

根据:start_bit 以及 bit_length,从信号的 bit 1位开始,取出总长度为 15 的数据串,并且转化为十进制数据值。

4. Unsigned不需要向有符号,浮点型转化,跳过。

5. 根据公式进行计算信号实际值

根据计算公式:即可得出 signal = (1638 * 0.01)+ 0.0 = 16.38

所以接收到 signal 数据值为16.38

Double、Float类型解析

Double、Float类型解析同Signed类型解析流程。

需要注意流程 4向有符号,浮点型转化,这块步骤有所差异,请注意。

类型转化说明

64756(十进制) 向有符号转化 : 二进制取反加1  ==》-780

64756(十进制) 向有浮点转化 :???待补充

C++编码解析

流程3:

  1. uint64_t jiexi_fun(
  2. uint16_t startbit, uint8_t length, const uint8_t *rawdata, std::string endian) {
  3. uint64_t data{0};
  4. uint8_t lsbbit = startbit % 8;
  5. uint8_t lsbbyte = startbit / 8;
  6. if (endian == "Motorola") {
  7. uint8_t msbbyte = lsbbyte - (lsbbit + length - 1) / 8;
  8. for (int i{msbbyte}; i < lsbbyte + 1; i++) {
  9. data+= ((uint64_t)rawdata[i]) << ((lsbbyte - i) * 8);
  10. }
  11. } else {
  12. uint8_t msbbyte = (startbit + length - 1) / 8;
  13. for (int i{msbbyte}; i >= lsbbyte; i--) {
  14. data += (((uint64_t)rawdata[i]) << (i - lsbbyte) * 8);
  15. }
  16. }
  17. data= data>> lsbbit;
  18. data <<= (64 - length);
  19. data >>= (64 - length);
  20. return data;
  21. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/585894
推荐阅读
相关标签
  

闽ICP备14008679号