1.dbc文件格式以及数据结构定义

CAN数据通信矩阵如下表所示。

Bit7

Bit6

Bit5

Bit4

Bit3

Bit2

Bit1

Bit0

Byte0

7

6

5

4

3

2

1

0

Byte1

15

14

13

12

11

10

9

8

Byte2

23

22

21

20

19

18

17

16

Byte3

31

30

29

28

27

26

25

24

Byte4

39

38

37

36

35

34

33

32

Byte5

47

46

45

44

43

42

41

40

Byte6

55

54

53

52

51

50

49

48

Byte7

63

62

61

60

59

58

57

56

1.Intel格式

当一个信号的数据长度超过1 个字节(8 位)或者数据长度不超过一个字节但是采用跨字节方式实现时,该信号的高位(S_msb)将被放在高字节(MSB)的高位,信号的低位(S_lsb)将被放在低字节(LSB)的低位。

信号字节传输时低字节在前,高字节在后,信号的起始位为最低字节的最低位。

2.Motorola格式

当一个信号的数据长度超过 1 个字节(8 位)或者数据长度不超过一个字节但是采用跨字节方式实现时,该信号的高位(S_msb)将被放在低字节(MSB)的高位,信号的低位(S_lsb)将被放在高字节(LSB)的低位。这样,信号的起始位就是高字节的低位。

信号字节传输时高字节在前,低字节在后,信号的起始位为最低字节的最低位。

假设有一个dbc文件如下所示:

该信号的高位(S_msb)将被放在低字节(MSB)的高位,所以为摩托罗拉格式。

定义数据如下:

struct ID{

   union {
          uint16_t D;
          //---------
          struct {
          uint16_t frontLeftTorque_lsb:8;//先定义的在低位
          uint16_t frontLeftTorque_msb:8;
         }bit;
   }DATA01;
   
   union {
          uint16_t D;
          //---------
          struct {
          uint16_t frontRightTorque_lsb:8;//先定义的在低位
          uint16_t frontRightTorque_msb:8;
         }bit;
   }DATA23;
   
      union {
          uint16_t D;
          //---------
          struct {
          uint16_t rearLeftTorque_lsb:8;//先定义的在低位
          uint16_t rearLeftTorque_msb:8;
         }bit;
   }DATA45;  
   
   union {
          uint16_t D;
          //---------
          struct {
          uint16_t rearRightTorque_lsb:8;//先定义的在低位
          uint16_t rearRightTorque_msb:8;
         }bit;
   }DATA67;

};

下发数据报文代码示例如下:

  sendFrame.can_id = 0x...;//这样赋值默认标准帧
       sendFrame.can_dlc = 8;//数据长度为 8个字节
       sendFrame.data[0] = ID.DATA01.bit.frontLeftTorque_msb;     //存放数据高位
       sendFrame.data[1] = ID.DATA01.bit.frontLeftTorque_lsb;     //存放数据低位
      
       sendFrame.data[2] = 0x00;  
       sendFrame.data[3] = 0x00;  
       
       sendFrame.data[4] = ID.DATA45.bit.rearLeftTorque_msb;
       sendFrame.data[5] = ID.DATA45.bit.rearLeftTorque_lsb;  
      
       sendFrame.data[6] = 0x00;
       sendFrame.data[7] = 0x00;  

       int bytesSend = write(can_skt, &sendFrame, sizeof(sendFrame)); 
       if(bytesSend != sizeof(sendFrame)){ 
	           printf("Send  Error\n!");
	    }	

2.基于simulink模块搭建RollingCounter以及CheckSum

1.例子报文

chesum检验公式:

校验和 = (字节1 + 字节2 + 字节3 + 字节4 + 字节5 +字节6 + 字节7 + 报文计数器 & 0x0F + 报文ID低字节+ 报文ID中低字节 + 报文ID中高字节 + 报文ID高字节)
校验和 = ((校验和 >> 4) + 校验和) & 0x0F

模块搭建如下:

其中,-15.687为偏移量,1/2048为分辨率。

心跳值模块搭建如下:

3.测试过程中的问题

在实际测试过程中,由于simulnik与C代码有差异性,在测试过程中发现Checksum与实际要下发的值少1,所以会导致checksum校验不对,无法发送完整的下发报文,因此需要严格遵守数据格式,确保数据下发的正确性。checksum发送错误如下:

校验和DA与下发的CA中,发送下去的checksum=C与实际的D少1。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