Motorola、Intel格式
讲这2个格式首先说一下大小端格式。
大端模式:
低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。例:
(16位宽的数0x1234在小端模式CPU内存中的存放方式(假设从地址0x4000开始存放))
| | |
内存地址
| 0x4000
| 0x4001
|
存放内容
| 0x34
| 0x12
|
大端模式:
字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。例:
| | |
内存地址
| 0x4000
| 0x4001
|
存放内容
| 0x12
| 0x34
|
在dbc中,
Motorola格式:
Motorola格式跟大端格式一样,低地址代表高字节,高地址代表低字节。与Intel不一样,Motorola格式有2种表达方式,一种是Motorola_LSB,另一种是Motorola_MSB,但实际上它们代表的数据结构是一样的,只是表达方式不一样而已,其中Motorola_LSB的起始位是从低字节开始的,而
Motorola_MSB的起始位是从高字节开始的。
以某段报文为例:

使用db++查看layout:

可以看到文本阅读和db++中看到的startbit是不一样的。db++的sb是lsb,而文本中显示的是msb。
从图中可以看到:motorola格式的msb为高字节的最高位。
Intel格式:
Intel格式跟小端格式一样,
低地址代表低字节,高地址代表高字节。
例:


物理值、总线值转换
公式如下:
physical_value = raw_value * factor + offset
raw_value =(physical_value - offset)/ factor
例子:

以车速信号为例:
假设实际车速为50km/h,那么根据公式
(50-0)/0.00390625=12800=0x3200,那么0x3200就是填充在报文中的总线值。
dbc文件详解

含上图所示的几种信息,接下来咱们逐一解释下。
- VERSION、BS_分别表示版本和波特率信息,都可以忽略不填;
- BU_定义总线上的节点名称;
- BO_ MessageId(10进制数表示) MessageName: MessageSize TransmitterBO_表示报文关键字,需要描述报文的ID、名字、长度和发送方;
- SG_ SignalName : StartBit|SignalSize@ByteOrder ValueType (Factor,Offset) [Min|Max] Unit ReceiverSG_为信号关键字,需要描述信号的名字、起始位、长度、字节顺序(motorola为0,Intel为1)、数值类型(+表示无符号,-表示有符号)、精度、偏移量、最值、单位、接收方;
- CM_ Object MessageId/NodeName “Comment”CM_为注释信息,可以为信号、报文添加解释信息,这些在db++文件中和导入到CAN设备后都可以显示出来;
- BA_DEF_ Object AttributeName ValueType Min Max;BA_DEF_DEF_ AttributeName DefaultValue;用来做属性定义,一般只有主机厂才会生成特别详细的dbc文件内容;
小工具分享
其实写这篇文章的初衷是有同事想要帮忙制作dbc文件,于是便写了一个
先来个生成过程的打印信息吧:

脚本的具体功能:
首先在config.xlsx中写入信号列表.xlsx中报文、信号的属性的位置信息(列号),如下图:

然后执行py脚本即可生成dbc文件。没有py环境的可以在dist文件夹下找到同名的exe文件双击执行。
附个视频吧:

