Используйте файлы DBC в коммуникации CAN

Этот пример показывает вам, как создать, получить и обработать сообщения с помощью информации, хранившей в файлах DBC. Этот пример описывает рабочий процесс для сети CAN, но концепция, продемонстрированная также, применяется к сети CAN FD.

Откройте файл DBC

Открытый файл demoVNT_CANdbFiles.dbc использование canDatabase.

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

             Name: 'demoVNT_CANdbFiles'
             Path: '/tmp/BR2021bd_1751886_255755/mlx_to_docbook2/tpadb915a3/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 просмотреть информацию для EngineRPM сигнала в сообщении EngineMsg, включая тип, порядок байтов, размер и масштабирующиеся значения, которые переводят необработанные сигналы в физические значения.

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

Когда значение записано непосредственно в сигнал, оно переводится, масштабируется и упаковывается в данные о сообщении с помощью определения базы данных. Обратите внимание на изменения значения в Data свойство после нового значения записано в VehicleSpeed сигнал.

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.060755 sec    100     false      {'EngineMsg'        }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.060935 sec    200     false      {'TransmissionMsg'  }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.060938 sec    400     false      {'DoorControlMsg'   }    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.06094 sec     600     false      {'WindowControlMsg' }    {[             0 0 0 0]}      4       {1x1 struct}    false    false 
    0.060942 sec    800     false      {'SunroofControlMsg'}    {[                 0 0]}      2       {1x1 struct}    false    false 
    0.085762 sec    100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.11076 sec     100     false      {'EngineMsg'        }    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.11076 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.16076 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.060755 sec    100     false      {'EngineMsg'}    {[     0 0 0 0 0 0 0 0]}      8       {1x1 struct}    false    false 
    0.085762 sec    100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.11076 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.13576 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.16076 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.18576 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.21074 sec     100     false      {'EngineMsg'}    {[172 129 0 0 50 0 0 0]}      8       {1x1 struct}    false    false 
    0.23576 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.060755 sec          0             250  
    0.085762 sec         50          3569.6  
    0.11076 sec          50          3569.6  
    0.13576 sec          50          3569.6  
    0.16076 sec          50          3569.6  
    0.18576 sec          50          3569.6  
    0.21074 sec          50          3569.6  
    0.23576 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 путем очищения его переменной из рабочей области.

clear db
Для просмотра документации необходимо авторизоваться на сайте