传输和接收 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.Dataans = 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