精华内容
下载资源
问答
  • 本文主要描述的是汽车行业中如何通过Vector工具CANdb++ Editor去创建DBC文件,本文主要通过图片的方式去指导用户去创建DBC,创建DBC的过程比较麻烦,所以我写了一个上位机可以直接通过Excel生成DBC文件,

    一、摘要

    1.描述

    本文主要描述的是汽车行业中如何通过Vector工具CANdb++ Editor去创建DBC文件,本文主要通过图片的方式去指导用户去创建DBC,创建DBC的过程比较麻烦,所以我写了一个上位机可以直接通过Excel生成DBC文件,但是我们首先要通过官方工具来创建DBC文件,这样才能更好的理解它的原理和内容。

    2.关键字

    DBC,DBC创建,CANdb++ Editor,CANoe,CAN。

    二、什么是DBC文件

    DBC是Database Can的缩写,其代表的是CAN的数据库文件,在这个文件中把CAN通讯的信息定义的非常完整清楚,而CAN网络的通讯就是依据这个文件的描述进行的,所以DBC文件的作用非常强大,正是因为有了它才可以使得整个CAN网路的节点控制器无差错的协同同步开发。

    三、DBC创建环境

    • Windows操作系统电脑一台。
    • 安装Vector工具CANoe。

    四、DBC创建过程

    1.软件运行

    • 方法一
      通过CANoe的Tools ->CANdb++ Editor运行。
      在这里插入图片描述
    • 方法二
      通过安装目录启动运行。
      在这里插入图片描述

    2.新建DBC文件

    打开CANdb++ Editor软件后,点击工具栏”File”下的”Create Database”,此时界面如下图所示。按需求选择模板,点击OK,然后选择保存路径,即完成DBC数据库文件的创建了。
    在这里插入图片描述
    在这里插入图片描述

    3.新建数值表

    数值表就是信号值描述,点击工具栏”View”下的”Value Tables”,右键空白部分,选择”New”进行新建。此时界面如下图所示,完成数值表名字及数值定义后,点击确定即完成该信号数值表的创建了,依次再将其它需要的数值表。
    在这里插入图片描述
    在这里插入图片描述

    4.新建信号消息

    右键点击”Signals”选择”New”进行信号的新建,此时界面如下图所示。根据通讯矩阵中对于该信号的定义进行设置,并关联上我们上一步创建的该信号的数值表,点击确定即完成了信号的创建,依次完成其他两个信号的创建工作。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    5.新建报文消息

    右键点击”Message”,选择”New”,此时的设置界面如下图所示,按通讯矩阵定义的报文信息进行设置,可添加描述信息。在这里可以关联之前建立的信号消息,点击确定即完成当前报文的建立工作。在建立其他报文时,可以以这个为模板进行复制操作再进行修改;也可重新创建。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    6.新建网络节点

    右键点击”Network nodes”,选择”New”,此时的设置界面如下图所示,这里我们只需输入创建的网络节点名字进行新建操作就行,可以在此添加报文信息,有多少节点就需要创建多少个节点。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    7.新建自定义属性

    在”View”下点击”Attribute Definitions”,右击选择”New”,按需要可以进行对报文、信号、节点、环境变量等进行属性创建。
    Attribute Definitions”中的属性也可以通过从其他已有的DBC文件中进行导入;操作如下:在”File”中选择”Import Attribute Definitions”,选择要导入的DBC文件,即可将该DBC中的属性定义导入到我们现在的DBC文件中来。
    根据上面的步骤我们完成了属性的自定义或导入工作;此时再双击打开信号、报文、或者节点,在其”Attributes”项下可以看到我们前面定义/导入的属性及其值;此时可根据通讯矩阵的定义对其进行修改设置。
    在这里插入图片描述
    在这里插入图片描述

    8.文件检查

    经过前面的几个步骤其实已经完成数据库文件的创建了。但我们还需要通过检查来确保数据库文件中的对象及内部关系的一致性。在”File”中选择”Consistency Check”,此时会在一致性检查窗口中输出检查结果,会有状态信息及对应的说明,以供我们检查出错/警告报警的原因。
    在这里插入图片描述

    五、MatrixCreat工具

    这儿我只把链接放上,具体使用说明见后续章节。
    DBC转Excel;DBC转位定义;Excel转DBC;Excel转位定义:https://download.csdn.net/download/weixin_44926112/12671320

    六、其他

    本文主要是讲解CANdb++ Editor工具的使用,有些地方可能会有描述性的错误,希望看到的朋友及时指出,我会及时更正错误,其他地方有些借鉴的描述,写此文章的目的是为了交流,非商业用途,欢迎私信讨论,感谢大家阅读。

    七、参考

    【1】:https://blog.csdn.net/lichenda/article/details/106958877
    【2】:https://blog.csdn.net/weixin_44536482/article/details/88914753

    展开全文
  • 详情:可以通过客户给Excel矩阵表通过配置生成DBC文件和位定义文件,也可以通过客户给的DBC文件生成Excel矩阵表和位定义文件, 附件里有demo模板,可自己创建配置ini文件,具体使用说明见博客会讲解:...
  • DBC文件详解一、摘要1.描述2.关键字二、为什么要了解DBC文件三、DBC文件构成1.版本2....本文主要描述是汽车行业中DBC文件格式,如何去解析它,如何通过文本编辑器去修改它,了解DBC文件之前如果不

    一、摘要

    1.描述

    本文主要描述的是汽车行业中DBC文件的格式,如何去解析它,如何通过文本编辑器去修改它,了解DBC文件之前如果不懂DBC的请去查看我之前的博客。

    2.关键字

    DBC,DBC解析,DBC数据库,DBC文件,C#解析DBC文件。

    二、为什么要了解DBC文件

    DBC文件在汽车行业应用十分广泛,如果编辑DBC文件我们都使用Vector工具CANdb++ Editor去编辑,那效率将会是十分的低下,当我们了解了DBC文件的构成后,我们可以通过其他方式进行解析,可以大大的提高工作的效率,我们可以通过记事本或者其他工具打开DBC文件。
    在这里插入图片描述

    三、DBC文件构成

    1.版本

    关键字:VERSION
    格式:VERSION "version"
    version就是版本信息,版本信息可以为空,但是不能省略""符。
    例如:VERSION "V1.0"代表版本号为V1.0。
    在这里插入图片描述

    2.新符号

    关键字:NS_:
    DBC生成后都会自动生成新符号,所以这一部分的信息我们无需过多留意,一般默认即可,如果是通过其他方式去生成DBC文件时,可以直接复制该信息即可。
    在这里插入图片描述

    3.波特率

    关键字:BS_:
    格式:BS_:[baudrate:BTR1,BTR2]
    其中[ ]内容表示为可选部分,可以省略,但关键字”BS_:”必须存在,省略会出错。
    在这里插入图片描述

    4.网络节点

    关键字:BU_:
    格式:BU_: name1 name2 name3 …
    格式中的name1 、name2 等表示定义的网络节点名字,由用户自己定义;但需保证节点命名的唯一性。
    例如:BU_: GW代表网络节点有GW。

    5.报文消息

    关键字:BO_
    格式:BO_ Msg_ID Msg_Name: Msg_Length Msg_Transmitter
    Msg_ID:报文标识符,十进制表示。
    Msg_Name:报文名称,命名规则和C语言变量相同。
    Msg_Length :报文长度,长度范围为0-8。
    Msg_Transmitter:发送节点,如果该报文没有指定发送节点,则该值需设置为” Vector__XXX”。
    例如:BO_ 1024 BCM_400: 8 BCM代表报文ID为0x400,报文名称为BCM_400,长度为8一个字节,发送节点为BCM。
    在这里插入图片描述

    6.信号消息

    关键字:SG_
    格式:SG_ Signal_Name : Start_Bit|Bit_Length@Byte_Order Date_Type (Factor, Offset) [Signal_Min_Value_Phy|Signal_Max_Value_Phy] “Unit” Receivers
    Signal_Name:信号名称,命名规则和C语言变量相同。
    Start_Bit:信号的起始位,范围为0-63。
    Bit_Length:信号的长度,范围为1-64。
    Byte_Order:信号的字节顺序:0代表Motorola格式,1代表Inter格式,这儿强调一下Motorola格式下的文本存储的是Motorola Msb格式的;
    Date_Type:信号的数值类型:+表示无符号数,-表示有符号数。
    Factor:精度。
    Offset:偏移量,Factor和Offset这两个值于该信号的原始值与物理值之间的转换,转换如下:物理值=原始值*因子+偏移量。
    Signal_Min_Value_Phy:物理总线最小值。
    Signal_Max_Value_Phy:物理总线最大值。
    Unit:信号的单位,为字符串类型,可以省略。
    Receivers:信号的接收节点,若该信号没有指定的接收节点,则必须设置为” Vector__XXX”。
    例如:SG_ BCM_WakeUp : 0|1@0+ (1,0) [0|1] “%” Vector__XXX代表信号名称为BCM_WakeUp,信号起始位为0,信号长度为 1,排列格式为Motorola Msb,数据类型为无符号,精度为1,偏移量为0,单位为%,无接收节点。
    在这里插入图片描述

    7.注释

    关键字:CM_
    格式:CM_ Object Msg_ID/Signal_Name “Signal_Description;”
    Object:注解的对象类型,可以是节点“BU_”、报文“BO_”、消息”SG_”。
    Msg_ID:报文标识符,十进制表示。
    Signal_Name:信号名称,命名规则和C语言变量相同。
    Signal_Description:信号描述,为字符串类型。
    例如:CM_ BO_ 1024 “网络管理报文”;代表报文ID为0x400的报文描述为网络管理报文。
    CM_ SG_ 1024 BCM_WakeUp “唤醒信号”;代表报文ID为0x400的报文中信号名称为BCM_WakeUp的描述信息为唤醒信号。
    在这里插入图片描述

    8.自定义属性

    • 关键字:**BA_DEF_ **
      格式:BA_DEF_ Object AttributeName ValueType Min Max;”
      Object:注解的对象类型,可以是节点“BU_”、报文“BO_”、消息”SG_”、网络节点” ”(用空格表示)。
      AttributeName: 自定义属性名称,命名规则和C语言变量相同。
      ValueType:属性值的类型,可以是整型、字符串、浮点型、枚举类型等。
      Min:属性值的最小值(字符串类型没有此项)。
      Min:属性值的最大值(字符串类型没有此项)。
      例如:BA_DEF_ “ECU” STRING ;代表自定义网络节点属性名称为ECU,类型为字符串型。
      BA_DEF_ BO_ “MsgCycleTime” INT 0 1000;代表自定义报文属性名称为MsgCycleTime,类型为整型,取值范围为0-1000。

    • 关键字:**BA_DEF_DEF_ **
      格式:BA_DEF_DEF_ AttributeName DefaultValue;”
      AttributeName: 自定义属性名称,命名规则和C语言变量相同。
      DefaultValue:默认值。
      例如:BA_DEF_DEF_ “MsgCycleTime” 0;代表自定义属性名称为MsgCycleTime的默认值为0。

    • 关键字:BA_
      格式:BA_ AttributeName Object /Signal_Name Msg_ID DefaultValue;”
      AttributeName: 自定义属性名称,命名规则和C语言变量相同。
      Object:注解的对象类型,可以是节点“BU_”、报文“BO_”、消息”SG_”、网络节点” ”(用空格表示)。
      Signal_Name:信号名称,命名规则和C语言变量相同。
      Msg_ID:报文标识符,十进制表示。
      DefaultValue:默认值。
      例如:BA_ “MsgCycleTime” BO_ 1024 0;代表自定义报文ID为0x400的报文属性名称MsgCycleTime值为100。
      在这里插入图片描述

    9.数值表

    关键字:VAL_
    格式:VAL_ Msg_ID Signal_Name N “DefineN” …… 0 “Define0”;”
    Msg_ID:报文标识符,十进制表示。
    Signal_Name:信号名称,命名规则和C语言变量相同。
    N “DefineN” …… 0 “Define0”:表示定义的数值表内容,即该信号的有效值分别用什么符号表示。
    例如:VAL_ 1024 BCM_WakeUp 1 “off” 0 “on” ;代表报文ID为0x400中的信号名称为BCM_WakeUp的值0x01代表off,0x00代表on。
    在这里插入图片描述

    四、DBC文件解析

    通过以上描述,我相信各位对DBC文件的结构有一定的了解,但是我们如何去解析呢,很多人第一时间想到的应该是按行解析,其实DBC文件有许多容错处理,单纯按行解析我们会错过许多细节部分,例如下图其实也没有出错,如果按行解析的话报文就解析不到了。
    在这里插入图片描述
    还有很多类似的容错处理在里面,所以单纯按行解析是不行的,并且有的时候也是不能通过空格来分开数据的,比如带有“”的前后是可以不追加空格的。
    在这里插入图片描述
    经过好久的挣扎,查询资料,终于在一个博客的找到了一种解析的方式,通过正则表达式去解析,当然他其实是按行解析,其实会丢掉一些数据,我将方法进行了一些简单的优化,先读取整个文件到字符串,把多行空格转换成一行空格,然后把换行符转换成空格符,然后进行查找,然后按照标准进行拆分。我这边解析的主要使用的C#语言,因为C#语言对字符串有友好的操作,我将部分代码粘贴如下,方便大家参考学习。

    1.解析版本

           /***********************************************
              * Name    :AnalysisDBCVersion
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCVersion(string data)
            {
                string pattern = "VERSION(([ ]+)|)\"((\\w+)|)\"";
                MatchCollection matchs = Regex.Matches(data, pattern);
                foreach (Match match in matchs)
                {
                    if (matchs.Count == 1)
                    {
                        string[] array = match.Value.Split(new string[] {@"""" }, StringSplitOptions.RemoveEmptyEntries);
                        if (array.Length >= 2)
                        {
                            string version = array[1];
                        }
                        return true;
                    } 
                }
                return true;
            }
    

    2.解析报文消息

           /***********************************************
              * Name    :AnalysisDBCMessagePattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCMessagePattern(List<Message> messages, string data)
            {
                string pattern = "BO_[ ]+(\\d+)[ ]+(\\w+):(([ ]+)|)(\\d+)[ ]+(\\w+)";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    string[] array = match.Value.Split(new string[] { " ", ":" }, StringSplitOptions.RemoveEmptyEntries);
                    Message message = FindCanMsg(messages, (uint)ConvertToInt(array[1]));
                    if (message != null)
                    {
                        ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                        return false;
                    }
                    message = new Message();
                    message.ID = (uint)ConvertToInt(array[1]);
                    message.Name = ConvertToName(array[2]);
                    message.DLC = ConvertToInt(array[3]);
                    message.Transmitter = array[4].Replace(" ", "") == "Vector__XXX" ? null : array[4].Replace(" ", "");
                    message.CycleTime = message.CycleTimeFast = message.NrOfRepetition = message.DelayTime = -1;
                    messages.Add(message);
                }
                return true;
            }
    

    3.解析信号消息

           /***********************************************
              * Name    :AnalysisDBCSignalPattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCSignalPattern(List<Message> messages, string data)
            {
                string pattern = "SG_[ ]+(\\w+)(([ ]+)|)(((m)(\\d+[ ]+))|(M[ ]+))?:(([ ]+)|)(\\d+)(([ ]+)|)\\|(([ ]+)|)(\\d+)(([ ]+)|)@(([ ]+)|)([0|1])(([ ]+)|)([+|-])(([ ]+)|)+\\((([ ]+)|)(-?\\d+(\\.\\d+)?)(([ ]+)|),(([ ]+)|)(-?\\d+(\\.\\d+)?)(([ ]+)|)\\)(([ ]+)|)\\[(([ ]+)|)(-?\\d+(\\.\\d+)?)(([ ]+)|)\\|(([ ]+)|)(-?\\d+(\\.\\d+((E\\+\\d+)|))?)(([ ]+)|)\\](([ ]+)|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"(([ ]+)|)(\\w+(,[ ]*\\w+)*)";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    Signal signal = new Signal();
                    string strPre = data.Substring(0, data.IndexOf(match.Value));
                    pattern = "BO_[ ]+(\\d+)[ ]+(\\w+):(([ ]+)|)(\\d+)[ ]+(\\w+)";
                    MatchCollection mc = Regex.Matches(strPre, pattern);
                    if (mc.Count == 0)
                    {
                        ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                        return false;
                    }
                    string[] arr = mc[mc.Count - 1].Value.Split(new string[] { " ", ":" }, StringSplitOptions.RemoveEmptyEntries);
                    uint id = (uint)ConvertToInt(arr[1]);
                    Message message = FindCanMsg(messages, id);
                    if (message == null)
                    {
                        ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                        return false;
                    }
                    string str = match.Value.Replace("+", " +").Replace("-", " -");
                    string[] array1 = str.Split(new string[] { @"""" }, StringSplitOptions.None);
                    string[] array2 = array1[0].Split(new string[] { " ", ":", ",", "|", "@", "(", ")", "[", "]" }, StringSplitOptions.RemoveEmptyEntries);
                    int startbit = ConvertToInt(array2[2]);
                    int bitlenth = ConvertToInt(array2[3]);
                    int sigbyte = (startbit / 8 + (bitlenth - 1) / 8 + ((startbit % 8 + 1 - ((bitlenth % 8) == 0 ? 8 : (bitlenth % 8))) >= 0 ? 0 : 1));
                    int sigbit = (startbit + 8 + 1 - bitlenth % 8) % 8;
                    int siglsb = sigbyte * 8 + sigbit;
                    signal.Name = ConvertToName(array2[1]);
                    signal.Startbit = array2[4] == "0" ? siglsb : ConvertToInt(array2[2]);
                    signal.Length = ConvertToInt(array2[3]);
                    signal.ByteOrder = (ByteOrderEnum)ConvertToInt(array2[4]);
                    signal.DataType = array2[5] == "-" ? DataTypeEnum.Signed : DataTypeEnum.Unsigned;
                    signal.Factor = ConvertToDouble(array2[6]);
                    signal.Offst = ConvertToDouble(array2[7]);
                    signal.MinValuePhy = ConvertToDouble(array2[8]);
                    signal.MaxValuePhy = ConvertToDouble(array2[9]);
                    signal.Unit = array1[1].Replace(" ", "");
                    signal.Receivers = array1[2].Replace(" ", "") == "Vector__XXX" ? null : array1[2].Replace(" ", "");
                    signal.InitValue = signal.InvalidValue = signal.InvalidValue = signal.InactiveValue = signal.MinValue = signal.MaxValue = -1;
                    message.Signals.Add(signal);
                }
                return true;
            }
    

    4.解析注释

           /***********************************************
              * Name    :AnalysisDBCCommentsPattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCCommentsPattern(List<Message> messages, string data)
            {
                string pattern = "CM_[ ]+((((BU_)|(BO_)|(SG_))[ ]+(\\d+)[ ]+(\\w+)(([ ]+)|))|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"(([ ]+)|);";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    bool result = false;
                    string[] array1 = match.Value.Split(new string[] {@"""" }, StringSplitOptions.None);
                    string[] array2 = array1[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                    if (array2.Length == 1)
                    {
                        string comments = array1[1];
                    }
                    else
                    {
                        
                        if (array2[1] == "SG_")
                        {
                            uint id = (uint)ConvertToInt(array2[2]);
                            string name = ConvertToName(array2[3]);
                            foreach (var message in messages)
                            {
                                if (id == message.ID)
                                {
                                    foreach (var signal in message.Signals)
                                    {
                                        if (name == signal.Name)
                                        {
                                            result = true;
                                            signal.Comments = array1[1];
                                            break;
                                        }
                                    }
                                }
                            }
                            if (!result)
                            {
                                ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                                return false;
                            }
                        }
                    }
                }
                return true;
            }
    

    5.解析自定义属性描述

           /***********************************************
              * Name    :AnalysisDBCAttributeDefinitionPattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCNatureDefinitionPattern(List<Nature> natures, string data)
            {
                string pattern = "BA_DEF_[ ]+((BU_)|(BO_)|(SG_)|(EV_))?(([ ]+)|)\"(\\w+)\"(([ ]+)|)(((INT)[ ]+([+|-]?\\d+)[ ]+([+|-]?\\d+))|((HEX)[ ]+([+|-]?\\d+)[ ]+([+|-]?\\d+))|((FLOAT)[ ]+([+|-]?\\d+.?\\d*)[ ]+([+|-]?\\d+.?\\d*))|(STRING)|((ENUM)(([ ]+)|)(\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"([ ]*,(([ ]+)|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\")*)))[ ]*(([ ]+)|);";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    string[] array1 = match.Value.Split(new string[] { " ", @"""" }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (Nature nature in natures)
                    {
                        if ((nature.Family == array1[1]) && (nature.Name == array1[2]))
                        {
                            ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                            return false;
                        }
                    }
                    Nature nat = new Nature();
                    nat.Family = array1[1];
                    nat.Name = ConvertToName(array1[2]);
                    int StartNum = 3;
                    if ((nat.Family != "BU_") && (nat.Family != "BO_") && (nat.Family != "SG_") && (nat.Family != "EV_"))
                    {
                        StartNum = 2;
                        nat.Family = null;
                        nat.Name = ConvertToName(array1[1]);
                    }
                    nat.Type = array1[StartNum];
                    if ((nat.Type == "INT") || (nat.Type == "HEX") || (nat.Type == "FLOAT"))
                    {
                        nat.data.Add(array1[StartNum + 1]);
                        nat.data.Add(array1[StartNum + 1]);
                    }
                    else if (nat.Type == "ENUM")
                    {
                        string[] array2 = match.Value.Split(new string[] {"ENUM"}, StringSplitOptions.RemoveEmptyEntries);
                        string[] array3 = array2[1].Replace(" ", "").Split(new string[] { ",", @"""" }, StringSplitOptions.RemoveEmptyEntries);
                        for (int i = 0; i < array3.Length - 1; i++)
                        {
                            nat.data.Add(array3[i]);
                        }
                    }
                    natures.Add(nat);
                }
                return true;
            }
    

    6.解析自定义属性默认值

           /***********************************************
              * Name    :AnalysisDBCNatureDefaultPattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCNatureDefaultPattern(List<Message> messages, List<Nature> natures, string data)
            {
                string pattern = "BA_DEF_DEF_[ ]+\"(\\w+)\"(([ ]+)|)\"?(([+|-]?\\d*.?\\d*)|((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*))\"?(([ ]+)|);";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    bool result = false;
                    string str = match.Value.Replace(@""" ", @"""").Replace(@" """, @"""").Trim(';');
                    string[] array = str.Split(new string[] {@""""}, StringSplitOptions.RemoveEmptyEntries);
                    string name = ConvertToName(array[1]);
                    string init = 2 >= array.Length ? "" : array[2];
                    foreach (Nature nature in natures)
                    {
                        if (nature.Name == name)
                        {
                            foreach (Message message in messages)
                            {
                                switch (name)
                                {
                                    case "GenMsgCycleTime":
                                        message.CycleTime = ConvertToInt(init);
                                        break;
                                    case "GenMsgCycleTimeFast":
                                        message.CycleTimeFast = ConvertToInt(init);
                                        break;
                                    case "GenMsgNrOfRepetition":
                                        message.NrOfRepetition = ConvertToInt(init);
                                        break;
                                    case "GenMsgDelayTime":
                                        message.DelayTime = ConvertToInt(init);
                                        break;
                                    case "NmMessage":
                                        message.Type = init;
                                        break;
                                    case "GenMsgSendType":
                                        message.SendType = init;
                                        break;
                                    default:
                                        break;
                                }
                                foreach (Signal signal in message.Signals)
                                {
                                    switch (name)
                                    {
                                        case "GenSigStartValue":
                                            signal.InitValue = ConvertToInt(init);
                                            break;
                                        case "GenSigTimeoutValue":
                                            signal.InvalidValue = ConvertToInt(init);
                                            break;
                                        case "GenSigInactiveValue":
                                            signal.InactiveValue = ConvertToInt(init);
                                            break;
                                        case "GenSigSendType":
                                            signal.SendType = init;
                                            break;
                                        case "GenSigMinValue":
                                            signal.MinValue = ConvertToInt(init);
                                            break;
                                        case "GenSigMaxValue":
                                            signal.MaxValue = ConvertToInt(init);
                                            break;
                                        default:
                                            break;
                                    }
                                }
                            }
                            nature.InitValue = init;
                            result = true;
                        }
                    }
                    if (!result)
                    {
                        ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                        return false;
                    }
                }
                return true;
            }
    

    7.解析自定义属性值

           /***********************************************
              * Name    :AnalysisDBCNatureValuePattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCNatureValuePattern(List<Message> messages, List<Nature> natures, string data)
            {
                string pattern = "BA_[ ]+\"(\\w+)\"(([ ]+)|)(((BU_)[ ]+(\\w+)[ ]+)|((BO_)[ ]+(\\d+)[ ]+)|((SG_)[ ]+(\\d+)[ ]+(\\w+)[ ]+)|((EV_)[ ]+(\\w+)[ ]+))?\"?(([+|-]?\\d*.?\\d*)|((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*))\"?(([ ]+)|);";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    bool result = false;
                    string str = match.Value.Trim(';');
                    string[] array = str.Split(new string[] { " ", @"""" }, StringSplitOptions.RemoveEmptyEntries);
                    string name = ConvertToName(array[1]);
                    uint id = array.Length <= 3 ? 0 : (uint)ConvertToInt(array[3]);
                    foreach (Nature nature in natures)
                    {
                        if (nature.Name == name)
                        {
                            foreach (Message message in messages)
                            {
                                if (message.ID == id)
                                {
                                    if (array[2] == "BO_")
                                    {
                                        switch (name)
                                        {
                                            case "GenMsgCycleTime":
                                                message.CycleTime = ConvertToInt(array[4]);
                                                break;
                                            case "GenMsgCycleTimeFast":
                                                message.CycleTimeFast = ConvertToInt(array[4]);
                                                break;
                                            case "GenMsgNrOfRepetition":
                                                message.NrOfRepetition = ConvertToInt(array[4]);
                                                break;
                                            case "GenMsgDelayTime":
                                                message.DelayTime = ConvertToInt(array[4]);
                                                break;
                                            case "NmMessage":
                                                message.Type = nature.data[ConvertToInt(array[4])];
                                                break;
                                            case "GenMsgSendType":
                                                message.SendType = nature.data[ConvertToInt(array[4])];
                                                break;
                                            default:
                                                break;
                                        }
                                        result = true;
                                    }
                                    else if (array[2] == "SG_")
                                    {
                                        foreach (Signal signal in message.Signals)
                                        {
                                            if (signal.Name == array[4])
                                            {
                                                switch (name)
                                                {
                                                    case "GenSigStartValue":
                                                        signal.InitValue = ConvertToInt(array[5]);
                                                        break;
                                                    case "GenSigTimeoutValue":
                                                        signal.InvalidValue = ConvertToInt(array[5]);
                                                        break;
                                                    case "GenSigInactiveValue":
                                                        signal.InactiveValue = ConvertToInt(array[5]);
                                                        break;
                                                    case "GenSigSendType":
                                                        signal.SendType = nature.data[ConvertToInt(array[5])];
                                                        break;
                                                    case "GenSigMinValue":
                                                        signal.MinValue = ConvertToInt(array[5]);
                                                        break;
                                                    case "GenSigMaxValue":
                                                        signal.MaxValue = ConvertToInt(array[5]);
                                                        break;
                                                    default:
                                                        break;
                                                }
                                                result = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            result = true;
                        }
                    }
                    if (!result)
                    {
                        ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                        return false;
                    }
                }
                return true;
            }
    

    8.解析数值表

           /***********************************************
              * Name    :AnalysisDBCSignalValueDescriptionPattern
              * Author  :WangHu
              * Function:***
              * Version :V1.0.0
              * Data    :2020.4.15
            ***********************************************/
            internal static bool AnalysisDBCSignalValueDescriptionPattern(List<Message> messages, string data)
            {
                string pattern = "VAL_[ ]+(\\d+)[ ]+(\\w+)[ ]+(((\\d+.?\\d*)(([ ]+)|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"[ ]*)*)+(([ ]+)|);";
                foreach (Match match in Regex.Matches(data, pattern))
                {
                    bool result = false;
                    string str = match.Value.Replace(@""" ", @"""").Replace(@" """, @"""").Trim(';');
                    string[] array1 = str.Split(new string[] { @"""" }, StringSplitOptions.RemoveEmptyEntries);
                    string[] array2 = array1[0].Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                    uint id = (uint)ConvertToInt(array2[1]);
                    string name = ConvertToName(array2[2]);
                    foreach (var message in messages)
                    {
                        if (message.ID == id)
                        {
                            foreach (var signal in message.Signals)
                            {
                                if (signal.Name == name)
                                {
                                    result = true;
                                    signal.ValueDescrptions = "";
                                    for (int i = 0; i < (array1.Length)/2; i++)
                                    {
                                        if (signal.ValueDescrptions == "")
                                        {
                                            signal.ValueDescrptions += "0x" + ConvertToInt(array2[3]).ToString("X") + ":" + array1[1];
                                        }
                                        else
                                        {
                                            signal.ValueDescrptions += " \r\n0x" + ConvertToInt(array1[2 * i]).ToString("X") + ":" + array1[2 * i + 1];
                                        }
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    if (!result)
                    {
                        ShowMsg(@"Find line """ + match.Value + @""" message fault", ShowEnum.Fault);
                        return false;
                    }
                }
                return true;
            }
    

    五、MatrixCreat工具

    这儿我只把链接放上,具体使用说明见后续章节。
    DBC转Excel;DBC转位定义;Excel转DBC;Excel转位定义:https://download.csdn.net/download/weixin_44926112/12671320

    六、其他

    本文主要是讲解DBC文件的结构和如何解析DBC文件,有些地方可能会有描述性的错误,希望看到的朋友及时指出,我会及时更正错误,其他地方有些借鉴的描述,写此文章的目的是为了交流,非商业用途,欢迎私信讨论,感谢大家阅读。

    七、参考

    【1】:https://blog.csdn.net/weixin_44536482/article/details/89030152
    【2】:https://blog.csdn.net/Jiang_Mr/article/details/103417163

    展开全文
  • 详情:可以通过客户给Excel矩阵表通过配置生成DBC文件和位定义文件,也可以通过客户给的DBC文件生成Excel矩阵表和位定义文件, 附件里有demo模板,可自己创建配置ini文件,具体使用说明见博客会讲解:...
  • 报文发送快速周期8.报文快速发送次数9.报文延时时间10.报文长度11.信号名称12.信号描述13.排列格式14.起始字节15.起始位16.信号发送类型17.信号长度18.数据类型19.精度20.偏移量21.物理最小值22.物理最大值23....

    一、摘要

    1.描述

    本文主要描述的是汽车行业中CAN矩阵的内容,主要描述我们当拿到一份矩阵表的时候如何去看懂内容。

    2.关键字

    CAN,CAN矩阵,矩阵详解,通信协议,汽车总线。

    二、什么是CAN

    CAN 是Controller Area Network 的缩写(以下称为CAN),是ISO国际标准化的串行通信协议。在汽车产业中,出于对安全性、舒适性、方便性、低功耗、低成本的要求,各种各样的电子控制系统被开发了出来。

    CAN总线是德国BOSCH公司从80年代初为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种串行数据通信协议,它是一种多主总线,通信介质可以是双绞线、同轴电缆或光导纤维。通信速率最高可达1Mbps,我们这儿主要讲的是低速CAN,非CANFD。

    1.报文格式

    在总线中传送的报文,每帧由7部分组成。CAN协议支持两种报文格式,其唯一的不同是标识符(ID)长度不同,标准格式为11位,扩展格式为29位。

    在标准格式中,报文的起始位称为帧起始(SOF),然后是由11位标识符和远程发送请求位 (RTR)组成的仲裁场。RTR位标明是数据帧还是请求帧,在请求帧中没有数据字节。

    控制场包括标识符扩展位(IDE),指出是标准格式还是扩展格式。它还包括一个保留位 (ro),为将来扩展使用。它的最后四个位用来指明数据场中数据的长度(DLC)。数据场范围为0~8个字节,其后有一个检测数据错误的循环冗余检查(CRC)。

    应答场(ACK)包括应答位和应答分隔符。发送站发送的这两位均为隐性电平(逻辑1),这时正确接收报文的接收站发送主控电平(逻辑0)覆盖它。用这种方法,发送站可以保证网络中至少有一个站能正确接收到报文。

    报文的尾部由帧结束标出。在相邻的两条报文间有一很短的间隔位,如果这时没有站进行总线存取,总线将处于空闲状态。

    2.数据帧格式

    远程帧:
    远程帧由6个场组成:帧起始、仲裁场、控制场、CRC场、应答场和帧结束。远程帧不存在数据场。
    远程帧的RTR位必须是隐位。
    DLC的数据值是独立的,它可以是0~8中的任何数值,为对应数据帧的数据长度。

    错误帧:
    错误帧由两个不同场组成,第一个场由来自各站的错误标志叠加得到,第二个场是错误界定符
    错误标志具有两种形式:
    活动错误标志(Active error flag),由6个连续的显位组成
    认可错误标志(Passive error flag),由6个连续的隐位组成
    错误界定符包括8个隐位

    超载帧:
    超载帧包括两个位场:超载标志和超载界定符
    发送超载帧的超载条件:
    要求延迟下一个数据帧或远程帧
    在间歇场检测到显位
    超载标志由6个显位组成
    超载界定符由8个隐位组成

    3.数据错误检测

    循环冗余检查(CRC):
    在一帧报文中加入冗余检查位可保证报文正确。接收站通过CRC可判断报文是否有错。

    帧检查:
    这种方法通过位场检查帧的格式和大小来确定报文的正确性,用于检查格式上的错误。

    应答错误:
    如前所述,被接收到的帧由接收站通过明确的应答来确认。如果发送站未收到应答,那么表明接收站发现帧中有错误,也就是说,ACK场已损坏或网络中的报文无站接收。CAN协议也可通过位检查的方法探测错误。

    总线检测:
    有时,CAN中的一个节点可监测自己发出的信号。因此,发送报文的站可以观测总线电平并探测发送位和接收位的差异。

    位填充:
    一帧报文中的每一位都由不归零码表示,可保证位编码的最大效率。然而,如果在一帧报文中有太多相同电平的位,就有可能失去同步。为保证同步,同步沿用位填充产生。在五个连续相等位后,发送站自动插入一个与之互补的补码位;接收时,这个填充位被自动丢掉。例如,五个连续的低电平位后,CAN自动插入一个高电平位。CAN通过这种编码规则检查错误,如果在一帧报文中有6个相同位,CAN就知道发生了错误。

    三、CAN矩阵

    在汽车行业开发的过程中,凡是挂在CAN总线上的产品,客户都会给一份CAN矩阵表,如何去读懂CAN矩阵表显得尤为重要,前面我们讲了CAN的基本概念,相信大家对CAN有一个初步的了解,下面我以某个车厂的CAN矩阵表为例来说明。

    1.矩阵表

    在这里插入图片描述

    2.报文名称

    Msg_Name主要是通过名称就能区分我们平时描述的是哪条报文,这个名称一般是唯一的,就像人的名称一样,一般客户也不是随便定义该名称,当然这个名称也可以随意定,一般定义的格式就是该报文发送的节点加上报文的标识符。
    例如.BCM_ALS_0x2F3 代表BCM_ALS为节点BCM转发ALS发送的报文,报文标识符为0x2F3。

    3.报文类型

    Msg_Type主要描述的是报文类型,在汽车行业中,报文主要类型有应用报文,网络管理报文,诊断报文。
    应用报文 Normal: Normal Communication message;
    网络管理报文 NM:Network Mangment message;
    诊断报文 Diag: Diagnostic message。

    4.报文标识符

    Msg_ID是Message identifier的缩写,在矩阵表中,一般同一个报文标识符的内容放在一起,方便他人阅读,这个标识符是我们CAN总线上的唯一标识符,不可与其他信号重复,在矩阵表中,一般加上0x开头,代表16进制显示,在前面已经提到过在标准帧CAN的标识符大小为11位,所以一般大小为0x00 - 0x7FF;扩展帧我们这儿不做描述,因为一般车厂使用的都是标准帧,很少采用扩展帧。

    5.报文发送类型

    Msg_Send_Type表示的是报文发送的类型,在汽车行业中,报文发送的类型一般主要有事件型,周期型,周期事件型,使能型,周期使能型等,其他的类型我在这儿不做描述。

    • 事件型(Event)
      事件报文的发送取决于事件是否触发,事件发生改变时,按照矩阵发送事件报文,非触发事件发生改变时不允许触发发送事件报文,事件型报文一般车厂都会要求一个事件触发的时候发送多次,为了避免报文丢失,每帧之间也会限定一个帧与帧之间的最小间隔。下图为最小间隔20ms,当在事件报文发送 20ms 之后有新的事件发生,则发送新的事件报文,丢弃上一个事件报文;当在事件报文发送 20ms 之内有新事件发生,则新事件报文延迟到 20ms 之后发送。
      在这里插入图片描述
    • 周期型(Cycle)
      报文以一定的间隔时间循环发送,报文的发送周期在矩阵表都会有体现,开发的时候必须按照客户规定的周期进行开发,一般时间两帧之间的误差不能超过规定时间的百分之十。
      在这里插入图片描述
    • 周期事件型(CE)
      CE意思是 Cycle and Event,当事件未发生时,报文以周期时间 T循环发送,事件发生时,报文以快周期发送规定次数,周期事件型报文是一条比较特殊的报文,一般对实时性要求比较高,但是为了减少总线的负载,采用此方式。假设某车厂要求快周期为20ms,事件报文与周期报文发送的时间间隔不应小于 20ms。如果事件发生在周期报文发送之后 20ms 内,则事件报文延迟到周期报文发送 20ms 后再发送。如果事件报文发生在周期报文发送之前 20ms 内,则周期报文延迟到事件报文发送 20ms 后再发送;如果事件报文和周期报文发生冲突时,周期报文应延时到事件报文发送完成后 20ms 再发送。
      在这里插入图片描述
    • 使能型(IfActive)
      和事件型发送类型一样,使能发送类型由报文中的一个或多个信号触发,引起报文传输。当触发信号的“当前信号值≠非使能值时”,约束条件满足,触发条件发生,使能报文立刻以周期时间 T 循环发送。当信号值由使能值变为非使能值时并且再无其它使能信号,相应报文发送 规定次数。
      在这里插入图片描述
    • 周期使能型(CA)
      CA意思是Cycle if Active,当触发信号的“当前信号值=非使能值时”,报文以周期时间 T 循环发送,当触发信号的“当前信号值≠非使能值时”,约束条件发生,触发条件满足时,使能报文以周期发送直到“当前信号值=非使能值时”。
      在这里插入图片描述

    6.报文周期时间

    Msg_Cycle_Time主要是针对周期型报,周期事件型报文和周期使能型,要注意这个周期世间的单位,一般默认为ms。

    7.报文发送的快速周期

    Msg_Cycle_Time_Fast指当报文发送类型不为周期型时,报文发送的快速周期。

    8.报文快速发送的次数

    Msg_Nr_Of_Reption指当报文发送类型不为周期型时,报文快速发送的次数。

    9.报文延时时间

    Msg_Delay_Time指当报文发送类型不为周期型时,相同ID报文之间的最小间隔。

    10.报文长度

    Msg_Length是指报文的长度,有的时候客户用lenth表示,有的时候用dlc表示,对于标准帧的传输,这个值最大为8,也就是一帧传输的有效字节数最多为8个有效数据位。

    11.信号名称

    Signal_Name是指定义在数据位信号名称,这个标识符和报文标识符是差不多的,也是唯一的,一般信号名称都是英文的,这个是为了通过这个标识符来生成信号,可用于位定义,DBC文件名称。

    12.信号描述

    Signal_Description指该信号的用途,代表的意思,一般是对该信号的描述。

    13.排列格式

    Byte_Order在汽车行业中有三种格式,分别是Intel,Motorola LSB,Motorola MSB。而有的时候车厂指写了Motorola,这个一般是指Motorola LSB。

    • 数据类型定义
      在汽车行业中,CAN传输的8个字节按照位定义了信号名称,定义名称如下图所示:
      在这里插入图片描述
    • Intel格式
      当一个信号的数据长度不超过1 Byte,并且信号在一个字节内实现时,该信号的高位将被放在该字节的高位,信号的低位将被放在该字节的低位,当一个信号的数据长度超过1 Byte或者数据长度不超过1 Byte,但是采用跨字节的方式实现时,该信号的高位将被放在高字节的高位,信号的低位将被放在低字节的低位,这样信号的起始位就是低字节的低位。
    • Motorola LSB格式
      当一个信号的数据长度不超过1 Byte并且信号在一个字节内实现时,信号的高位将被放在该字节的高位,信号的低位将被放在该字节的低位,这样,信号的起始位就是该字节的低位,当一个信号的数据长度超过1 Byte或者数据长度不超过一个字节但是采用跨字节方式实现时,该信号的高位将被放在低字节的高位,信号的低位将被放在高字节的低位,这样信号的起始位就是高字节的低位。
      在这里插入图片描述
    • Motorola MSB格式
      当一个信号的数据长度不超过1 Byte并且信号在一个字节内实现时,信号的高位将被放在该字节的高位,信号的低位将被放在该字节的低位,这样,信号的起始位就是该字节的高位,当一个信号的数据长度超过1 Byte或者数据长度不超过一个字节但是采用跨字节方式实现时,该信号的高位将被放在低字节的高位,信号的低位将被放在高字节的低位,这样信号的起始位就是低字节的高位。
      在这里插入图片描述

    14.起始字节

    Start_Byte就是指起始位所在的字节,在标准帧中这个值只能是0-7,不会出现大于7的情况。

    15.起始位

    Start_Bit对于不同排列格式的起始位是不相同的,这点一定要注意,得出的数据内容可能完全是两个东西,在标准帧中这个值只能是0-63,不会出现大于63的情况。

    16.信号发送类型

    Signal_Send_Type的类型主要有以下几种:Cycle,OnWrite ,OnWriteWithRepetition,OnChange ,OnChangeWithRepetition,IfActive,IfActiveWithRepetition等。

    17.信号长度

    Bit_Length代表信号的长度,不同排列格式虽然起始位不同,但是信号长度却是一样的,它代表该信号占了多个数据位,在标准帧中这个值只能是1-64,不会出现大于64的情况。

    18.数据类型

    Date_Type主要有两种,无符号和有符号,即Unsigned和Signed,其他还有IEEE float, IEEE Double等。

    19.精度

    Factor十六进制值的比例因子是为了计算信号的物理值。公式如下:

    [Physical value] = ( [Hex value] * [Factor] ) + [Offset]
    

    [物理值] = ( [十六进制值] * [精度] ) + [偏移量]

    20.偏移量

    Offset偏移量用来计算信号的物理值。

    21.物理最小值

    Signal_Min_Value_Phy指总线实际换算出来的最小值。

    22.物理最大值

    Signal_Max_Value_Phy指总线实际换算出来的最大值。

    23.总线最小值

    Signal_Min_Value指总线上的最小值。

    24.总线最大值

    Signal_Max_Value指总线上的最大值。

    25.初始值

    Initial_Value指如果在网络启动后没有可用的有效信号,预定义的值将被发送(取决于功能需求)。有效值必须在启动后此时间内可用。

    26.无效值

    Invalid_Value一般用于节点丢失时的替代值。

    27.非使能值

    Inactive_Value仅用于使能型及周期使能型报文。

    28.单位

    Unit指信号的换算单位,比如“%”“℃”等。

    29.信号值描述

    Signal_Value_Description指信号的代表的意思,比如:0x00:Close;0x01:Open代表当总线上信号的指为0x00的时候代表关闭,0x01代表打开。

    30.备注

    Comments即其他的描述。

    31.发送节点

    Transmitter代表该报文信号是哪个ECU发送的,指发送节点。

    32.接收节点

    Receivers代表该报文信号是哪些ECU接收的,指接收节点。

    四、CAN解析方式

    当我们拿到客户给过来的CAN矩阵后,我们如何才能快速的解析报文,如何才能快速的使用,其实方法有许多,其中很多人会选择去移位,比如 demo是起始字节是2,起始位是22,占用两个字节,在C语言中,我们可以解析如下:

    char demo = (message.byte[0]>>5)&0xFF;
    

    这样虽然能得到demo 信号的指,但是如果现在有无数个信号,解析的效率会非常的低,而且还容易出错,我们可以使用单片机的特性,使用共用体来解析,当然这需要注意一点,不同单片机有大端和小端的问题。

    • 大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。

    • 小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。

    在清楚单片机的大端和小端的情况,我们可以这样去定义一个共用体,假设该报文长度为4;我们可以定义如下共用体,后面称为位定义:

    typedef union
    {
        uint8_t data[4];
        struct
        {
            //Byte[0]
            bits_t reserved0_7                        :8;
            //Byte[1]
            bits_t reserved8_15                       :8;
            //Byte[2]
            bits_t reserved16_21                      :6;
            bits_t demo 							  :2;
            //Byte[3]
            bits_t reserved24_31                      :8;
        }bits;
    }Msg_TYPE;//单片机为小端
    
    typedef union
    {
        uint8_t data[4];
        struct
        {
            //Byte[0]
            bits_t reserved0_7                        :8;
            //Byte[1]
            bits_t reserved8_15                       :8;
            //Byte[2]
            bits_t demo 							  :2;
            bits_t reserved16_21                      :6;
            //Byte[3]
            bits_t reserved24_31                      :8;
        }bits;
    }Msg_TYPE;//单片机为大端
    

    当报文接收到的时候,我们可以直接强制转换。

    Msg_TYPE* p_msg = (Msg_TYPE*)message.byte;
    demo = p_msg -> demo; 
    

    这样就可以快速解析所有报文,但是如果手动去生成位定义的话也会显得十分麻烦,而且也容易出错,因此我写了一个上位机,可以直接解析Excel的数据内容,自动生成位定义,这样就可以大大的减轻工程师的负担。对于工具的使用后面有详细的讲解吗,在这儿我就不再重复讲解。

    五、MatrixCreat工具

    这儿我只把链接放上,具体使用说明见后续章节。
    DBC转Excel;DBC转位定义;Excel转DBC;Excel转位定义:https://download.csdn.net/download/weixin_44926112/12671320

    六、其他

    本文主要是讲解对CAN矩阵的理解,有些地方可能会有描述性的错误,希望看到的朋友及时指出,我会及时更正错误,其他地方有些借鉴的描述,写此文章的目的是为了交流,非商业用途,欢迎私信讨论,感谢大家阅读。

    七、参考

    【1】:https://baike.baidu.com/item/CAN%E6%80%BB%E7%BA%BF/297754?fr=aladdin
    【2】:https://www.jianshu.com/p/adeed02a552f
    【3】:https://blog.csdn.net/jingling122/article/details/78599636

    展开全文
  • DBC的故事

    万次阅读 多人点赞 2018-05-02 09:43:37
    1.DBC定义 DBC(data base CAN)是汽车ECU间进行CAN通讯报文内容,有了它相互之间才能听懂。 2.DBC查看 DBC是文本文件,可以用记事本...DBC是由一系列Message和Signal组成,文件定义了Message和Signal属...

    欢迎关注《汽车软件技术》公众号,回复关键字获取资料。

    1.DBC定义

    DBC(data base CAN)是汽车ECU间进行CAN通讯的报文内容,有了它相互之间才能听懂。

    2.DBC查看

    DBC是文本文件,可以用记事本打开,一般都用CANdb++,可以更方便的查看和编辑。

    3.DBC组成

    DBC是由一系列的Message和Signal组成,文件定义了Message和Signal的属性,可参考vector文档(回复“DBC文档”获取)。下面介绍几个重要的关键字:

    1)BO_

    BO_是对Message的定义。

    • 格式:BO_ ID Name: DLC Transmiter
    • 例子:BO_ 100 ESP_01: 8 ESP
    • 释义:发送方=ESP,帧名称=ESP_01,帧ID=0x64,报文长度=8个字节

    2)SG_

    SG_是对Signal的定义。

    • 格式:SG_ Name : StartBit | Length @ ByteOrder SignedFlag (Factor,Offset) [Minimum | Maximum] "Unit" Receiver1,Receiver2
    • 例子:SG_ VehSpd : 7|16@0+ (0.01,0) [0|655.35] "km/h" ECM.TCM
    • 释义:信号名称=VehSpd,起始地址=7,长度=16,字节顺序=MSB(大端),符号位=无符号,系数=0.01,偏移=0,最小值=0,最大值=655.35,单位=km/h,接收方=ECM和TCM

    3)VAL_

    VAL_是对Signal枚举值的定义。

    • 格式:VAL_ ID Name key1 "value1" key2 "value2" ;
    • 例子:VAL_ 100 VehSpdValid 1 "Valid" 0 "Invalid" ;
    • 释义:帧ID=0x64,信号名称=VehSpdValid,枚举值(0x0=Invalid,0x1=Valid)

    4.DBC解析

    上文已经介绍了DBC的格式,接下来介绍如何使用DBC从原始报文中解析出物理值。在此之前要先理解MSB(大端)和LSB(小端)。MSB是高位在前,LSB是低位在前,大多数都用的MSB。

    1)原始值

    假设有3个信号:signal1、signal2和signal3,长度分别是16、4、12。这3个信号包括了3种类型:完整字节,部分字节和跨字节。用Layout来比较。下面使用了位操作指令:&是按位与,<<是左移,>>是右移。

    • MSB

     

     

     

     

     

    MSB高位在前。

    signal1:起始地址=7,值=Byte0<<8+Byte1。(Byte0是高位,Byte1是低位)

    signal2:起始地址=23,值=(Byte2&0xf0)>>4。(取Byte2的高4位)

    signal3:起始地址=19,值=(Byte2&0x0f)<<8+Byte3。(取Byte2的低4位,作为高位)

     

     

     

    • LSB

     

     

     

     

     

    LSB是低位在前。

    signal1:起始地址=0,值=Byte0+Byte1<<8。(Byte0是低位,Byte1是高位)

    signal2:起始地址=16,值=Byte2&0x0f。

    signal3:起始地址=20,值=(Byte2&0xf0)>>4+Byte3<<4。(Byte2是低位,Byte3是高位)

    2)物理值

    物理值=原始值*Factor+Offset

    3)代码实现

    以.NET(C#)为例,绘制layout,计算出数值。

    (回复“DBC例子”获取源代码)

    • MSB

     

     

     

     

     

     

     

    • LSB

     

     

     

     

     

     

     

     

    5.DBC开源资料

    (回复“DBC开源”随机获取)

    展开全文
  • dB dBc dBi dBd dBm dBW 定义(db 和dbm关系:dbm - dbm = db<重要>) 在无线通信行业,经常会涉及到dB,dBc,dBi, dBd, dBm,dBw问题,其定义如下:1、dBdB是一个表征相对值值,纯粹比值,只表示两个量...
  • 有时为了节约空间会定义多路复用信号,当有多个较长信号时,而这些信号又无需一直发送,通过定义多路复用信号进行交替发送。定义方式为通过一个短信号(与复用多少路有关,如两路复用,只需一位即可,依此2位可...
  • 1.示例读取dbc文件并根据dbc定义的消息/信号生成Rust结构。 使用can_dbc :: DBC; 使用codegen :: Scope; 使用std :: fs :: File; 使用std :: io; 使用std :: io :: prelude :: *; fn main()-> io :: Result {let...
  • 关于Oracle R2DBC Oracle R2DBC驱动程序是一个Java库,支持使用Oracle数据库进行React式编程。 Oracle R2DBC实现了Reactive Relational Database Connectivity(R2DBC...了解有关R2DBC的更多信息: 了解有关React式
  • DBC是Database CAN缩写,意思是CAN数据库文件。在这个文件中完整详细定义了CAN通讯信息。 2DBC文件有什么作用 相比于各个厂商提供Excel版本协议描述文件,该文件通用且格式标准,便于交流。而且很多通用...
  • DBC文件解析

    2021-01-07 14:28:15
    这里写自定义目录标题1、基础介绍2、DBC文件2.1、...2.2、波特率定义2.3、网络节点的定义2.4、报文帧的定义2.5、信号的定义2.6、注解部分2.7、特征(属性)定义部分:2.8、数值表部分 protuesjzy写过两篇dbc文件的介绍 ...
  • DBC解析

    2021-01-25 16:50:16
    DBC文件也可以用来开发电子控制单元通信软件,该控制单元应该是CAN网络一部分。 DBC文件不处理ECU功能行为。 2一般定义 本文档中使用以下常规元素: unsigned_integer:一个无符号整数 signed_...
  • DBC 文件格式

    2018-03-17 18:44:46
    Vector公司的dbc文件格式说明文档,详细说明了dbc文件中各标识符的定义
  • DBC文件

    千次阅读 2019-07-20 10:18:27
    DBC文件: 波特率定义 格式如下: BS_:[baudrate:BTR1,BTR2]; ... 其中BS_为关键字,用于定义CAN网络的波特率;[ ]内容表示为可选部分,可以省略(如下图例子中即把该部分省略...网络节点的定义 格式如下: ...
  • 关于DBC文件格式解析(转)

    千次阅读 2019-08-31 17:31:54
    3、网络节点的定义 4、报文帧的定义 5、信号的定义 6、注解部分 7、属性定义部分 8、数值表部分 其中第2点、第3点是必须项,缺少这两项的dbc文件是不能用CANdb++ Editor软件打开的;接下来我们结合例子对dbc文件的这...
  • DBC文件学习

    2020-04-22 14:00:50
    文章目录DBCDBC文件的创建对文件的解析版本与新符号波特率网络节点的定义报文帧的定义信号的定义注释部分属性定义部分数值表部分 DBC dbc数据库文件是一种用来描述CAN总线协议中协议数据及其代表的具体意义 可以...
  • DBC专题】-5-DBC文件格式解析

    千次阅读 热门讨论 2020-12-23 20:44:38
    1 DBC文件标头 1 Bit Timing波特率定义 2 Node节点定义 3 Value Table值表定义 4 Message消息定义 4.1 标准帧Message定义举例 4.2 扩展帧Message定义举例 5 Signal信号定义 6 Value Table指标绑定Signal...
  • CAN网络dbc格式

    2021-04-28 09:41:57
    是vector公司定义的私有文件格式。因vector公司在汽车领域,用者甚众,dbc成为描述can matrix,can报文格式一种重要形式。格式标准说明,见本人上传附件。 CAN协议领域,有很多CAN协议,通用有J1939,还有很多...
  • db dbm dbi dbc 含义

    2020-12-07 17:27:57
    首先, DB 是一个纯计数单位:对于功率,dB = 10lg(A/B)。对于电压或电流,dB = 20lg(A/B).dB意义其实再简单不过了,就是把一个很大...dBm 定义的是 miliwatt。0 dBm=10lg1mw; dBw 定义 watt。0 dBw = 10lg1 W = 1
  • 首先要定义存放DBC数据结构体:首先是 信号类和报文类 定义。 此定义需遵循变量从属关系(一个DBC文件内有多个BO_,一个BO_下有多个SG_) 可以参考此文章,https://www.vecll.com/news/10.html,作者提供思路比较...
  • 既然是CAN仿真工具,第一篇就讲一下CAN DBC的格式,如何通过dbc文件定位到需要的信号 。下面用到的所有定义都已经做过处理,都是假的,不涉及任何商业使用的数据。 以下内容不针对没有CAN基础的同学,如果有基础...
  • DBC的故事(二)

    2018-05-13 15:18:00
    上篇介绍了MSB和LSB,此篇介绍更复杂:有符号和无符号数。 1.信号符号 CAN信号有其物理意义,如温度、扭矩等,...上篇文章中提到signal定义中有SignedFlag,当SignedFlag是负号时,表示此信号是由符号。 ...
  • DBC文件源码解析

    千次阅读 2020-03-16 19:04:39
    DBC文件源码解析   DBC(data base CAN)文件是由德国...DBC是一种文件格式,.dbc文件是一个ASCII格式文件,其.dbc扩展名可用于定义CAN网络。DBC由一系列Message和Signal组成,文件定义了Message和Signal属...
  • 如果使用Spring Boot,只需定义一个SqlQueries类型bean。 示例 。 产品特点 基于约定文件名,例如V3__insert_to_customers__split,nontransactional.sql 它一直等到数据库已经启动,有测试查询和验证结果为止...
  • DBC文件信号多路复用详解 1何时定义 有些信号比较长,但是又不常用,就可以定义多路复用信号以节约空间。 2具体定义 2.1定义一个短信号来当做“控制开关”。 【若定义1bit,则有2种可能0x00和0x01,复用两路】 【若...

空空如也

空空如也

1 2 3 4 5 ... 10
收藏数 188
精华内容 75
关键字:

dbc的定义