Main Content

传输和接收 CAN 报文

发现已安装的硬件

在本示例中,您将使用 canChannelList 发现系统 CAN 设备,然后使用 canChannel 创建两个 CAN 通道。稍后,您将编辑第一个通道的属性并使用 canMessage 创建一条报文,然后使用 transmit 从第一个通道传输该报文,并使用 receive 在另一个通道上接收该报文。

  1. 获取有关系统上 CAN 硬件设备的信息。

    info = canChannelList
    info =
    
      14×6 table
    
          Vendor              Device           Channel       DeviceModel       ProtocolMode   SerialNumber
       _____________  _______________________  _______  _____________________  _____________  ____________
    
       "MathWorks"    "Virtual 1"                 1     "Virtual"              "CAN, CAN FD"    "0"     
       "MathWorks"    "Virtual 1"                 2     "Virtual"              "CAN, CAN FD"    "0"     
       "Vector"       "VN1610 1"                  1     "VN1610"               "CAN, CAN FD"    "18959"
       "Vector"       "VN1610 1"                  2     "VN1610"               "CAN, CAN FD"    "18959"
       "Vector"       "Virtual 1"                 1     "Virtual"              "CAN, CAN FD"    "0"
       "Vector"       "Virtual 1"                 2     "Virtual"              "CAN, CAN FD"    "0"
       "PEAK-System"  "PCAN-USB Pro"              1     "PCAN-USB Pro"         "CAN, CAN FD"    "0"
       "PEAK-System"  "PCAN-USB Pro"              2     "PCAN-USB Pro"         "CAN, CAN FD"    "0"
       "Kvaser"       "USBcan Professional 1"     1     "USBcan Professional"  "CAN"            "10680"
       "Kvaser"       "USBcan Professional 1"     1     "USBcan Professional"  "CAN"            "10680"
       "Kvaser"       "Virtual 1"                 1     "Virtual"              "CAN, CAN FD"    "0"
       "Kvaser"       "Virtual 1"                 2     "Virtual"              "CAN, CAN FD"    "0"
       "NI"           "9862 CAN/HS (CAN1)"        1     "9862"                 "CAN, CAN FD"    "17F5094"
       "NI"           "9862 CAN/HS (CAN2)"        1     "9862"                 "CAN, CAN FD"    "17F50B2"

注意

要针对硬件 CAN 设备修改此示例,请在两个通道之间建立环回连接。

创建 CAN 通道

创建两个 MathWorks® 虚拟 CAN 通道。

canch1 = canChannel('MathWorks','Virtual 1',1)
canch2 = canChannel('MathWorks','Virtual 1',2)
canch1 = 

  Channel with properties:

   Device Information
            DeviceVendor: 'MathWorks'
                  Device: 'Virtual 1'
      DeviceChannelIndex: 1
      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: []
                UserData: []


canch2 = 

  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: []
                UserData: []

对于每个通道,请注意其初始 Running 值为 0(已停止),其总线速度为 500000

注意

您不能使用同一变量连续创建多个通道。在使用同一变量构造新 CAN 通道之前,请清除任何通道。

您不能创建 CAN 通道对象数组。您创建的每个对象都必须赋给它自己的标量变量。

配置通道属性

您可以通过配置 CAN 通道的属性值来设置其行为。对于本练习,请使用 configBusSpeed 函数将通道 1 的总线速度更改为 250000。

提示

在启动通道之前配置属性值。

  1. 将两个通道的总线速度都更改为 250000,然后查看通道的 BusSpeed 属性以验证设置。

    configBusSpeed(canch1,250000)
    canch1.BusSpeed
    ans =
    
          250000
  2. 您还可以在通道显示中查看更新后的总线速度。

    canch1
    canch1 = 
    
      Channel with properties:
    
       Device Information
                DeviceVendor: 'MathWorks'
                      Device: 'Virtual 1'
          DeviceChannelIndex: 1
          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: 250000
                         SJW: []
                       TSEG1: []
                       TSEG2: []
                NumOfSamples: []
    
       Other Information
                    Database: []
                    UserData: []
  3. 以类似的方式,更改第二个通道的总线速度。

    configBusSpeed(canch2,250000)

