从 MDF 文件中解码 J1939 数据
此示例说明如何在 MATLAB® 中从 MDF 文件中导入和解码 J1939 数据进行分析。此示例中使用的 MDF 文件是使用 Vector 的 CANoe 基于 System Configuration (J1939) 采样生成的。此示例还使用 Vector 采样配置提供的 CAN 数据库文件 Powertrain_J1939_MDF.dbc
。
查看 MDF 文件的详细信息
使用 mdfInfo
函数查看 MDF 文件的元数据。
mdfInfo("LoggingMDF_J1939.mf4")
ans = MDFInfo with properties: File Details Name: "LoggingMDF_J1939.mf4" Path: "/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex76385747/LoggingMDF_J1939.mf4" Author: "" Department: "" Project: "" Subject: "" Comment: "" Version: "4.10" InitialTimestamp: 2021-04-21 14:05:13.232000000 Creator Details ProgramIdentifier: "MDF4Lib" CreatorVendorName: "Vector Informatik GmbH" CreatorToolName: "CANoe" CreatorToolVersion: "12.0.167" CreatorUserName: "sdange" CreatorComment: "Created using MdfLog version 1.5.1.0 and Mdf4Lib version 1.6.1.0 X64 (2018-03-13)" File Contents Attachment: [5x7 table] ChannelGroupCount: 43
标识 J1939 CAN 数据帧
根据总线日志记录的 ASAM MDF 相关联标准,为 CAN 总线系统定义的事件类型可以是“CAN_DataFrame”、“CAN_RemoteFrame”、“CAN_ErrorFrame”或“CAN_OverloadFrame”。 J1939 是基于 CAN 协议构建的协议。J1939 参数组 (PG) 是属于同一主题并共享相同传输速率的一组参数。例如,电子发动机控制器 1 (EEC1) PG 包含发动机转速、发动机扭矩要求百分比、实际发动机扭矩百分比等。 每个参数组都通过一个称为参数组编号 (PGN) 的唯一编号进行寻址。J1939 PG 作为 CAN 帧传输,MDF 文件反映 J1939 PG 记录为 CAN_DataFrame。
该标准规定事件结构体的通道名称应以事件类型名称为前缀,例如“CAN_DataFrame”。通常,使用点作为分隔符来指定成员通道,例如“CAN_DataFrame.ID”或“CAN_DataFrame.DataLength”。
使用 mdfChannelInfo
函数查找与“CAN_DataFrame.*”匹配的通道名称。返回包含匹配通道信息的表。
mdfChannelInfo("LoggingMDF_J1939.mf4", Channel="CAN_DataFrame.*")
ans=24×13 table
Name GroupNumber GroupNumSamples GroupAcquisitionName GroupComment GroupSourceName GroupSourcePath DisplayName Unit Comment ExtendedNamePrefix SourceName SourcePath
_____________________________ ___________ _______________ ____________________ ____________ _______________ _______________ _______________ ___________ __________________________________________________________ __________________ ___________ __________
"CAN_DataFrame.BitCount" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "BitCount" <undefined> Frame length in bits. CAN2 <undefined> CAN2
"CAN_DataFrame.BitCount" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "BitCount" <undefined> Frame length in bits. CAN1 <undefined> CAN1
"CAN_DataFrame.BusChannel" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "BusChannel" <undefined> Logical bus channel number the frame was sent or received. CAN2 <undefined> CAN2
"CAN_DataFrame.BusChannel" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "BusChannel" <undefined> Logical bus channel number the frame was sent or received. CAN1 <undefined> CAN1
"CAN_DataFrame.DLC" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "DLC" <undefined> Data length code. CAN2 <undefined> CAN2
"CAN_DataFrame.DLC" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "DLC" <undefined> Data length code. CAN1 <undefined> CAN1
"CAN_DataFrame.DataBytes" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "DataBytes" <undefined> Payload data bytes containing the signal values. CAN2 <undefined> CAN2
"CAN_DataFrame.DataBytes" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "DataBytes" <undefined> Payload data bytes containing the signal values. CAN1 <undefined> CAN1
"CAN_DataFrame.DataLength" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "DataLength" <undefined> Length of stored payload in bytes. CAN2 <undefined> CAN2
"CAN_DataFrame.DataLength" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "DataLength" <undefined> Length of stored payload in bytes. CAN1 <undefined> CAN1
"CAN_DataFrame.Dir" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "Dir" <undefined> Bit signal indicating the direction (Rx, Tx). CAN2 <undefined> CAN2
"CAN_DataFrame.Dir" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "Dir" <undefined> Bit signal indicating the direction (Rx, Tx). CAN1 <undefined> CAN1
"CAN_DataFrame.Flags" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "Flags" <undefined> Combination of bit flags for the message. CAN2 <undefined> CAN2
"CAN_DataFrame.Flags" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "Flags" <undefined> Combination of bit flags for the message. CAN1 <undefined> CAN1
"CAN_DataFrame.FrameDuration" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "FrameDuration" ns Duration for transmission of the frame in nanoseconds. CAN2 <undefined> CAN2
"CAN_DataFrame.FrameDuration" 14 92720 CAN1 <undefined> <undefined> CAN_DataFrame "FrameDuration" ns Duration for transmission of the frame in nanoseconds. CAN1 <undefined> CAN1
⋮
感兴趣的 J1939 动力总成系统数据是从 CAN 2 网络记录的。上面的输出显示来自 CAN 2 网络的数据已存储在 MDF 文件的通道组 13 中。通过指定 GroupNumber
选项,使用 mdfChannelGroupInfo
函数查看有关通道组 13 的详细信息。
mdfChannelGroupInfo("LoggingMDF_J1939.mf4", GroupNumber=13)
ans=1×13 table
GroupNumber AcquisitionName Comment NumSamples DataSize Sorted SourceName SourcePath SourceComment SourceType SourceBusType SourceBusChannelNumber SourceSimulated
___________ _______________ ___________ __________ ________ ______ ___________ _____________ _____________ __________ _____________ ______________________ _______________
13 CAN2 <undefined> 26054 703458 true <undefined> CAN_DataFrame <undefined> Bus CAN 2 false
使用 mdfChannelInfo
查看通道组 13 中所有通道的详细信息。
mdfChannelInfo("LoggingMDF_J1939.mf4", GroupNumber=13)
ans=13×13 table
Name GroupNumber GroupNumSamples GroupAcquisitionName GroupComment GroupSourceName GroupSourcePath DisplayName Unit Comment ExtendedNamePrefix SourceName SourcePath
_____________________________ ___________ _______________ ____________________ ____________ _______________ _______________ _______________ ___________ __________________________________________________________ __________________ ___________ ___________
"CAN_DataFrame.BitCount" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "BitCount" <undefined> Frame length in bits. CAN2 <undefined> CAN2
"CAN_DataFrame.BusChannel" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "BusChannel" <undefined> Logical bus channel number the frame was sent or received. CAN2 <undefined> CAN2
"CAN_DataFrame.DLC" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "DLC" <undefined> Data length code. CAN2 <undefined> CAN2
"CAN_DataFrame.DataBytes" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "DataBytes" <undefined> Payload data bytes containing the signal values. CAN2 <undefined> CAN2
"CAN_DataFrame.DataLength" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "DataLength" <undefined> Length of stored payload in bytes. CAN2 <undefined> CAN2
"CAN_DataFrame.Dir" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "Dir" <undefined> Bit signal indicating the direction (Rx, Tx). CAN2 <undefined> CAN2
"CAN_DataFrame.Flags" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "Flags" <undefined> Combination of bit flags for the message. CAN2 <undefined> CAN2
"CAN_DataFrame.FrameDuration" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "FrameDuration" ns Duration for transmission of the frame in nanoseconds. CAN2 <undefined> CAN2
"CAN_DataFrame.ID" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "ID" <undefined> ID of the CAN message. CAN2 <undefined> CAN2
"CAN_DataFrame.IDE" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "IDE" <undefined> Identifier Extension bit. CAN2 <undefined> CAN2
"CAN_DataFrame.SingleWire" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "SingleWire" <undefined> Bit flag indicating a single wire operation. CAN2 <undefined> CAN2
"CAN_DataFrame.WakeUp" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "WakeUp" <undefined> Bit flag indicating a wake-up message (high voltage). CAN2 <undefined> CAN2
"t" 13 26054 CAN2 <undefined> <undefined> CAN_DataFrame "" s <undefined> CAN2 <undefined> <undefined>
从 MDF 文件中读取 J1939 CAN 数据帧
使用 mdfRead
函数将通道组 13 中所有通道的所有数据读入一个时间表中。时间表的结构遵循 ASAM MDF 标准日志记录格式。每行表示来自总线的一个原始 CAN 帧,而每列表示指定通道组中的一个通道。通道,如“CAN_DataFrame.Dir”,是按照总线日志记录标准命名的。
data = mdfRead("LoggingMDF_J1939.mf4", GroupNumber=13)
data = 1x1 cell array
{26054x12 timetable}
canData = data{1}
canData=26054×12 timetable
t CAN_DataFrame.BusChannel CAN_DataFrame.Flags CAN_DataFrame.Dir CAN_DataFrame.SingleWire CAN_DataFrame.WakeUp CAN_DataFrame.ID CAN_DataFrame.IDE CAN_DataFrame.FrameDuration CAN_DataFrame.BitCount CAN_DataFrame.DLC CAN_DataFrame.DataLength CAN_DataFrame.DataBytes
____________ ________________________ ___________________ _________________ ________________________ ____________________ ________________ _________________ ___________________________ ______________________ _________________ ________________________ ___________________________________
0.000568 sec 2 1 "Tx" 0 0 2565799910 1 0 0 8 8 {[ 105 52 169 232 0 131 0 16]}
0.27057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.29057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.30058 sec 2 1 "Tx" 0 0 2565866470 1 0 0 8 8 {[ 255 0 255 255 255 255 255 255]}
0.30116 sec 2 1 "Tx" 0 0 2566810854 1 0 0 8 8 {[255 255 255 255 255 255 255 255]}
0.31057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.33057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.35058 sec 2 1 "Tx" 0 0 2565866470 1 0 0 8 8 {[ 255 0 255 255 255 255 255 255]}
0.35115 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.35173 sec 2 1 "Tx" 0 0 2566810854 1 0 0 8 8 {[255 255 255 255 255 255 255 255]}
0.3523 sec 2 1 "Tx" 0 0 2566844902 1 0 0 8 8 {[ 255 0 0 12 255 255 224 255]}
0.37057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.39057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
0.40058 sec 2 1 "Tx" 0 0 2565866470 1 0 0 8 8 {[ 255 0 255 255 255 255 255 255]}
0.40116 sec 2 1 "Tx" 0 0 2566810854 1 0 0 8 8 {[255 255 255 255 255 255 255 255]}
0.41057 sec 2 1 "Tx" 0 0 2565866726 1 0 0 8 8 {[ 255 255 255 208 7 255 255 255]}
⋮
使用 DBC 文件解码 J1939 参数组
使用 canDatabase
函数打开 DBC 文件。
canDB = canDatabase("Powertrain_J1939_MDF.dbc")
canDB = Database with properties: Name: 'Powertrain_J1939_MDF' Path: '/tmp/Bdoc24a_2511836_3070643/tp8879c7f7/vnt-ex76385747/Powertrain_J1939_MDF.dbc' UTF8_File: '/tmp/Bdoc24a_2511836_3070643/tp1d547111_a021_43b6_98c7_4f409bc4bc4a' Nodes: {12x1 cell} NodeInfo: [12x1 struct] Messages: {93x1 cell} MessageInfo: [93x1 struct] Attributes: {3x1 cell} AttributeInfo: [3x1 struct] UserData: []
j1939ParameterGroupTimetable
函数使用数据库将原始 CAN 数据解码为 PG、PGN 和信号。将 ASAM 标准记录格式数据的时间表转换为 Vehicle Network Toolbox™ J1939 参数组时间表。
j1939PGTimetable = j1939ParameterGroupTimetable(canData, canDB)
j1939PGTimetable=26054×8 timetable
Time Name PGN Priority PDUFormatType SourceAddress DestinationAddress Data Signals
____________ ________ _____ ________ _____________________ _____________ __________________ ___________________________________ ____________
0.000568 sec ACL 60928 6 Peer-to-Peer (Type 1) 230 255 {[ 105 52 169 232 0 131 0 16]} {1x1 struct}
0.27057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.29057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.30058 sec EEC2_EMS 61443 6 Broadcast (Type 2) 230 255 {[ 255 0 255 255 255 255 255 255]} {1x1 struct}
0.30116 sec TCO1_TCO 65132 6 Broadcast (Type 2) 230 255 {[255 255 255 255 255 255 255 255]} {1x1 struct}
0.31057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.33057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.35058 sec EEC2_EMS 61443 6 Broadcast (Type 2) 230 255 {[ 255 0 255 255 255 255 255 255]} {1x1 struct}
0.35115 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.35173 sec TCO1_TCO 65132 6 Broadcast (Type 2) 230 255 {[255 255 255 255 255 255 255 255]} {1x1 struct}
0.3523 sec CCVS_EMS 65265 6 Broadcast (Type 2) 230 255 {[ 255 0 0 12 255 255 224 255]} {1x1 struct}
0.37057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.39057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
0.40058 sec EEC2_EMS 61443 6 Broadcast (Type 2) 230 255 {[ 255 0 255 255 255 255 255 255]} {1x1 struct}
0.40116 sec TCO1_TCO 65132 6 Broadcast (Type 2) 230 255 {[255 255 255 255 255 255 255 255]} {1x1 struct}
0.41057 sec EEC1_EMS 61444 6 Broadcast (Type 2) 230 255 {[ 255 255 255 208 7 255 255 255]} {1x1 struct}
⋮
查看时间表的第三个 PG 中存储的信号数据,这是“EEC1_EMS”PG 的一个实例。
signalData = j1939PGTimetable.Signals{3}
signalData = struct with fields:
EngDemandPercentTorque: 130
EngStarterMode: 15
SrcAddrssOfCtrllngDvcForEngCtrl: 255
EngSpeed: 250
ActualEngPercentTorque: 130
DriversDemandEngPercentTorque: 130
EngTorqueMode: 15
重新打包并可视化感兴趣的信号值
使用 j1939SignalTimetable
函数将来自总线上每个唯一 PGN 的信号数据重新打包到一个信号时间表中。此示例根据 J1939 PG 时间表为两个感兴趣的 PG(“EEC1_EMS”和“TCO1_TCO”)创建两个单独的信号时间表。
signalTimetable1 = j1939SignalTimetable(j1939PGTimetable, "ParameterGroups", "EEC1_EMS")
signalTimetable1=12043×7 timetable
Time EngDemandPercentTorque EngStarterMode SrcAddrssOfCtrllngDvcForEngCtrl EngSpeed ActualEngPercentTorque DriversDemandEngPercentTorque EngTorqueMode
___________ ______________________ ______________ _______________________________ ________ ______________________ _____________________________ _____________
0.27057 sec 130 15 255 250 130 130 15
0.29057 sec 130 15 255 250 130 130 15
0.31057 sec 130 15 255 250 130 130 15
0.33057 sec 130 15 255 250 130 130 15
0.35115 sec 130 15 255 250 130 130 15
0.37057 sec 130 15 255 250 130 130 15
0.39057 sec 130 15 255 250 130 130 15
0.41057 sec 130 15 255 250 130 130 15
0.43057 sec 130 15 255 250 130 130 15
0.45115 sec 130 15 255 250 130 130 15
0.47057 sec 130 15 255 250 130 130 15
0.49057 sec 130 15 255 250 130 130 15
0.51057 sec 130 15 255 250 130 130 15
0.53057 sec 130 15 255 250 130 130 15
0.55115 sec 130 15 255 250 130 130 15
0.57057 sec 130 15 255 250 130 130 15
⋮
signalTimetable2 = j1939SignalTimetable(j1939PGTimetable, "ParameterGroups", "TCO1_TCO")
signalTimetable2=4817×14 timetable
Time TachographVehicleSpeed TachographOutputShaftSpeed DirectionIndicator TachographPerformance HandlingInformation SystemEvent DriverCardDriver2 Driver2TimeRelatedStates Overspeed DriverCardDriver1 Driver1TimeRelatedStates DriveRecognize Driver2WorkingState Driver1WorkingState
___________ ______________________ __________________________ __________________ _____________________ ___________________ ___________ _________________ ________________________ _________ _________________ ________________________ ______________ ___________________ ___________________
0.30116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.35173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.40116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.45173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.50116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.55173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.60116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.65173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.70116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.75173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.80116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.85173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.90116 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
0.95173 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
1.0012 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
1.0517 sec 256 8191.9 3 3 3 3 3 15 3 3 15 3 7 7
⋮
您也可以选择将整个 J1939 PG 时间表转换为一个结构体,该结构体包含每个单独 PG 的多个 J1939 信号时间表,并对其进行索引以获取特定 PG 的数据。
signalTimetables = j1939SignalTimetable(j1939PGTimetable)
signalTimetables = struct with fields:
ACL: [1x14 timetable]
CCVS_EMS: [2408x19 timetable]
DD: [240x5 timetable]
EEC1_EMS: [12043x7 timetable]
EEC2_EMS: [4817x10 timetable]
ET1_EMS: [240x6 timetable]
HOURS_EMS: [240x2 timetable]
LFC_EMS: [480x2 timetable]
SERV: [240x6 timetable]
TCO1_TCO: [4817x14 timetable]
VDHR_EMS: [240x2 timetable]
VI_EMS: [24x1 timetable]
VW_SSC: [240x4 timetable]
signalTimetables.EEC1_EMS
ans=12043×7 timetable
Time EngDemandPercentTorque EngStarterMode SrcAddrssOfCtrllngDvcForEngCtrl EngSpeed ActualEngPercentTorque DriversDemandEngPercentTorque EngTorqueMode
___________ ______________________ ______________ _______________________________ ________ ______________________ _____________________________ _____________
0.27057 sec 130 15 255 250 130 130 15
0.29057 sec 130 15 255 250 130 130 15
0.31057 sec 130 15 255 250 130 130 15
0.33057 sec 130 15 255 250 130 130 15
0.35115 sec 130 15 255 250 130 130 15
0.37057 sec 130 15 255 250 130 130 15
0.39057 sec 130 15 255 250 130 130 15
0.41057 sec 130 15 255 250 130 130 15
0.43057 sec 130 15 255 250 130 130 15
0.45115 sec 130 15 255 250 130 130 15
0.47057 sec 130 15 255 250 130 130 15
0.49057 sec 130 15 255 250 130 130 15
0.51057 sec 130 15 255 250 130 130 15
0.53057 sec 130 15 255 250 130 130 15
0.55115 sec 130 15 255 250 130 130 15
0.57057 sec 130 15 255 250 130 130 15
⋮
为了可视化感兴趣的信号,可以绘制信号时间表中的变量随时间变化的图,以便进一步分析。对于此示例,请查看来自 EEC1_EMS PG 的 EngineSpeed 信号。
plot(signalTimetable1.Time, signalTimetable1.EngSpeed, "r") title("{\itEngineSpeed} signal from {\itEEC1\_EMS} PG", "FontWeight", "bold") xlabel("Timestamp") ylabel("Engine Speed")
关闭 DBC 文件
通过从工作区中清除 DBC 文件的变量,关闭对该 DBC 文件的访问。
clear canDB