Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

解码并将 CAN 数据写入 MDF 文件

此示例说明如何在 MATLAB® 中从 MDF 文件导入 CAN 数据并对其进行解码以供分析,然后将解码后的数据写回到同一个文件中。

此示例中使用的 MDF 文件是使用 Vector 的 CANoe™ 基于 CAN - General System Configuration (CAN) 采样生成的。此示例还使用 Vector 采样配置提供的 CAN 数据库文件 PowerTrain.dbc

查看 MDF 文件的详细信息

使用 mdfInfo 函数查看 MDF 文件的元数据。

mdfInfo("Logging_MDF.mf4")
ans = 
  MDFInfo with properties:

   File Details
                  Name: "Logging_MDF.mf4"
                  Path: "/tmp/Bdoc23b_2361005_1548966/tp60a7197f/vnt-ex42187575/Logging_MDF.mf4"
                Author: ""
            Department: ""
               Project: ""
               Subject: ""
               Comment: ""
               Version: "4.10"
      InitialTimestamp: 2020-06-25 20:41:13.133000000

   Creator Details
     ProgramIdentifier: "MDF4Lib"
     CreatorVendorName: "Vector Informatik GmbH"
       CreatorToolName: "CANoe"
    CreatorToolVersion: "13.0.118"
       CreatorUserName: "michellw"
        CreatorComment: "Created using MdfLog version 1.5.4.0 and Mdf4Lib version 1.7.0.5  X64 (2019-10-22)"

   File Contents
            Attachment: [5x7 table]
     ChannelGroupCount: 62

标识 CAN 数据帧

根据总线日志记录的 ASAM MDF 相关联标准,为 CAN 总线系统定义的事件类型可以是“CAN_DataFrame”、“CAN_RemoteFrame”、“CAN_ErrorFrame”或“CAN_OverloadFrame”。此示例的重点是提取 CAN 数据帧,因此将使用“CAN_DataFrame”事件类型作为示例来讨论总线日志记录标准。此外,请注意,标准 CAN 数据帧的有效负载最多包含 8 个字节,用于传输信号值。

该标准规定事件结构体的通道名称应以事件类型名称为前缀,例如“CAN_DataFrame”。通常,使用点作为分隔符来指定成员通道,例如“CAN_DataFrame.ID”或“CAN_DataFrame.DataLength”。

使用 mdfChannelInfo 函数查找与“CAN_DataFrame.*”匹配的通道名称。返回包含匹配通道信息的表。

