小聊一下excel生成dbc

无聊逛51
发布于 2023-11-9 13:55
浏览
0收藏

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的起始位是从高字节开始的。

以某段报文为例:

小聊一下excel生成dbc-鸿蒙开发者社区

使用db++查看layout:

小聊一下excel生成dbc-鸿蒙开发者社区

可以看到文本阅读和db++中看到的startbit是不一样的。db++的sb是lsb,而文本中显示的是msb。

从图中可以看到:motorola格式的msb为高字节的最高位。

Intel格式:

  Intel格式跟小端格式一样,

低地址代表低字节,高地址代表高字节

例:

小聊一下excel生成dbc-鸿蒙开发者社区

小聊一下excel生成dbc-鸿蒙开发者社区

物理值、总线值转换

公式如下:

physical_value = raw_value * factor + offset

raw_value =(physical_value - offset)/ factor

例子:

小聊一下excel生成dbc-鸿蒙开发者社区

以车速信号为例:

假设实际车速为50km/h,那么根据公式

(50-0)/0.00390625=12800=0x3200,那么0x3200就是填充在报文中的总线值。

dbc文件详解

小聊一下excel生成dbc-鸿蒙开发者社区

含上图所示的几种信息,接下来咱们逐一解释下。

  1. VERSION、BS_分别表示版本和波特率信息,都可以忽略不填;
  2. BU_定义总线上的节点名称;
  3. BO_ MessageId(10进制数表示) MessageName: MessageSize TransmitterBO_表示报文关键字,需要描述报文的ID、名字、长度和发送方;
  4. SG_ SignalName : StartBit|SignalSize@ByteOrder ValueType (Factor,Offset) [Min|Max] Unit ReceiverSG_为信号关键字,需要描述信号的名字、起始位、长度、字节顺序(motorola为0,Intel为1)、数值类型(+表示无符号,-表示有符号)、精度、偏移量、最值、单位、接收方;
  5. CM_ Object MessageId/NodeName “Comment”CM_为注释信息,可以为信号、报文添加解释信息,这些在db++文件中和导入到CAN设备后都可以显示出来;
  6. BA_DEF_ Object AttributeName ValueType Min Max;BA_DEF_DEF_ AttributeName DefaultValue;​用来做属性定义,一般只有主机厂才会生成特别详细的dbc文件内容;​​

小工具分享

其实写这篇文章的初衷是有同事想要帮忙制作dbc文件,于是便写了一个

先来个生成过程的打印信息吧:

小聊一下excel生成dbc-鸿蒙开发者社区

脚本的具体功能:

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

小聊一下excel生成dbc-鸿蒙开发者社区

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

附个视频吧:

小聊一下excel生成dbc-鸿蒙开发者社区

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()

文章转载自公众号:汽车与基础软件

分类
已于2023-11-9 13:55:10修改
收藏
回复
举报
回复
    相关推荐