Main Content

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

在 CAN 通信中使用 DBC 文件

以下示例说明如何使用存储在 DBC 文件中的信息创建、接收和处理报文。此示例说明 CAN 网络的工作流,但所展示的概念也适用于 CAN FD 网络。

打开 DBC 文件

使用 canDatabase 打开文件 demoVNT_CANdbFiles.dbc

db = canDatabase("demoVNT_CANdbFiles.dbc")
db = 
  Database with properties:

             Name: 'demoVNT_CANdbFiles'
             Path: '/tmp/Bdoc22a_1880208_151076/tp5e0c0350/vnt-ex80654288/demoVNT_CANdbFiles.dbc'
        UTF8_File: '/tmp/Bdoc22a_1880208_151076/tp5e0c0350/vnt-ex80654288/demoVNT_CANdbFiles.dbc'
            Nodes: {}
         NodeInfo: [0x0 struct]
         Messages: {5x1 cell}
      MessageInfo: [5x1 struct]
       Attributes: {}
    AttributeInfo: [0x0 struct]
         UserData: []

请检查 Messages 属性,以查看此文件中定义的所有报文的名称。

db.Messages
ans = 5x1 cell
    {'DoorControlMsg'   }
    {'EngineMsg'        }
    {'SunroofControlMsg'}
    {'TransmissionMsg'  }
    {'WindowControlMsg' }

查看报文信息

使用 messageInfo 查看报文 EngineMsg 的信息,包括标识符、数据长度和信号列表。

messageInfo(db, "EngineMsg")
ans = struct with fields:
             Name: 'EngineMsg'
     ProtocolMode: 'CAN'
          Comment: ''
               ID: 100
         Extended: 0
            J1939: []
           Length: 8
              DLC: 8
              BRS: 0
          Signals: {2x1 cell}
       SignalInfo: [2x1 struct]
          TxNodes: {0x1 cell}
       Attributes: {}
    AttributeInfo: [0x0 struct]

您还可以一次查询所有报文的信息。

messageInfo(db)
ans=5×1 struct array with fields:
    Name
    ProtocolMode
    Comment
    ID
    Extended
    J1939
    Length
    DLC
    BRS
    Signals
    SignalInfo
    TxNodes
    Attributes
    AttributeInfo

查看信号信息

使用 signalInfo 查看报文 EngineMsg 中信号 EngineRPM 的信息,包括用于将原始信号转换为物理值的类型、字节顺序、大小和缩放值。

signalInfo(db, "EngineMsg", "EngineRPM")
ans = struct with fields:
             Name: 'EngineRPM'
          Comment: ''
         StartBit: 0
       SignalSize: 32
        ByteOrder: 'LittleEndian'
           Signed: 0
        ValueType: 'Integer'
            Class: 'uint32'
           Factor: 0.1000
           Offset: 250
          Minimum: 250
          Maximum: 9500
            Units: 'rpm'
       ValueTable: [0x1 struct]
      Multiplexor: 0
      Multiplexed: 0
    MultiplexMode: 0
          RxNodes: {0x1 cell}
       Attributes: {}
    AttributeInfo: [0x0 struct]

您还可以一次查询报文 EngineMsg 中所有信号的信息。

signalInfo(db, "EngineMsg")
ans=2×1 struct array with fields:
    Name
    Comment
    StartBit
    SignalSize
    ByteOrder
    Signed
    ValueType
    Class
    Factor
    Offset
    Minimum
    Maximum
    Units
    ValueTable
    Multiplexor
    Multiplexed
    MultiplexMode
    RxNodes
    Attributes
    AttributeInfo
      ⋮

使用数据库定义创建报文

通过指定要应用数据库定义的数据库和报文名称 EngineMsg 来创建新报文。此报文中的 CAN 信号除以原始数据字节表示外,还以工程单位来表示。

msgEngineInfo = canMessage(db, "EngineMsg")
msgEngineInfo = 
  Message with properties:

   Message Identification
    ProtocolMode: 'CAN'
              ID: 100
        Extended: 0
            Name: 'EngineMsg'

   Data Details
       Timestamp: 0
            Data: [0 0 0 0 0 0 0 0]
         Signals: [1x1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1x1 can.Database]
        UserData: []

查看信号信息

使用 Signals 属性查看此报文的信号值。您可以直接对这些信号进行写入和读取,以打包和解包报文中的数据。

msgEngineInfo.Signals
ans = struct with fields:
    VehicleSpeed: 0
       EngineRPM: 250

更改信号信息

直接写入信号 EngineRPM 以更改其值。

msgEngineInfo.Signals.EngineRPM = 5500.25
msgEngineInfo = 
  Message with properties:

   Message Identification
    ProtocolMode: 'CAN'
              ID: 100
        Extended: 0
            Name: 'EngineMsg'

   Data Details
       Timestamp: 0
            Data: [23 205 0 0 0 0 0 0]
         Signals: [1x1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1x1 can.Database]
        UserData: []

读回当前信号值,注意 EngineRPM 已用写入的值更新。

msgEngineInfo.Signals
ans = struct with fields:
    VehicleSpeed: 0
       EngineRPM: 5.5003e+03

当值直接写入信号时,它会转换、缩放,并使用数据库定义打包到报文数据中。请注意在向 VehicleSpeed 信号写入新值后,Data 属性中的值变化。