mdfChannelInfo("Logging_MDF.mf4", Channel="CAN_DataFrame.*")
ans=24×13 table
                Name                 GroupNumber    GroupNumSamples    GroupAcquisitionName    GroupComment    GroupSourceName    GroupSourcePath      DisplayName         Unit                                 Comment                              ExtendedNamePrefix    SourceName     SourcePath
    _____________________________    ___________    _______________    ____________________    ____________    _______________    _______________    _______________    ___________    __________________________________________________________    __________________    ___________    __________

    "CAN_DataFrame.BitCount"             17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "BitCount"         <undefined>    Frame length in bits.                                                CAN1           <undefined>       CAN1   
    "CAN_DataFrame.BitCount"             29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "BitCount"         <undefined>    Frame length in bits.                                                CAN2           <undefined>       CAN2   
    "CAN_DataFrame.BusChannel"           17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "BusChannel"       <undefined>    Logical bus channel number the frame was sent or received.           CAN1           <undefined>       CAN1   
    "CAN_DataFrame.BusChannel"           29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "BusChannel"       <undefined>    Logical bus channel number the frame was sent or received.           CAN2           <undefined>       CAN2   
    "CAN_DataFrame.DLC"                  17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "DLC"              <undefined>    Data length code.                                                    CAN1           <undefined>       CAN1   
    "CAN_DataFrame.DLC"                  29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "DLC"              <undefined>    Data length code.                                                    CAN2           <undefined>       CAN2   
    "CAN_DataFrame.DataBytes"            17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "DataBytes"        <undefined>    Payload data bytes containing the signal values.                     CAN1           <undefined>       CAN1   
    "CAN_DataFrame.DataBytes"            29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "DataBytes"        <undefined>    Payload data bytes containing the signal values.                     CAN2           <undefined>       CAN2   
    "CAN_DataFrame.DataLength"           17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "DataLength"       <undefined>    Length of stored payload in bytes.                                   CAN1           <undefined>       CAN1   
    "CAN_DataFrame.DataLength"           29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "DataLength"       <undefined>    Length of stored payload in bytes.                                   CAN2           <undefined>       CAN2   
    "CAN_DataFrame.Dir"                  17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "Dir"              <undefined>    Bit signal indicating the direction (Rx, Tx).                        CAN1           <undefined>       CAN1   
    "CAN_DataFrame.Dir"                  29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "Dir"              <undefined>    Bit signal indicating the direction (Rx, Tx).                        CAN2           <undefined>       CAN2   
    "CAN_DataFrame.Flags"                17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "Flags"            <undefined>    Combination of bit flags for the message.                            CAN1           <undefined>       CAN1   
    "CAN_DataFrame.Flags"                29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "Flags"            <undefined>    Combination of bit flags for the message.                            CAN2           <undefined>       CAN2   
    "CAN_DataFrame.FrameDuration"        17              8889                  CAN1            <undefined>       <undefined>       CAN_DataFrame     "FrameDuration"    ns             Duration for transmission of the frame in nanoseconds.               CAN1           <undefined>       CAN1   
    "CAN_DataFrame.FrameDuration"        29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "FrameDuration"    ns             Duration for transmission of the frame in nanoseconds.               CAN2           <undefined>       CAN2   
      ⋮

感兴趣的动力总成系统数据是从 CAN 2 网络记录的。上面的输出显示来自 CAN 2 网络的数据已存储在 MDF 文件的通道组 29 中。通过指定 GroupNumber 选项,使用 mdfChannelGroupInfo 函数查看有关通道组 29 的详细信息。

mdfChannelGroupInfo("Logging_MDF.mf4", GroupNumber=29)
ans=1×13 table
    GroupNumber    AcquisitionName      Comment      NumSamples    DataSize    Sorted    SourceName      SourcePath      SourceComment    SourceType    SourceBusType    SourceBusChannelNumber    SourceSimulated
    ___________    _______________    ___________    __________    ________    ______    ___________    _____________    _____________    __________    _____________    ______________________    _______________

        29              CAN2          <undefined>       7648        206496     true      <undefined>    CAN_DataFrame     <undefined>        Bus             CAN                   2                    false     

使用 mdfChannelInfo 查看通道组 29 中所有通道的详细信息。

