LDF文件详解
一、摘要
1.描述
本文主要描述的是汽车行业中LDF文件的格式,如何去解析它,如何通过文本编辑器去修改它,了解LDF文件之前如果不懂LDF的请去查看我之前的博客。
2.关键字
LDF,LDF解析,LDF数据库,LDF文件,C#解析LDF文件。
二、为什么要了解LDF文件
LDF文件在汽车行业应用十分广泛,如果编辑LDF文件我们都使用Vector工具DF Explorer Pro或者LDFEditor去编辑,那效率将会是十分的低下,当我们了解了LDF文件的构成后,我们可以通过其他方式进行解析,可以大大的提高工作的效率,我们可以通过记事本或者其他工具打开LDF文件。
三、LDF文件构成
1.版本
关键字:LIN_protocol_version
格式:LIN_protocol_version = “version”;
格式中的version就是版本信息,版本信息可以为空,但是不能省略""符。
例如:LIN_protocol_version = “2.1”;代表版本号为V2.1。

2.波特率
关键字:LIN_speed
格式:LIN_speed = baudrate;
格式中的baudrate就是波特率。
例如:LIN_speed = 19.2 kbps;;代表波特率为19200。

3.节点信息
关键字:Nodes
格式:Nodes {
Master: name1 jitter ms, timebase ms ;
Slaves: name2,name3…;
}
name1:主节点名称。
jitter:偏移是指一帧报文实际开始发送的时刻与帧时隙起点的时间差。
timebase:时间基数
name2,name3…:代表接收节点名称。
例如:Nodes {
Master: GW_BCM, 1 ms, 0 ms ;
Slaves: LIN_RLS,Tellus_Node;
}
代表主节点名称为BCM,偏移为1ms,时间基数为0ms,从节点名称为LIN_RLS和Tellus_Node。

4.信号信息
关键字:Signals
格式:Signals {
Signal_Name: Bit_Length, Signal_Init_Value, name1, name2… ;
…;
}
Signal_Name:信号名称,命名规则和C语言变量相同。
Bit_Length:信号的长度,范围为1-64。
Signal_Init_Value:信号初始值。
name1,name2…:代表接收节点名称。
例如:Signals {
BCM_WiperRunning: 1, 0, GW_BCM, LIN_RLS ;
RLS_MessageCounter: 4, 0, LIN_RLS, GW_BCM;
}
代表信号名称为BCM_WiperRunning的长度为1,初始值为0,接收节点有GW_BCM, LIN_RLS;
信号名称为RLS_MessageCounter的长度为4,初始值为0,接收节点有LIN_RLS, GW_BCM;

5.诊断信号信息
关键字:Diagnostic_signals
格式:Diagnostic_signals{
Signal_Name: Bit_Length, Signal_Init_Value ;
…;
}
Msg_ID:报文标识符,十进制表示。
Msg_Name:报文名称,命名规则和C语言变量相同。
Msg_Length :报文长度,长度范围为0-8。
例如:Diagnostic_signals{
MasterReqB0: 8, 0 ;
MasterReqB1: 8, 0 ;
MasterReqB2: 8, 0 ;
MasterReqB3: 8, 0 ;
MasterReqB4: 8, 0 ;
MasterReqB5: 8, 0 ;
MasterReqB6: 8, 0 ;
MasterReqB7: 8, 0 ;
SlaveRespB0: 8, 0 ;
SlaveRespB1: 8, 0 ;
SlaveRespB2: 8, 0 ;
SlaveRespB3: 8, 0 ;
SlaveRespB4: 8, 0 ;
SlaveRespB5: 8, 0 ;
SlaveRespB6: 8, 0 ;
SlaveRespB7: 8, 0 ;
}
诊断报文一般自动生成的格式基本不变,也可以做一定名字调整等。

6.报文消息
关键字:Frames
格式:Frames {
Msg_Name: Msg_ID, Msg_Transmitter, Msg_Length {
Signal_Name, Start_Bit;
…;
};
…;
}
Msg_Name:报文名称,命名规则和C语言变量相同。
Msg_ID:报文标识符,十进制或者十六进制表示。
Msg_Transmitter:发送节点。
Msg_Length :报文长度,长度范围为0-8。
Signal_Name:信号名称,命名规则和C语言变量相同。
Start_Bit:信号的起始位,范围为0-63。
例如:Frames {
BCM_data: 21, GW_BCM, 8{
BCM_WiperRunning, 23;
}
RLS_data: 13, LIN_RLS, 8{
RLS_MessageCounter, 0;
}
}
代表报文名称BCM_data的ID为0x15,长度为8,发送节点为GW_BCM,包含信号名称为BCM_WiperRunning,该信号起始位为23;
报文名称RLS_data的ID为0x0D,长度为8,发送节点为LIN_RLS,包含信号名称为RLS_MessageCounter,该信号起始位为0;

