传输和接收 CAN 报文
发现已安装的硬件
在本示例中,您将使用 canChannelList
发现系统 CAN 设备,然后使用 canChannel
创建两个 CAN 通道。稍后,您将编辑第一个通道的属性并使用 canMessage
创建一条报文,然后使用 transmit
从第一个通道传输该报文,并使用 receive
在另一个通道上接收该报文。
获取有关系统上 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。
提示
在启动通道之前配置属性值。
将两个通道的总线速度都更改为
250000
,然后查看通道的BusSpeed
属性以验证设置。configBusSpeed(canch1,250000) canch1.BusSpeed
ans = 250000
您还可以在通道显示中查看更新后的总线速度。
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: []
以类似的方式,更改第二个通道的总线速度。
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
上的可用报文。
要查看可在此通道上接收的报文,请键入:
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。在
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
函数以了解有关其输入参量的详细信息。要检查通道是否收到报文,请查看通道显示。
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 通道的连接。
停止第一个通道。
stop(canch1)
检查通道状态。
canch1
. . . Status Information Running: 0 MessagesAvailable: 1 MessagesReceived: 0 MessagesTransmitted: 1
停止第二个通道。
stop(canch2)
检查通道状态。
canch2
. . . Status Information Running: 0 MessagesAvailable: 0 MessagesReceived: 1 MessagesTransmitted: 0
清理 MATLAB 工作区
如果不再需要这些对象和变量,请使用 clear
命令从 MATLAB 工作区中删除它们。
清除每个通道。
clear canch1 clear canch2
清除 CAN 报文。
clear messageout clear messagein
清除解包的值。
clear value