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.解析版本
/**********************************************/
///<summary>
///Name :AnalysisVersion
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisVersion(MsgInfo_Type msgInfo, 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) { msgInfo.version = array[1]; }
return true;
}
}
return true;
}
2.解析报文消息
/**********************************************/
///<summary>
///Name :AnalysisMessagePattern
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisMessagePattern(List<Message_Type> messages, string data)
{
string messagePattern = "BO_[ ]+(\\d+)[ ]+(\\w+):(([ ]+)|)(\\d+)[ ]+(\\w+)[ ]*(SG_[ ]+(\\w+)(([ ]+)|)(((m)(\\d+[ ]+))|(M[ ]+))?:(([ ]+)|)(\\d+)(([ ]+)|)\\|(([ ]+)|)(\\d+)(([ ]+)|)@(([ ]+)|)([0|1])(([ ]+)|)([+|-])(([ ]+)|)+\\((([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|),(([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|)\\)(([ ]+)|)\\[(([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|)\\|(([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|)\\](([ ]+)|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"(([ ]+)|)(\\w+(,[ ]*\\w+)*)[ ]*)*";
foreach (Match messageMatch in Regex.Matches(data, messagePattern))
{
string msgPattern = "BO_[ ]+(\\d+)[ ]+(\\w+):(([ ]+)|)(\\d+)[ ]+(\\w+)";
Match msgMatch = Regex.Matches(messageMatch.Value, msgPattern)[0];
string[] array = msgMatch.Value.Split(new string[] { " ", ":" }, StringSplitOptions.RemoveEmptyEntries);
uint? id = CommonLib.ToDec(array[1]) & 0x7FFFFFFF;
if (id == null) { continue; }
Message_Type message = FindMessage(messages, (uint)id);
if (message == null)
{
message = new Message_Type();
messages.Add(message);
}
message.id = CommonLib.ToDec(array[1]) & 0x7FFFFFFF;
message.name = CommonLib.ToVar(array[2]);
message.length = CommonLib.ToInt(array[3]);
message.transmitter = CommonLib.ToStr(array[4]) == "Vector__XXX" ? null : CommonLib.ToStr(array[4]);
message.cycleTime = message.cycleTimeFast = message.nrOfRepetition = message.delayTime = null;
string signalPattern = "SG_[ ]+(\\w+)(([ ]+)|)(((m)(\\d+[ ]+))|(M[ ]+))?:(([ ]+)|)(\\d+)(([ ]+)|)\\|(([ ]+)|)(\\d+)(([ ]+)|)@(([ ]+)|)([0|1])(([ ]+)|)([+|-])(([ ]+)|)+\\((([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|),(([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|)\\)(([ ]+)|)\\[(([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|)\\|(([ ]+)|)((\\d|\\.|E|\\-|\\+)+)(([ ]+)|)\\](([ ]+)|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"(([ ]+)|)(\\w+(,[ ]*\\w+)*)";
foreach (Match signalMatch in Regex.Matches(messageMatch.Value, signalPattern))
{
try
{
string str = signalMatch.Value.Replace("- ", " - ").Replace("+ ", " + ").Replace("-(", " -(").Replace("+(", " +(");
string[] array1 = str.Split(new string[] { @"""" }, StringSplitOptions.None);
string[] array2 = array1[0].Split(new string[] { " ", ":", ",", "|", "@", "(", ")", "[", "]" }, StringSplitOptions.RemoveEmptyEntries);
int startbit = (int)CommonLib.ToInt(array2[2]);
int bitlenth = (int)CommonLib.ToInt(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;
List<string> receivers = new List<string>();
string[] array3 = array1[2].Split(new string[] { " ", "," }, StringSplitOptions.RemoveEmptyEntries);
foreach (string receiver in array3) { if (!receiver.Equals("Vector__XXX")) { receivers.Add(receiver); } }
message.signals.Add(new Signal_Type
{
name = CommonLib.ToVar(array2[1]),
startBit = array2[4].Contains("0") ? siglsb : CommonLib.ToInt(array2[2]),
length = CommonLib.ToInt(array2[3]),
byteOrder = (ByteOrderEnum)CommonLib.ToInt(array2[4]),
dataType = array2[5].Contains("-") ? DataTypeEnum.SIGNED : DataTypeEnum.UNSIGNED,
factor = (double)CommonLib.ToDouble(array2[6]),
offset = (double)CommonLib.ToDouble(array2[7]),
minValuePhy = CommonLib.ToDouble(array2[8]),
maxValuePhy = CommonLib.ToDouble(array2[9]),
unit = CommonLib.ToStr(array1[1]),
receivers = receivers
});
}
catch { continue; }
}
}
return true;
}
3.解析节点信息
/**********************************************/
///<summary>
///Name :AnalysisNodes
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisNodes(MsgInfo_Type msgInfo)
{
if (msgInfo.messages.Count == 0) { return false; }
foreach (Message_Type message in msgInfo.messages)
{
if ((message.transmitter != null) && (!msgInfo.nodes.Contains(message.transmitter))) { msgInfo.nodes.Add(message.transmitter); }
foreach (Signal_Type signal in message.signals)
{
if (signal.sendType == null) { signal.sendType = message.sendType; }
foreach (string receiver in signal.receivers)
{
if (msgInfo.nodes.Contains(receiver)) { continue; }
msgInfo.nodes.Add(receiver);
}
}
}
msgInfo.busType = BusTypeEnum.CAN;
return true;
}
4.解析注释
/**********************************************/
///<summary>
///Name :AnalysisCommentsPattern
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisCommentsPattern(List<Message_Type> messages, string data)
{
string pattern = "CM_[ ]+((((BU_)|(BO_)|(SG_))[ ]+(\\d+)[ ]+(\\w*)(([ ]+)|))|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"(([ ]+)|);";
foreach (Match match in Regex.Matches(data, pattern))
{
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] == "BO_")
{
uint? id = CommonLib.ToDec(array2[2]) & 0x7FFFFFFF;
if (id == null) { continue; }
Message_Type message = FindMessage(messages, (uint)id);
if (message == null) { continue; }
message.comments = array1[1];
}
else if (array2[1] == "SG_")
{
uint? id = CommonLib.ToDec(array2[2]) & 0x7FFFFFFF;
if (id == null) { continue; }
Message_Type message = FindMessage(messages, (uint)id);
if (message == null) { continue; }
string name = CommonLib.ToVar(array2[3]);
foreach (Signal_Type signal in message.signals)
{
if (name == signal.name)
{
signal.descrption = array1[1];
break;
}
}
}
}
}
return true;
}
5.解析自定义属性描述
/**********************************************/
///<summary>
///Name :AnalysisNatureDefinitionPattern
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisNatureDefinitionPattern(List<Nature_Type> natures, string data)
{
string pattern = "BA_DEF_[ ]+((BU_)|(BO_)|(SG_)|(EV_))?(([ ]+)|)\"(\\w+)\"(([ ]+)|)(((INT)[ ]+([+|-]?\\d+)[ ]+([+|-]?\\d+))|((HEX)[ ]+([+|-]?\\d+)[ ]+([+|-]?\\d+))|((FLOAT)[ ]+((\\d|\\.|E|\\-|\\+)+)[ ]+((\\d|\\.|E|\\-|\\+)+))|(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);
Nature_Type nat = new Nature_Type();
foreach (Nature_Type nature in natures) { if ((nature.family == array1[1]) && (nature.name == array1[2])) { nat = nature; } }
nat.family = array1[1];
nat.name = CommonLib.ToVar(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 = CommonLib.ToVar(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 = CommonLib.ToStr(array2[1]).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.解析自定义属性默认值
/**********************************************/
///<summary>
///Name :AnalysisNatureDefaultPattern
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisNatureDefaultPattern(MsgInfo_Type msgInfo, string data)
{
string pattern = "BA_DEF_DEF_[ ]+\"(\\w+)\"(([ ]+)|)\"?(([+|-]?\\d*.?\\d*)|((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*))\"?(([ ]+)|);";
foreach (Match match in Regex.Matches(data, pattern))
{
string str = match.Value.Replace(@""" ", @"""").Replace(@" """, @"""").Trim(';');
string[] array = str.Split(new string[] { @"""" }, StringSplitOptions.RemoveEmptyEntries);
string name = CommonLib.ToVar(array[1]);
string value = 2 >= array.Length ? "" : array[2];
foreach (Nature_Type nature in msgInfo.natures)
{
if (nature.name == name)
{
if (name.Equals("BusType"))
{
msgInfo.busType = value.Equals("CAN") ? BusTypeEnum.CAN : BusTypeEnum.CANFD;
continue;
}
foreach (Message_Type message in msgInfo.messages)
{
switch (name)
{
case "GenMsgCycleTime":
message.cycleTime = CommonLib.ToInt(value);
break;
case "GenMsgCycleTimeFast":
message.cycleTimeFast = CommonLib.ToInt(value);
break;
case "GenMsgNrOfRepetition":
message.nrOfRepetition = CommonLib.ToInt(value);
break;
case "GenMsgDelayTime":
message.delayTime = CommonLib.ToInt(value);
break;
case "NmMessage":
message.type = value.ToLower().Contains("yes") ? TypeEnum.NM : TypeEnum.NORMAL;
break;
case "GenMsgSendType":
message.sendType = value;
break;
default:
break;
}
foreach (Signal_Type signal in message.signals)
{
switch (name)
{
case "GenSigStartValue":
signal.initValue = CommonLib.ToInt(value);
break;
case "GenSigTimeoutValue":
signal.invalidValue = CommonLib.ToInt(value);
break;
case "GenSigInactiveValue":
signal.inactiveValue = CommonLib.ToInt(value);
break;
case "GenSigSendType":
signal.sendType = value;
break;
case "GenSigMinValue":
signal.minValue = CommonLib.ToInt(value);
break;
case "GenSigMaxValue":
signal.maxValue = CommonLib.ToInt(value);
break;
default:
break;
}
}
}
nature.initValue = value;
}
}
}
return true;
}
7.解析自定义属性值
/**********************************************/
///<summary>
///Name :AnalysisNatureValuePattern
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisNatureValuePattern(MsgInfo_Type msgInfo, 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))
{
string str = match.Value.Trim(';');
string[] array = str.Split(new string[] { " ", @"""" }, StringSplitOptions.RemoveEmptyEntries);
string name = CommonLib.ToVar(array[1]);
foreach (Nature_Type nature in msgInfo.natures)
{
if (nature.name == name)
{
if (name.Equals("BusType"))
{
msgInfo.busType = array[2].Equals("CAN") ? BusTypeEnum.CAN : BusTypeEnum.CANFD;
continue;
}
uint? id = array.Length <= 3 ? null : (CommonLib.ToDec(array[3]) & 0x7FFFFFFF);
if (id == null) { continue; }
Message_Type message = FindMessage(msgInfo.messages, (uint)id);
if (message == null) { continue; }
string type = array[2];
try
{
if (type == "BO_")
{
switch (name)
{
case "GenMsgCycleTime":
message.cycleTime = CommonLib.ToInt(array[4]);
break;
case "GenMsgCycleTimeFast":
message.cycleTimeFast = CommonLib.ToInt(array[4]);
break;
case "GenMsgNrOfRepetition":
message.nrOfRepetition = CommonLib.ToInt(array[4]);
break;
case "GenMsgDelayTime":
message.delayTime = CommonLib.ToInt(array[4]);
break;
case "NmMessage":
message.type = nature.data[(int)CommonLib.ToInt(array[4])].ToLower().Contains("yes") ? TypeEnum.NM : TypeEnum.NORMAL;
break;
case "GenMsgSendType":
message.sendType = nature.data[(int)CommonLib.ToInt(array[4])];
break;
default:
break;
}
}
else if (type == "SG_")
{
foreach (Signal_Type signal in message.signals)
{
if (signal.name == array[4])
{
switch (name)
{
case "GenSigStartValue":
signal.initValue = CommonLib.ToInt(array[5]);
break;
case "GenSigTimeoutValue":
signal.invalidValue = CommonLib.ToInt(array[5]);
break;
case "GenSigInactiveValue":
signal.inactiveValue = CommonLib.ToInt(array[5]);
break;
case "GenSigSendType":
signal.sendType = nature.data[(int)CommonLib.ToInt(array[5])];
break;
case "GenSigMinValue":
signal.minValue = CommonLib.ToInt(array[5]);
break;
case "GenSigMaxValue":
signal.maxValue = CommonLib.ToInt(array[5]);
break;
default:
break;
}
}
}
}
}
catch { continue; }
}
}
}
return true;
}
8.解析数值表
/**********************************************/
///<summary>
///Name :AnalysisSignalValueDescriptionPattern
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisSignalValueDescriptionPattern(List<Message_Type> messages, string data)
{
string pattern = "VAL_[ ]+(\\d+)[ ]+(\\w+)[ ]+(((\\d+.?\\d*)(([ ]+)|)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"[ ]*)*)+(([ ]+)|);";
foreach (Match match in Regex.Matches(data, pattern))
{
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 = CommonLib.ToDec(array2[1]) & 0x7FFFFFFF;
if (id == null) { continue; }
Message_Type message = FindMessage(messages, (uint)id);
if (message == null) { continue; }
string name = CommonLib.ToVar(array2[2]);
foreach (Signal_Type signal in message.signals)
{
if (signal.name == name)
{
for (int i = 0; i < array1.Length / 2; i++)
{
ValueDescriptionInfoModel valueDescription = new ValueDescriptionInfoModel();
if (i == 0)
{
valueDescription.Value = CommonLib.ToDec(array2[3]);
valueDescription.Name = array1[1];
}
else
{
valueDescription.Value = CommonLib.ToDec(array1[2 * i]);
valueDescription.Name = array1[(2 * i) + 1];
}
signal.valueDescriptions.Add(valueDescription);
}
break;
}
}
}
return true;
}
五、MatrixCreat工具
这儿我只把链接放上,具体使用说明见后续章节。
DBC转Excel;DBC转位定义;Excel转DBC;Excel转位定义:https://download.csdn.net/download/weixin_44926112/86912538
六、其他
本文主要是讲解DBC文件的结构和如何解析DBC文件,有些地方可能会有描述性的错误,希望看到的朋友及时指出,我会及时更正错误,其他地方有些借鉴的描述,写此文章的目的是为了交流,非商业用途,欢迎私信讨论,感谢大家阅读。
七、参考
【1】:https://blog.csdn.net/weixin_44536482/article/details/89030152
【2】:https://blog.csdn.net/Jiang_Mr/article/details/103417163