mdfChannelInfo("Logging_MDF.mf4", GroupNumber=29)
ans=13×13 table
                Name                 GroupNumber    GroupNumSamples    GroupAcquisitionName    GroupComment    GroupSourceName    GroupSourcePath      DisplayName         Unit                                 Comment                              ExtendedNamePrefix    SourceName     SourcePath 
    _____________________________    ___________    _______________    ____________________    ____________    _______________    _______________    _______________    ___________    __________________________________________________________    __________________    ___________    ___________

    "CAN_DataFrame.BitCount"             29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "BitCount"         <undefined>    Frame length in bits.                                                CAN2           <undefined>    CAN2       
    "CAN_DataFrame.BusChannel"           29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "BusChannel"       <undefined>    Logical bus channel number the frame was sent or received.           CAN2           <undefined>    CAN2       
    "CAN_DataFrame.DLC"                  29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "DLC"              <undefined>    Data length code.                                                    CAN2           <undefined>    CAN2       
    "CAN_DataFrame.DataBytes"            29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "DataBytes"        <undefined>    Payload data bytes containing the signal values.                     CAN2           <undefined>    CAN2       
    "CAN_DataFrame.DataLength"           29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "DataLength"       <undefined>    Length of stored payload in bytes.                                   CAN2           <undefined>    CAN2       
    "CAN_DataFrame.Dir"                  29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "Dir"              <undefined>    Bit signal indicating the direction (Rx, Tx).                        CAN2           <undefined>    CAN2       
    "CAN_DataFrame.Flags"                29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "Flags"            <undefined>    Combination of bit flags for the message.                            CAN2           <undefined>    CAN2       
    "CAN_DataFrame.FrameDuration"        29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "FrameDuration"    ns             Duration for transmission of the frame in nanoseconds.               CAN2           <undefined>    CAN2       
    "CAN_DataFrame.ID"                   29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "ID"               <undefined>    ID of the CAN message.                                               CAN2           <undefined>    CAN2       
    "CAN_DataFrame.IDE"                  29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "IDE"              <undefined>    Identifier Extension bit.                                            CAN2           <undefined>    CAN2       
    "CAN_DataFrame.SingleWire"           29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "SingleWire"       <undefined>    Bit flag indicating a single wire operation.                         CAN2           <undefined>    CAN2       
    "CAN_DataFrame.WakeUp"               29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     "WakeUp"           <undefined>    Bit flag indicating a wake-up message (high voltage).                CAN2           <undefined>    CAN2       
    "t"                                  29              7648                  CAN2            <undefined>       <undefined>       CAN_DataFrame     ""                 s              <undefined>                                                          CAN2           <undefined>    <undefined>

从 MDF 文件中读取 CAN 数据帧

使用 mdfRead 函数将通道组 29 中的所有数据读入一个时间表中。时间表的结构遵循 ASAM MDF 标准日志记录格式。每行表示来自总线的一个原始 CAN 帧,而每列表示指定通道组中的一个通道。通道,如“CAN_DataFrame.Dir”,是按照总线日志记录标准命名的。

data = mdfRead("Logging_MDF.mf4", GroupNumber=29)
data = 1x1 cell array
    {7648x12 timetable}

canData = data{1}
canData=7648×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    
    __________    ________________________    ___________________    _________________    ________________________    ____________________    ________________    _________________    ___________________________    ______________________    _________________    ________________________    ______________________________

    2.2601 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.2801 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.3002 sec               2                         1                   "Tx"                      0                         0                     100                  0                      232000                        119                      8                       8                {[      238 2 25 1 0 0 238 2]}
    2.3005 sec               2                         1                   "Tx"                      0                         0                     102                  0                      240000                        123                      8                       8                {[       0 128 59 68 0 0 0 0]}
    2.3006 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.3008 sec               2                         1                   "Tx"                      0                         0                     201                  0                      196000                        101                      6                       6                {[            0 0 0 0 172 38]}
    2.3009 sec               2                         1                   "Tx"                      0                         0                    1020                  0                      110000                         58                      1                       1                {[                         1]}
    2.3201 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.3401 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.3502 sec               2                         1                   "Tx"                      0                         0                     100                  0                      234000                        120                      8                       8                {[      4 0 25 2 119 1 238 2]}
    2.3505 sec               2                         1                   "Tx"                      0                         0                     102                  0                      228000                        117                      8                       8                {[53 127 119 64 0 128 187 67]}
    2.3507 sec               2                         1                   "Tx"                      0                         0                     201                  0                      198000                        102                      6                       6                {[             0 0 0 0 35 40]}
    2.3508 sec               2                         1                   "Tx"                      0                         0                    1020                  0                      110000                         58                      1                       1                {[                         1]}
    2.3601 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.3801 sec               2                         1                   "Tx"                      0                         0                     103                  0                      128000                         67                      2                       2                {[                       1 0]}
    2.4002 sec               2                         1                   "Tx"                      0                         0                     100                  0                      234000                        120                      8                       8                {[     10 0 25 3 119 1 238 2]}
      ⋮

使用 DBC 文件解码 CAN 报文

使用 canDatabase 函数打开 DBC 文件。