msgEngineInfo.Signals.VehicleSpeed = 70.81
msgEngineInfo = 
  Message with properties:

   Message Identification
    ProtocolMode: 'CAN'
              ID: 100
        Extended: 0
            Name: 'EngineMsg'

   Data Details
       Timestamp: 0
            Data: [23 205 0 0 71 0 0 0]
         Signals: [1x1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1x1 can.Database]
        UserData: []

msgEngineInfo.Signals
ans = struct with fields:
    VehicleSpeed: 71
       EngineRPM: 5.5003e+03

接收具有数据库信息的报文

将数据库连接到 CAN 通道,该通道接收报文以自动将数据库定义应用于传入报文。数据库仅解码已定义的报文。所有其他报文都以其原始形式接收。

rxCh = canChannel("MathWorks", "Virtual 1", 2);
rxCh.Database = db
rxCh = 
  Channel with properties:

   Device Information
            DeviceVendor: 'MathWorks'
                  Device: 'Virtual 1'
      DeviceChannelIndex: 2
      DeviceSerialNumber: 0
            ProtocolMode: 'CAN'

   Status Information
                 Running: 0
       MessagesAvailable: 0
        MessagesReceived: 0
     MessagesTransmitted: 0
    InitializationAccess: 1
        InitialTimestamp: [0x0 datetime]
           FilterHistory: 'Standard ID Filter: Allow All | Extended ID Filter: Allow All'

   Channel Information
               BusStatus: 'N/A'
              SilentMode: 0
         TransceiverName: 'N/A'
        TransceiverState: 'N/A'
       ReceiveErrorCount: 0
      TransmitErrorCount: 0
                BusSpeed: 500000
                     SJW: []
                   TSEG1: []
                   TSEG2: []
            NumOfSamples: []

   Other Information
                Database: [1x1 can.Database]
                UserData: []

接收报文

启动通道,生成一些报文流,然后通过物理报文解码来接收报文。

start(rxCh);
generateMsgsDb();
rxMsg = receive(rxCh, Inf, "OutputFormat", "timetable");

查看接收到的报文的前几行。

head(rxMsg)
ans=8×8 timetable
        Time        ID     Extended            Name                       Data              Length      Signals       Error    Remote
    ____________    ___    ________    _____________________    ________________________    ______    ____________    _____    ______

    0.05319 sec     100     false      {'EngineMsg'        }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.053209 sec    200     false      {'TransmissionMsg'  }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.053235 sec    400     false      {'DoorControlMsg'   }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.053243 sec    600     false      {'WindowControlMsg' }    {[             0 0 0 0]}      4       {1x1 struct}    false    false 
    0.053248 sec    800     false      {'SunroofControlMsg'}    {[                 0 0]}      2       {1x1 struct}    false    false 
    0.078179 sec    100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.10314 sec     100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.10314 sec     200     false      {'TransmissionMsg'  }    {[     4 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 

停止接收通道并将其从工作区中清除。

stop(rxCh);
clear rxCh

检查收到的报文

检查收到的报文以查看应用的数据库解码。

rxMsg(10, :)
ans=1×8 timetable
       Time        ID     Extended        Name                   Data              Length      Signals       Error    Remote
    ___________    ___    ________    _____________    ________________________    ______    ____________    _____    ______

    0.15312 sec    100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 

rxMsg.Signals{10}
ans = struct with fields:
    VehicleSpeed: 50
       EngineRPM: 3.5696e+03

提取指定报文的所有实例

提取报文 EngineMsg 的所有实例。

allMsgEngine = rxMsg(strcmpi("EngineMsg", rxMsg.Name), :);

查看此特定报文的前几个实例。

head(allMsgEngine)
ans=8×8 timetable
        Time        ID     Extended        Name                   Data              Length      Signals       Error    Remote
    ____________    ___    ________    _____________    ________________________    ______    ____________    _____    ______

    0.05319 sec     100     false      {'EngineMsg'}    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.078179 sec    100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.10314 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.12812 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.15312 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.17812 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.20311 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.22814 sec     100     false      {'EngineMsg'}    {[177 131 0 0 55 0 0 0]}      8       {1x1 struct}    false    false 

绘制物理信号值

使用 canSignalTimetable 将报文 EngineMsg 中的信号数据重新打包为一个信号时间表。

signalTimetable = canSignalTimetable(rxMsg, "EngineMsg");

查看信号时间表的前几行。

head(signalTimetable)
ans=8×2 timetable
        Time        VehicleSpeed    EngineRPM
    ____________    ____________    _________

    0.05319 sec           0             250  
    0.078179 sec         50          3569.6  
    0.10314 sec          50          3569.6  
    0.12812 sec          50          3569.6  
    0.15312 sec          50          3569.6  
    0.17812 sec          50          3569.6  
    0.20311 sec          50          3569.6  
    0.22814 sec          55          3621.3  

绘制信号 VehicleSpeed 随时间变化的值。

plot(signalTimetable.Time, signalTimetable.VehicleSpeed)
title("Vehicle Speed from EngineMsg", "FontWeight", "bold")
xlabel("Timestamp")
ylabel("Vehicle Speed")

Figure contains an axes object. The axes object with title Vehicle Speed from EngineMsg contains an object of type line.

关闭 DBC 文件

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

clear db