주요 콘텐츠

이 페이지는 기계 번역을 사용하여 번역되었습니다. 영어 원문을 보려면 여기를 클릭하십시오.

CAN 통신에서 DBC 파일 사용

이 예제는 DBC 파일에 저장된 정보를 사용하여 메시지를 생성, 수신 및 처리하는 방법을 보여줍니다. 이 예시는 CAN 네트워크의 워크플로를 설명하지만, 제시된 개념은 CAN FD 네트워크에도 적용됩니다.

DBC 파일 열기

canDatabase를 사용하여 demoVNT_CANdbFiles.dbc 파일을 엽니다.

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

             Name: 'demoVNT_CANdbFiles'
             Path: 'C:\Users\michellw\OneDrive - MathWorks\Documents\MATLAB\Examples\vnt-ex80654288\demoVNT_CANdbFiles.dbc'
            Nodes: {}
         NodeInfo: [0×0 struct]
         Messages: {5×1 cell}
      MessageInfo: [5×1 struct]
       Attributes: {}
    AttributeInfo: [0×0 struct]
         UserData: []

Messages 속성을 확인하여 이 파일에 정의된 모든 메시지의 이름을 볼 수 있습니다.

db.Messages
ans = 5×1 cell array
    "'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: {2×1 cell}
       SignalInfo: [2×1 struct]
          TxNodes: {0×1 cell}
       Attributes: {}
    AttributeInfo: [0×0 struct]

모든 메시지에 대한 정보를 한 번에 쿼리할 수도 있습니다.

messageInfo(db)
ans=5×1 struct array with fields:
       'DoorControlMsg'    'CAN'    ''    400    0    [ ]    8    8    0    2×1 cell    2×1 struct    0×1 cell    0×0 cell    0×0 struct
            'EngineMsg'    'CAN'    ''    100    0    [ ]    8    8    0    2×1 cell    2×1 struct    0×1 cell    0×0 cell    0×0 struct
    'SunroofControlMsg'    'CAN'    ''    800    0    [ ]    2    2    0    1×1 cell    1×1 struct    0×1 cell    0×0 cell    0×0 struct
      'TransmissionMsg'    'CAN'    ''    200    0    [ ]    8    8    0    1×1 cell    1×1 struct    0×1 cell    0×0 cell    0×0 struct
     'WindowControlMsg'    'CAN'    ''    600    0    [ ]    4    4    0    2×1 cell    2×1 struct    0×1 cell    0×0 cell    0×0 struct

신호 정보 보기

메시지 EngineMsg 내 신호 EngineRPM의 정보를 확인하려면 signalInfo를 사용하십시오. 여기에는 유형, 바이트 순서, 크기 및 원시 신호를 물리적 값으로 변환하는 스케일링 값이 포함됩니다.

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: [0×1 struct]
      Multiplexor: 0
      Multiplexed: 0
    MultiplexMode: 0
          RxNodes: {0×1 cell}
       Attributes: {}
    AttributeInfo: [0×0 struct]

메시지 EngineMsg 내의 모든 신호에 대한 정보를 한 번에 쿼리할 수도 있습니다.

signalInfo(db, "EngineMsg")
ans=2×1 struct array with fields:
       'EngineRPM'    ''     0    32    'LittleEndian'    0    'Integer'    'uint32'    0.1000    250    250          9500    'rpm'    0×1 struct    0    0    0    0×1 cell    0×0 cell    0×0 struct
    'VehicleSpeed'    ''    32    32    'LittleEndian'    0    'Integer'    'uint32'         1      0      0    4.2950e+09    'mph'    0×1 struct    0    0    0    0×1 cell    0×0 cell    0×0 struct
      ⋮

데이터베이스 정의를 사용하여 메시지 생성하기

데이터베이스와 메시지 이름 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: [1×1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1×1 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: [1×1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1×1 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: [1×1 struct]
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: [1×1 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: [0×0 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: [1×1 can.Database]
                UserData: []

메시지 수신하기

채널을 시작하고, 메시지 트래픽을 생성하며, 물리적 메시지 디코딩을 통해 메시지를 수신합니다.

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

수신된 메시지의 처음 몇 줄을 확인합니다.

head(rxMsg)
ans=8×8 timetable
    0.13103 sec    100    0    'EngineMsg'    [0,0,0,0,0,0,0,0]    8    1×1 struct    0    0
    0.13103 sec    200    0    'TransmissionMsg'    [0,0,0,0,0,0,0,0]    8    1×1 struct    0    0
    0.13104 sec    400    0    'DoorControlMsg'    [0,0,0,0,0,0,0,0]    8    1×1 struct    0    0
    0.13104 sec    600    0    'WindowControlMsg'    [0,0,0,0]    4    1×1 struct    0    0
    0.13105 sec    800    0    'SunroofControlMsg'    [0,0]    2    1×1 struct    0    0
    0.15598 sec    100    0    'EngineMsg'    [0,0,0,0,0,0,0,0]    8    1×1 struct    0    0
    0.18 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0
    0.18001 sec    200    0    'TransmissionMsg'    [4,0,0,0,0,0,0,0]    8    1×1 struct    0    0

수신 채널을 중지하고 작업 공간에서 제거하십시오.

stop(rxCh);
clear rxCh

수신된 메시지 검토하기

수신된 메시지를 검사하여 적용된 데이터베이스 디코딩을 확인하십시오.

rxMsg(10, :)
ans=1×8 timetable
    0.22994 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0

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
    0.13103 sec    100    0    'EngineMsg'    [0,0,0,0,0,0,0,0]    8    1×1 struct    0    0
    0.15598 sec    100    0    'EngineMsg'    [0,0,0,0,0,0,0,0]    8    1×1 struct    0    0
    0.18 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0
    0.20597 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0
    0.22994 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0
    0.25695 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0
    0.27995 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0
    0.30597 sec    100    0    'EngineMsg'    [172,129,0,0,50,0,0,0]    8    1×1 struct    0    0

물리적 신호 값 플로팅하기

canSignalTimetable를 사용하여 메시지 EngineMsg의 신호 데이터를 신호 타임테이블로 리패키징합니다.

signalTimetable = canSignalTimetable(rxMsg, "EngineMsg");

신호 타임테이블의 처음 몇 줄을 확인하십시오.

head(signalTimetable)
ans=8×2 timetable
    0.13103 sec    0    250
    0.15598 sec    0    250
    0.18 sec    50    3.5696e+03
    0.20597 sec    50    3.5696e+03
    0.22994 sec    50    3.5696e+03
    0.25695 sec    50    3.5696e+03
    0.27995 sec    50    3.5696e+03
    0.30597 sec    50    3.5696e+03

시간에 따른 신호 VehicleSpeed의 값을 그래프로 표시하십시오.

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

DBC 파일 닫기

작업 공간에서 DBC 파일의 변수를 지워 해당 파일에 대한 액세스를 종료하십시오.

clear db