canDB = canDatabase("PowerTrain_MDF.dbc")
canDB = 
  Database with properties:

             Name: 'PowerTrain_MDF'
             Path: '/tmp/Bdoc23b_2361005_1548966/tp60a7197f/vnt-ex42187575/PowerTrain_MDF.dbc'
        UTF8_File: '/tmp/Bdoc23b_2361005_1548966/tp60a7197f/vnt-ex42187575/PowerTrain_MDF.dbc'
            Nodes: {2x1 cell}
         NodeInfo: [2x1 struct]
         Messages: {12x1 cell}
      MessageInfo: [12x1 struct]
       Attributes: {11x1 cell}
    AttributeInfo: [11x1 struct]
         UserData: []

canMessageTimetable 函数使用数据库来解码报文名称和信号。ASAM 标准日志记录格式数据的时间表转换为 Vehicle Network Toolbox™ CAN 报文时间表。

msgTimetable = canMessageTimetable(canData, canDB)
msgTimetable=7648×8 timetable
       Time        ID     Extended           Name                        Data                 Length      Signals       Error    Remote
    __________    ____    ________    __________________    ______________________________    ______    ____________    _____    ______

    2.2601 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.2801 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.3002 sec     100     false      {'EngineData'    }    {[      238 2 25 1 0 0 238 2]}      8       {1x1 struct}    false    false 
    2.3005 sec     102     false      {'EngineDataIEEE'}    {[       0 128 59 68 0 0 0 0]}      8       {1x1 struct}    false    false 
    2.3006 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.3008 sec     201     false      {'ABSdata'       }    {[            0 0 0 0 172 38]}      6       {1x1 struct}    false    false 
    2.3009 sec    1020     false      {'GearBoxInfo'   }    {[                         1]}      1       {1x1 struct}    false    false 
    2.3201 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.3401 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.3502 sec     100     false      {'EngineData'    }    {[      4 0 25 2 119 1 238 2]}      8       {1x1 struct}    false    false 
    2.3505 sec     102     false      {'EngineDataIEEE'}    {[53 127 119 64 0 128 187 67]}      8       {1x1 struct}    false    false 
    2.3507 sec     201     false      {'ABSdata'       }    {[             0 0 0 0 35 40]}      6       {1x1 struct}    false    false 
    2.3508 sec    1020     false      {'GearBoxInfo'   }    {[                         1]}      1       {1x1 struct}    false    false 
    2.3601 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.3801 sec     103     false      {'Ignition_Info' }    {[                       1 0]}      2       {1x1 struct}    false    false 
    2.4002 sec     100     false      {'EngineData'    }    {[     10 0 25 3 119 1 238 2]}      8       {1x1 struct}    false    false 
      ⋮

查看“EngineData”报文中存储的信号。

msgTimetable.Signals{3}
ans = struct with fields:
    PetrolLevel: 1
       EngPower: 7.5000
       EngForce: 0
    IdleRunning: 0
        EngTemp: 0
       EngSpeed: 750

重新打包并可视化感兴趣的信号值

使用 canSignalTimetable 函数将来自总线上每个唯一报文的信号数据重新打包为一个信号时间表。此示例根据 CAN 报文时间表,为三个感兴趣的报文“ABSdata”、“EngineData”和“GearBoxInfo”创建三个单独的信号时间表。

signalTimetable1 = canSignalTimetable(msgTimetable, "ABSdata")
signalTimetable1=1147×4 timetable
       Time       AccelerationForce    Diagnostics    GearLock    CarSpeed
    __________    _________________    ___________    ________    ________

    2.3008 sec          -100                0            0            0   
    2.3507 sec           275                0            0            0   
    2.4008 sec           275                0            0            0   
    2.4507 sec           275                0            0            0   
    2.5008 sec           275                0            0            0   
    2.5507 sec           275                0            0            0   
    2.6008 sec           275                0            0            0   
    2.6507 sec           275                0            0            0   
    2.7008 sec           350                0            0            0   
    2.7507 sec           425                0            0          0.5   
    2.8008 sec           425                0            0          0.5   
    2.8507 sec           500                0            0          0.5   
    2.9008 sec           575                0            0          0.5   
    2.9507 sec           575                0            0          0.5   
    3.0008 sec           650                0            0          0.5   
    3.0507 sec           725                0            0          0.5   
      ⋮