启动通道

配置其属性后,启动两个通道。然后查看第一个通道的更新后的状态信息。

start(canch1)
start(canch2)
canch1
canch1 = 

  Channel with properties:

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

   Status Information
                 Running: 1
       MessagesAvailable: 0
        MessagesReceived: 0
     MessagesTransmitted: 0
    InitializationAccess: 1
        InitialTimestamp: 23-May-2019 15:43:40
           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: 250000
                     SJW: []
                   TSEG1: []
                   TSEG2: []
            NumOfSamples: []

   Other Information
                Database: []
                UserData: []
请注意,通道的 Running 属性值现在为 1 (true)。

创建报文

根据需要设置所有属性值并且通道处于运行状态后,即可在 CAN 总线上传输和接收报文。对于本练习,请使用 canch1 传输报文,使用 canch2 接收报文。要传输报文,请创建一个报文对象并将必要的数据打包到报文。

构建具有标准类型 ID (500) 且数据长度为 8 个字节的 CAN 报文。

messageout = canMessage(500,false,8)
messageout = 

  Message with properties:

   Message Identification
    ProtocolMode: 'CAN'
              ID: 500
        Extended: 0
            Name: ''

   Data Details
       Timestamp: 0
            Data: [0 0 0 0 0 0 0 0]
         Signals: []
          Length: 8

   Protocol Flags
           Error: 0
          Remote: 0

   Other Information
        Database: []
        UserData: []

该报文的一些属性指示如下:

  • Error - 逻辑值 0 (false),因为该报文不是错误。

  • Remote - 逻辑值 0 (false),因为该报文不是远程帧。

  • ID - 您指定的 ID。

  • Extended - 逻辑值 0 (false),因为您未指定扩展 ID。

  • Data - 由 0 组成的 uint8 数组,其大小由数据长度指定。

请参阅 canMessage 函数以了解有关其输入参数的详细信息。

打包报文

创建报文后,将必要的数据打包到报文。

使用 pack 函数用以下输入参数对报文进行打包:Data 值为 25,开始位为 0,信号大小为 16,字节顺序使用 little-endian 格式。查看报文 Data 属性以验证设置。

pack(messageout,25,0,16,'LittleEndian')
messageout.Data
ans =

  1×8 uint8 row vector

   25    0    0    0    0    0    0    0

从打包更改的唯一报文属性是 Data。请参阅 pack 函数以了解有关其输入参数的详细信息。

传输报文

现在您可以传输打包的报文。使用 transmit 函数,提供通道 canch1 和报文作为输入参数。

transmit(canch1,messageout)
canch1
canch1 = 

  Channel with properties:

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

   Status Information
                 Running: 1
       MessagesAvailable: 1
        MessagesReceived: 0
     MessagesTransmitted: 1
    InitializationAccess: 1
        InitialTimestamp: 23-May-2019 15:43:40
           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: 250000
                     SJW: []
                   TSEG1: []
                   TSEG2: []
            NumOfSamples: []

   Other Information
                Database: []
                UserData: []

MATLAB® 显示更新后的通道。在“状态信息”部分中,每传输一条报文时,MessagesTransmitted 值都会递增 1。要接收的报文可供总线上的所有设备使用,因此即使对于传输通道,它也会显示在 MessagesAvailable 属性中。

请参阅 transmit 函数以了解有关其输入参数的详细信息。

接收报文

