Этот пример показывает вам, как создать, получить и обработать сообщения с помощью информации, хранившей в файлах DBC. Этот пример описывает рабочий процесс для сети CAN, но концепция, продемонстрированная также, применяется к сети CAN FD.
Открытый файл 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")
Закройте доступ к файлу DBC путем очищения его переменной из рабочей области.
clear db