signalTimetable2 = canSignalTimetable(msgTimetable, "EngineData")
signalTimetable2=1147×6 timetable
       Time       PetrolLevel    EngPower    EngForce    IdleRunning    EngTemp    EngSpeed
    __________    ___________    ________    ________    ___________    _______    ________

    2.3002 sec         1            7.5          0            0            0         750   
    2.3502 sec         2            7.5        375            0            0           4   
    2.4002 sec         3            7.5        375            0            0          10   
    2.4502 sec         4            7.5        375            0            0          17   
    2.5002 sec         5            7.5        375            0            0          23   
    2.5502 sec         6            7.5        375            0            0          30   
    2.6002 sec         7            7.5        375            0            0          36   
    2.6502 sec         8            7.5        375            0            0          43   
    2.7002 sec         9              9        450            0            0          50   
    2.7502 sec        10           10.5        525            0            0          59   
    2.8002 sec        10           10.5        525            0            0          69   
    2.8502 sec        11             12        600            0            0          80   
    2.9002 sec        11           13.5        675            0            0          92   
    2.9502 sec        12           13.5        675            0            0         106   
    3.0002 sec        13             15        750            0            0         121   
    3.0502 sec        13           16.5        825            0            0         136   
      ⋮

signalTimetable3 = canSignalTimetable(msgTimetable, "GearBoxInfo")
signalTimetable3=1147×3 timetable
       Time       EcoMode    ShiftRequest    Gear
    __________    _______    ____________    ____

    2.3009 sec       0            0           1  
    2.3508 sec       0            0           1  
    2.4009 sec       0            0           1  
    2.4508 sec       0            0           1  
    2.5009 sec       0            0           1  
    2.5508 sec       0            0           1  
    2.6009 sec       0            0           1  
    2.6508 sec       0            0           1  
    2.7009 sec       0            0           1  
    2.7508 sec       0            0           1  
    2.8009 sec       0            0           1  
    2.8508 sec       0            0           1  
    2.9009 sec       0            0           1  
    2.9508 sec       0            0           1  
    3.0009 sec       0            0           1  
    3.0508 sec       0            0           1  
      ⋮

为了可视化感兴趣的信号,可以绘制信号时间表中的列随时间变化的图,以便进一步分析。

subplot(3, 1, 1)
plot(signalTimetable1.Time, signalTimetable1.CarSpeed, "r")
title("{\itCarSpeed} Signal from {\itABSdata} Message", "FontWeight", "bold")
xlabel("Timestamp")
ylabel("Car Speed")
subplot(3, 1, 2)
plot(signalTimetable2.Time, signalTimetable2.EngSpeed, "b")
title("{\itEngSpeed} Signal from {\itEngineData} Message", "FontWeight", "bold")
xlabel("Timestamp")
ylabel("Engine Speed")
subplot(3, 1, 3)
plot(signalTimetable3.Time, signalTimetable3.Gear, "y")
title("{\itGear} Signal from {\itGearBoxInfo} Message", "FontWeight", "bold")
xlabel("Timestamp")
ylabel("Gear")

Figure contains 3 axes objects. Axes object 1 with title CarSpeed blank Signal blank from blank ABSdata Message, xlabel Timestamp, ylabel Car Speed contains an object of type line. Axes object 2 with title EngSpeed blank Signal blank from blank EngineData Message, xlabel Timestamp, ylabel Engine Speed contains an object of type line. Axes object 3 with title Gear blank Signal blank from blank GearBoxInfo Message, xlabel Timestamp, ylabel Gear contains an object of type line.

配置通道组和通道元数据

此示例的最终目标是将三条感兴趣的报文“ABSdata”、“EngineData”和“GearBoxInfo”解码后的信号数据写回到同一个 MDF 文件的三个新通道组中。这样,原始数据和解码后的数据可以存储在一个文件中。