使用 receive 函数接收 canch2 上的可用报文。

  1. 要查看可在此通道上接收的报文,请键入:

    canch2
    canch2 = 
    
      Channel with properties:
    
       Device Information
                DeviceVendor: 'MathWorks'
                      Device: 'Virtual 1'
          DeviceChannelIndex: 2
          DeviceSerialNumber: 0
                ProtocolMode: 'CAN'
    
       Status Information
                     Running: 1
           MessagesAvailable: 1
            MessagesReceived: 0
         MessagesTransmitted: 0
        InitializationAccess: 1
            InitialTimestamp: 23-May-2019 15:43:40
               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: 250000
                         SJW: []
                       TSEG1: []
                       TSEG2: []
                NumOfSamples: []
    
       Other Information
                    Database: []
                    UserData: []

    通道状态信息指示 MessagesAvailable 为 1。

  2. canch2 上接收一条报文,并将其分配给 messagein。短暂的暂停确保报文传输完成。

    messagein = receive(canch2,1)
    messagein = 
    
      Message with properties:
    
       Message Identification
        ProtocolMode: 'CAN'
                  ID: 500
            Extended: 0
                Name: ''
    
       Data Details
           Timestamp: 0.0312
                Data: [25 0 0 0 0 0 0 0]
             Signals: []
              Length: 8
    
       Protocol Flags
               Error: 0
              Remote: 0
    
       Other Information
            Database: []
            UserData: []

    请注意收到的报文的 Data 属性。该属性匹配从 canch1 传输的数据。

    请参阅 receive 函数以了解有关其输入参数的详细信息。

  3. 要检查通道是否收到报文,请查看通道显示。

    canch2
    canch2 = 
    
      Channel with properties:
    
       Device Information
                DeviceVendor: 'MathWorks'
                      Device: 'Virtual 1'
          DeviceChannelIndex: 2
          DeviceSerialNumber: 0
                ProtocolMode: 'CAN'
    
       Status Information
                     Running: 1
           MessagesAvailable: 0
            MessagesReceived: 1
         MessagesTransmitted: 0
        InitializationAccess: 1
            InitialTimestamp: 23-May-2019 15:43:40
               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: 250000
                         SJW: []
                       TSEG1: []
                       TSEG2: []
                NumOfSamples: []
    
       Other Information
                    Database: []
                    UserData: []

    通道状态信息指示 MessagesReceived 为 1,MessagesAvailable 为 0。

解包报文

在您的通道收到报文后,指定如何解包报文并解释报文中的数据。使用 unpack 指定用于解包报文的参数;这些参数应该对应于用于打包的参数。

value = unpack(messagein,0,16,'LittleEndian','int16')
value =

  int16

   25

请参阅 unpack 函数以了解有关其输入参数的详细信息。

保存并加载 CAN 通道

在 CAN 通信会话期间,您可以随时使用 save 函数将 CAN 通道对象保存到一个文件中。

要将 canch1 保存到 MATLAB 文件 mycanch.mat,请键入:

save mycanch.mat canch1

如果已在 MATLAB 文件中保存 CAN 通道,则可以使用 load 函数将该通道加载到 MATLAB 中。例如,要从先前创建的 mycanch.mat 重新加载通道,请键入:

load mycanch.mat

加载的 CAN 通道对象会重新连接到指定的硬件,并将其自身重新配置为保存通道时的设定。

断开通道连接并进行清理

断开已配置的通道连接

当您不再需要与 CAN 总线通信时,请使用 stop 函数断开与您配置的 CAN 通道的连接。

  1. 停止第一个通道。

    stop(canch1)
  2. 检查通道状态。

    canch1
    .
    .
    .
     Status Information
                     Running: 0
           MessagesAvailable: 1
            MessagesReceived: 0
         MessagesTransmitted: 1
  3. 停止第二个通道。

    stop(canch2)
  4. 检查通道状态。

    canch2
    .
    .
    .
     Status Information
                     Running: 0
           MessagesAvailable: 0
            MessagesReceived: 1
         MessagesTransmitted: 0

清理 MATLAB 工作区

如果不再需要这些对象和变量,请使用 clear 命令从 MATLAB 工作区中删除它们。

  1. 清除每个通道。

    clear canch1
    clear canch2
  2. 清除 CAN 报文。

    clear messageout
    clear messagein
  3. 清除解包的值。

    clear value

相关示例

详细信息