py 源码
from openpyxl import load_workbook
from collections import OrderedDict
import xlrd
from telnetlib import NOP
import os,sys
class Xls_Info_cl:
def __init__(self):
#there configs are important.
self.ByteOrder = "Motorola_lsb"
# there configs are necessary.
self.FileName = 'Platform_CANCMX_V0.4.0_FVCM_2022_05_30.xlsx'
self.Sheet = 'Signal Matrix'
self.Start_row = 2
self.MsgID_column = 'B'
self.Msg_Name_column = 'A'
self.Msg_Lenth_column = 'E'
self.Sig_Name_column = 'G'
self.StartBit_column = 'L'
self.Size_column = 'M'
self.ValueType_column = 'N'
self.Sig_Factor_column = 'O'
self.Sig_Offset_column = 'P'
self.Min_column = 'Q'
self.Max_column = 'R'
self.Unit_column = 'Y'
self.Value_Description_column = 'Z'
# there config is not necessary
self.Self_Node_colume = 'AA'
self.Self_Msg_Period_colume = 'D'
self.Sig_Multiplexortype = 'F'
# 获取当前工作目录的绝对路径
script_dir = os.path.dirname(sys.argv[0])
#获取表格内容
file_path = os.path.join(script_dir,'config_ini.xlsx')
workbook_object = load_workbook(filename=file_path)
sheet = workbook_object['config']
Xls_Info = Xls_Info_cl()
Xls_Info.ByteOrder = sheet['B3'].value
Xls_Info.FileName = sheet['B4'].value
Xls_Info.Sheet = sheet['B5'].value
Xls_Info.Start_row = sheet['B6'].value
Xls_Info.MsgID_column = sheet['B7'].value
Xls_Info.Msg_Name_column = sheet['B8'].value
Xls_Info.Msg_Lenth_column = sheet['B9'].value
Xls_Info.Sig_Name_column = sheet['B10'].value
Xls_Info.StartBit_column = sheet['B11'].value
Xls_Info.Size_column = sheet['B12'].value
Xls_Info.Sig_Factor_column = sheet['B13'].value
Xls_Info.Sig_Offset_column = sheet['B14'].value
Xls_Info.Max_column = sheet['B15'].value
Xls_Info.Min_column = sheet['B16'].value
Xls_Info.Unit_column = sheet['B17'].value
Xls_Info.ValueType_column = sheet['B18'].value
Xls_Info.Self_Node_colume = sheet['B19'].value
Xls_Info.Self_Msg_Period_colume = sheet['B20'].value
Xls_Info.Sig_Multiplexortype = sheet['B21'].value
file_path = os.path.join(script_dir,Xls_Info.FileName)
#加载Excel
if '.xlsx' in Xls_Info.FileName:
workbook_object = load_workbook(filename=file_path)
else:
workbook_object = xlrd.open_workbook(filename=(file_path))
#获取表单名称
names= workbook_object.sheetnames #获取表单的名称返回list
# 获取表单
sheet = workbook_object[Xls_Info.Sheet]
def Get_CellValue(column,row):
if column != 'FF' or column != None:
code = sheet[column + str(row)].value
else:
code = None
if type(code) == str:
code = code.replace('0X','').replace('0X','')
elif type(code) == int or type(code) == float:
code = str(code)
else:
code = None
return code
dbc_code = ''
MSg_Comment = ''
Sig_Comment = ''
dbc_txt = ''
last = ''
dbc_canfd = False
for i in range(((int)(Xls_Info.Start_row) + 1),sheet.max_row+1):
if(None != Get_CellValue(Xls_Info.Msg_Name_column,i)):
#eg:BO_ 389 ESCDAFuncSts: 8 Vector__XXX
if None != Get_CellValue(Xls_Info.Msg_Name_column,i) and last != Get_CellValue(Xls_Info.Msg_Name_column,i):
last = Get_CellValue(Xls_Info.Msg_Name_column,i)
if None != Get_CellValue(Xls_Info.Self_Node_colume,i) and (('S' in Get_CellValue(Xls_Info.Self_Node_colume,i)) or ('T' in Get_CellValue(Xls_Info.Self_Node_colume,i))\
or ('s' in Get_CellValue(Xls_Info.Self_Node_colume,i)) or ('t' in Get_CellValue(Xls_Info.Self_Node_colume,i))):
send_node = Get_CellValue(Xls_Info.Self_Node_colume,Xls_Info.Start_row)
receive_node = 'Vector__XXX'
else:
send_node = 'Vector__XXX'
receive_node = Get_CellValue(Xls_Info.Self_Node_colume,Xls_Info.Start_row)
MSG_ID = Get_CellValue(Xls_Info.MsgID_column,i)
MSG_ID = int(MSG_ID,16)
if Get_CellValue(Xls_Info.Msg_Lenth_column,i) != None:
MsgLenth = int(Get_CellValue(Xls_Info.Msg_Lenth_column,i))
else:
#default value is 8
MsgLenth = 8
dbc_code += '\nBO_ ' + str(MSG_ID) + ' ' + Get_CellValue(Xls_Info.Msg_Name_column,i)\
+ ': ' + str(MsgLenth) + ' ' + send_node + '\n'
if MsgLenth > 8:
dbc_canfd = True
if Get_CellValue(Xls_Info.Self_Msg_Period_colume,i) != None:
MSg_Comment += 'BA_ "GenMsgSendType" BO_ ' + str(MSG_ID) + ' 0;\n'
MSg_Comment += 'BA_ "GenMsgCycleTime" BO_ ' + str(MSG_ID) + ' ' + Get_CellValue(Xls_Info.Self_Msg_Period_colume,i) + ';\n'
if None != Get_CellValue(Xls_Info.Sig_Name_column,i):
#start bit is msb in db++,but is lsb in candb++!
if Xls_Info.ByteOrder == 'Motorola_lsb':
""" if 'TrGearRatio' == Get_CellValue(Xls_Info.Sig_Name_column,i):
NOP """
startByte = int(Get_CellValue(Xls_Info.StartBit_column,i))//8
Bit_CAN_Use = 8 - int(Get_CellValue(Xls_Info.StartBit_column,i))%8
Ramain_Bit = int(Get_CellValue(Xls_Info.Size_column,i))
for bitnum in range(int(Get_CellValue(Xls_Info.Size_column,i))):
if Bit_CAN_Use > 0:
#use byte in start bit first
Bit_CAN_Use -= 1
Ramain_Bit -= 1
else:
#use last byte in sb
Bit_CAN_Use = 8
if startByte > 0:
startByte -= 1
Bit_CAN_Use -= 1
Ramain_Bit -= 1
if Ramain_Bit == 0:
startbit = startByte*8 + (8-Bit_CAN_Use) - 1
else:
startbit = int(Get_CellValue(Xls_Info.StartBit_column,i))
# SG_ BrkPdlPosInfo_RllCnt : 51|4@0+ (1,0) [0|15] "" FVCM
if Xls_Info.ValueType_column != 'FF' and Xls_Info.ValueType_column != None and 'u' not in Get_CellValue(Xls_Info.ValueType_column,i)\
and 'U' not in Get_CellValue(Xls_Info.ValueType_column,i):
ValueType = '-'
else:
ValueType = '+'
if Xls_Info.Unit_column != 'FF' and Xls_Info.Unit_column != None and None != Get_CellValue(Xls_Info.Unit_column,i):
Unit = sheet[Xls_Info.Unit_column+str(i)].value.replace(' ','')
else:
Unit = ''
if Xls_Info.Sig_Multiplexortype != 'FF' and Xls_Info.Sig_Multiplexortype != None and None != Get_CellValue(Xls_Info.Sig_Multiplexortype,i):
if 'M' in Get_CellValue(Xls_Info.Sig_Multiplexortype,i) or 'm' in Get_CellValue(Xls_Info.Sig_Multiplexortype,i):
Multi_code = ' m'
else:
Multi_code = ' m' + Get_CellValue(Xls_Info.Sig_Multiplexortype,i)
else:
Multi_code = ''
dbc_code +=' SG_ ' + Get_CellValue(Xls_Info.Sig_Name_column,i) + Multi_code +' : ' + str(startbit) +\
'|' + Get_CellValue(Xls_Info.Size_column,i) + '@0' + ValueType + '(' + Get_CellValue(Xls_Info.Sig_Factor_column,i) + ',' +\
Get_CellValue(Xls_Info.Sig_Offset_column,i) + ') [' + Get_CellValue(Xls_Info.Min_column,i) + '|' +\
Get_CellValue(Xls_Info.Max_column,i) + '] \"' + Unit + '\" ' + receive_node + '\n'
# Sig Comment Gen ,Different manufacturers have different formats, to do.
""" if Xls_Info.Value_Description_column != 'FF' and Xls_Info.Value_Description_column != '' and None != sheet[Xls_Info.Value_Description_column+str(i)].value:
Sig_Comment += 'VAL_ ' + str(MSG_ID) + ' ' + sheet[Xls_Info.Sig_Name_column+str(i)].value.replace(' ','') + ' ' +\
sheet[Xls_Info.Value_Description_column+str(i)].value.replace(' ','').replace('0X','').replace('0x','').replace('\n','" ').replace(':',' "') + '" ;\n' """
dbc_txt +='VERSION ""\n\
\n\
\n\
NS_ : \n\
NS_DESC_\n\
CM_\n\
BA_DEF_\n\
BA_\n\
VAL_\n\
CAT_DEF_\n\
CAT_\n\
FILTER\n\
BA_DEF_DEF_\n\
EV_DATA_\n\
ENVVAR_DATA_\n\
SGTYPE_\n\
SGTYPE_VAL_\n\
BA_DEF_SGTYPE_\n\
BA_SGTYPE_\n\
SIG_TYPE_REF_\n\
VAL_TABLE_\n\
SIG_GROUP_\n\
SIG_VALTYPE_\n\
SIGTYPE_VALTYPE_\n\
BO_TX_BU_\n\
BA_DEF_REL_\n\
BA_REL_\n\
BA_DEF_DEF_REL_\n\
BU_SG_REL_\n\
BU_EV_REL_\n\
BU_BO_REL_\n\
SG_MUL_VAL_\n\
\n\
BS_:\n\
\n\
BU_: Vector__XXX '
dbc_txt += Get_CellValue(Xls_Info.Self_Node_colume,Xls_Info.Start_row) + '\n\n'
dbc_txt += dbc_code
dbc_txt += '\n\nBA_DEF_ BO_ "GenMsgCycleTime" FLOAT 0 300000;\n\
BA_DEF_ BO_ "GenMsgSendType" ENUM "cyclic","spontaneous","immediate";\n\
BA_DEF_ "BaudRate" FLOAT 0 2000000;\n\
BA_DEF_ "BusType" STRING ;\n\
BA_DEF_DEF_ "GenMsgCycleTime" 0;\n\
BA_DEF_DEF_ "GenMsgSendType" "cyclic";\n'
if dbc_canfd == True:
dbc_txt += 'BA_ "BusType" "CAN FD";\n\
BA_ "BaudRate" 2000000;\n'
else:
dbc_txt += 'BA_DEF_DEF_ "BaudRate" 500000;\n\
BA_DEF_DEF_ "BusType" "CAN";"'
dbc_txt += MSg_Comment +'\n'
#dbc_txt += Sig_Comment
print(dbc_txt)
file = open(script_dir+"\\inputfilename.dbc", "w")
file.write(dbc_txt)
file.close()
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
文章转载自公众号:汽车与基础软件