除了每个时间表中的数据之外,元数据也是重要元素,它可以提供关于测量环境的描述性信息。本节说明如何配置数据附带的元数据,这是写入文件之前的可选准备步骤。

使用函数 mdfAddChannelGroupMetadata 将该特定通道组及其通道的默认或推断元数据添加到每个信号时间表中。

signalTimetable1 = mdfAddChannelGroupMetadata(signalTimetable1);
signalTimetable2 = mdfAddChannelGroupMetadata(signalTimetable2);
signalTimetable3 = mdfAddChannelGroupMetadata(signalTimetable3);

查看每个通道组及其通道的默认元数据。

signalTimetable1.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: ""
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""    ""]
                        ChannelComment: [""    ""    ""    ""]
                           ChannelUnit: [""    ""    ""    ""]
                           ChannelType: [FixedLength    FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64 64]
                  ChannelComponentType: [None    None    None    None]
                ChannelCompositionType: [None    None    None    None]
                     ChannelSourceName: [""    ""    ""    ""]
                     ChannelSourcePath: [""    ""    ""    ""]
                  ChannelSourceComment: [""    ""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0 0]
                     ChannelReadOption: [Missing    Missing    Missing    Missing]

signalTimetable2.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: ""
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""    ""    ""    ""]
                        ChannelComment: [""    ""    ""    ""    ""    ""]
                           ChannelUnit: [""    ""    ""    ""    ""    ""]
                           ChannelType: [FixedLength    FixedLength    FixedLength    FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64 64 64 64]
                  ChannelComponentType: [None    None    None    None    None    None]
                ChannelCompositionType: [None    None    None    None    None    None]
                     ChannelSourceName: [""    ""    ""    ""    ""    ""]
                     ChannelSourcePath: [""    ""    ""    ""    ""    ""]
                  ChannelSourceComment: [""    ""    ""    ""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0 0 0 0]
                     ChannelReadOption: [Missing    Missing    Missing    Missing    Missing    Missing]

signalTimetable3.Properties.CustomProperties
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: ""
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""]
                        ChannelComment: [""    ""    ""]
                           ChannelUnit: [""    ""    ""]
                           ChannelType: [FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64]
                  ChannelComponentType: [None    None    None]
                ChannelCompositionType: [None    None    None]
                     ChannelSourceName: [""    ""    ""]
                     ChannelSourcePath: [""    ""    ""]
                  ChannelSourceComment: [""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0]
                     ChannelReadOption: [Missing    Missing    Missing]

创建一个数组来包含三个报文名称,创建一个元胞数组来包含三个信号时间表。

msgNames = ["ABSdata", "EngineData", "GearBoxInfo"];
TTs = {signalTimetable1, signalTimetable2, signalTimetable3};

TTs 中的每个时间表设置属性 ChannelGroupComment,以指示从其解码信号数据的 CAN 报文的名称。

for ii = 1:numel(TTs)
    TTs{ii}.Properties.CustomProperties.ChannelGroupComment = sprintf("Signal data from CAN message ""%s"".", msgNames(ii));
end

对于每个 CAN 报文,使用此脚本末尾提供的辅助函数 getSignalUnitcanDB 获取每个信号的单位。将每个时间表变量的属性 ChannelUnit 设置为获得的单位。

for ii = 1:numel(msgNames)
    sigNames = TTs{ii}.Properties.VariableNames;
    for jj = 1:numel(sigNames)
        sigUnit = getSignalUnit(canDB, msgNames(ii), sigNames(jj));
        TTs{ii}.Properties.CustomProperties.ChannelUnit(jj) = sigUnit;
    end
end

查看每个通道组及其通道的更新后的元数据。请注意属性 ChannelGroupCommentChannelUnit 中更新后的值。

for ii = 1:numel(TTs)
    TTs{ii}.Properties.CustomProperties