7.诊断报文消息
关键字:Diagnostic_frames
格式:Diagnostic_frames {
MasterReq: Msg_ID{
Signal_Name, Start_Bit;
…;
};
SlaveResp: Msg_ID{
Signal_Name, Start_Bit;
…;
};
}
Msg_ID:报文标识符,十进制或者十六进制表示。
Msg_Length :报文长度,长度范围为0-8。
Signal_Name:信号名称,命名规则和C语言变量相同。
Start_Bit:信号的起始位,范围为0-63。
例如:Diagnostic_frames {
MasterReq: 0x3c {
MasterReqB0, 0;
MasterReqB1, 8;
MasterReqB2, 16;
MasterReqB3, 24
MasterReqB4, 32;
MasterReqB5, 40;
MasterReqB6, 48;
MasterReqB7, 56;
}
SlaveResp: 0x3d {
SlaveRespB0, 0;
SlaveRespB1, 8;
SlaveRespB2, 16;
SlaveRespB3, 24
SlaveRespB4, 32;
SlaveRespB5, 40;
SlaveRespB6, 48;
SlaveRespB7, 56;
}
}

8.从节点信息
- 关键字:Node_attributes
格式: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。
9.调度表
- 关键字:Node_attributes
格式: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。
10.描述信息
关键字:Signal_encoding_types
格式:Signal_encoding_types {
Signal_Encoding{
physical_value, Min, Max, Factor, Offset,“Unit” ;
logical_value, N, “DefineN;
…;
};
…;
}
Signal_Encoding:信号描述定义名称,命名规则和C语言变量相同。
N:定义的数值表内容。
Min:属性值的最小值(十进制)。
Min:属性值的最大值(十进制)。
Factor:精度。
Offset:偏移量,Factor和Offset这两个值于该信号的原始值与物理值之间的转换,转换如下:物理值=原始值*因子+偏移量。
DefineN:数值表内容对应该信号的有效值分别用什么符号表示。
Unit:信号的单位,为字符串类型,可以省略,省略时“,”也要省略。
例如:Signal_encoding_types{
BCM_AMP_Driver_Encoding {
physical_value, 0, 7, 1, 0 ;
logical_value, 0, “No input” ;
logical_value, 1, “Manual Up” ;
logical_value, 2, “Manual Down” ;
}
}
代表描述信号名称为BCM_AMP_Driver_Encoding 的最小值为0,最大值为7,精度为1,偏移量为0,定义0x00表示为"No input" ,0x01表示为"Manual Up" ,0x02表示为"Manual Down" 。

11.信号描述关联
关键字:Signal_representation
格式:Signal_representation {
Signal_Encoding: Signal_Name1, Signal_Name2…;
…
}
Signal_Encoding:信号描述定义名称,命名规则和C语言变量相同。
Signal_Name1,Signal_Name2…:信号定义名称,命名规则和C语言变量相同。
例如:Signal_representation {
BCM_AMP_Driver_Encoding: BCM_AMP_Driver ;
BCM_DRV_SWITCH_COOL_Encoding: BCM_DRV_SWITCH_COOL ;
}
代表信号名称为BCM_AMP_Driver 的信号定义是BCM_AMP_Driver_Encoding的内容;
BCM_DRV_SWITCH_COOL_Encoding的信号定义是BCM_DRV_SWITCH_COOL 的内容。

四、LDF文件解析
通过以上描述,我相信各位对LDF文件的结构有一定的了解,但是我们如何去解析呢,很多人第一时间想到的应该是按行解析,其实LDF文件有许多容错处理,单纯按行解析我们会错过许多细节部分,例如下图其实也没有出错,如果按行解析的话报文就解析不到了。还有很多类似的容错处理在里面,所以单纯按行解析是不行的,并且有的时候也是不能通过空格来分开数据的,比如带有“”的前后是可以不追加空格的。

经过好久的挣扎,查询资料,终于在一个博客的找到了一种解析的方式,通过正则表达式去解析,当然他其实是按行解析,其实会丢掉一些数据,我将方法进行了一些简单的优化,先读取整个文件到字符串,把多行空格转换成一行空格,然后把换行符转换成空格符,然后进行查找,然后按照标准进行拆分。我这边解析的主要使用的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 = "LIN_protocol_version([ ]*)(=)([ ]*)\"((([^\"\\s])|([\\s\\u4e00-\\u9fa5]))*)\"([ ]*);";
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 :AnalysisNodes
///Author :WangHu
///Function:***
///Version :V1.0.0
///Data :2022.5.20
///</summary>
/**********************************************/
private static bool AnalysisNodes(MsgInfo_Type msgInfo, string data)
{
string pattern = "(Nodes[ ]*){[^{}]*}";
foreach (Match match in Regex.Matches(data, pattern))
{
string masterPattern = "(Master[ ]*):([ ]*\\w+[ ]*),([ ]*(\\.|\\w|[ ])+[ ]*),([ ]*(\\.|\\w|[ ])+[ ]*);";
foreach (Match masterMatch in Regex.Matches(match.Value, masterPattern))
{
string[] array = masterMatch.Value.Split(new string[] {
" ", ":", ",", ";" }, StringSplitOptions.RemoveEmptyEntries);
msgInfo.master = array[1];
}
string slavesPattern = "(Slaves[ ]*):([ ]*\\w+[ ]*)(,[ ]*\\w+[ ]*)*;";
foreach (Match slavesMatch in Regex.Matches(match.Value, slavesPattern))
{
string[] array = slavesMatch.Value.Split(new string[] {
" "

本文深入剖析LDF文件格式,涵盖版本、波特率、节点、信号等关键元素,详述C#解析技巧,助您高效处理汽车通讯数据。
最低0.47元/天 解锁文章
9326