end
ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Signal data from CAN message "ABSdata"."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""    ""]
                        ChannelComment: [""    ""    ""    ""]
                           ChannelUnit: ["N"    ""    ""    "mph"]
                           ChannelType: [FixedLength    FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64 64]
                  ChannelComponentType: [None    None    None    None]
                ChannelCompositionType: [None    None    None    None]
                     ChannelSourceName: [""    ""    ""    ""]
                     ChannelSourcePath: [""    ""    ""    ""]
                  ChannelSourceComment: [""    ""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0 0]
                     ChannelReadOption: [Missing    Missing    Missing    Missing]

ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Signal data from CAN message "EngineData"."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""    ""    ""    ""]
                        ChannelComment: [""    ""    ""    ""    ""    ""]
                           ChannelUnit: ["l"    "kW"    "N"    ""    "degC"    "rpm"]
                           ChannelType: [FixedLength    FixedLength    FixedLength    FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64 64 64 64]
                  ChannelComponentType: [None    None    None    None    None    None]
                ChannelCompositionType: [None    None    None    None    None    None]
                     ChannelSourceName: [""    ""    ""    ""    ""    ""]
                     ChannelSourcePath: [""    ""    ""    ""    ""    ""]
                  ChannelSourceComment: [""    ""    ""    ""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified    Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0 0 0 0]
                     ChannelReadOption: [Missing    Missing    Missing    Missing    Missing    Missing]

ans = 
CustomProperties with properties:

           ChannelGroupAcquisitionName: ""
                   ChannelGroupComment: "Signal data from CAN message "GearBoxInfo"."
                ChannelGroupSourceName: ""
                ChannelGroupSourcePath: ""
             ChannelGroupSourceComment: ""
                ChannelGroupSourceType: Unspecified
             ChannelGroupSourceBusType: Unspecified
    ChannelGroupSourceBusChannelNumber: 0
                    ChannelDisplayName: [""    ""    ""]
                        ChannelComment: [""    ""    ""]
                           ChannelUnit: [""    ""    ""]
                           ChannelType: [FixedLength    FixedLength    FixedLength]
                       ChannelDataType: [RealLittleEndian    RealLittleEndian    RealLittleEndian]
                        ChannelNumBits: [64 64 64]
                  ChannelComponentType: [None    None    None]
                ChannelCompositionType: [None    None    None]
                     ChannelSourceName: [""    ""    ""]
                     ChannelSourcePath: [""    ""    ""]
                  ChannelSourceComment: [""    ""    ""]
                     ChannelSourceType: [Unspecified    Unspecified    Unspecified]
                  ChannelSourceBusType: [Unspecified    Unspecified    Unspecified]
         ChannelSourceBusChannelNumber: [0 0 0]
                     ChannelReadOption: [Missing    Missing    Missing]

使用可自定义的通道组和通道元数据将数据写入 MDF 文件

使用 mdfWrite 函数,将 TTs 中的三个时间表逐个写入 Logging_MDF.mf4。由于 MDF 文件当前有 62 个通道组,因此 TTs{1}TTs{2}TTs{3} 将作为通道组 63、64 和 65 写入文件的末尾。

for ii = 1:numel(TTs)
    mdfWrite("Logging_MDF.mf4", TTs{ii})
end

将 DBC 文件作为附件添加到 MDF 文件中

为了方便地访问 PowerTrain_MDF.dbc 以便将来执行额外的数据解码,您可以使用 mdfAddAttachment 将 DBC 文件作为嵌入附件添加到 MDF 文件中。

mdfAddAttachment("Logging_MDF.mf4", "PowerTrain_MDF.dbc", Embedded=true)

关闭 DBC 文件

通过从工作区中清除 DBC 文件的变量,关闭对 DBC 文件的访问。

clear canDB

辅助函数

function sigUnit = getSignalUnit(canDB, msgName, sigName)
% Look up the unit of a signal in a message from a CAN database. Return the unit as a string.
    msgIdx = find(strcmp({canDB.MessageInfo.Name}, msgName));
    sigIdx = find(strcmp({canDB.MessageInfo(msgIdx).SignalInfo.Name}, sigName));
    sigUnit = string(canDB.MessageInfo(msgIdx).SignalInfo(sigIdx).Units);
end