在 CAN 通信中使用报文过滤器
以下示例说明如何使用 CAN 报文过滤器以仅允许包含指定标识符的报文通过通道。它使用以环回配置形式连接的 MathWorks® 虚拟 CAN 通道。此示例说明 CAN 网络的工作流,但所展示的概念也适用于 CAN FD 网络。
创建传输和接收通道
创建一个用于传输报文的通道和另一个用于接收报文的通道。稍后会对接收通道设置过滤器。
txCh = canChannel("MathWorks", "Virtual 1", 1)
txCh = 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: []
rxCh = canChannel("MathWorks", "Virtual 1", 2)
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: [] UserData: []
创建报文
创建一些要多次发送到接收通道的报文,它们将会在此示例中多次使用请注意,其中一条报文有一个扩展标识符。
txMsgs(1) = canMessage(250, false, 8); txMsgs(2) = canMessage(500, false, 8); txMsgs(3) = canMessage(1000, false, 8); txMsgs(4) = canMessage(1500, true, 8); txMsgs(5) = canMessage(2000, false, 8);
在不使用过滤器的情况下接收报文
将通道设置为在线状态,在一个通道上传输报文,在另一个通道上接收。请注意,所有发送的报文都会接收到。默认情况下,新创建的未配置过滤器的通道接收所有标准和扩展标识符。
start(rxCh); start(txCh); transmit(txCh, txMsgs); pause(0.5); rxMsgs1 = receive(rxCh, Inf, "OutputFormat", "timetable")
rxMsgs1=5×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ____ ________ __________ ___________________ ______ ____________ _____ ______
0.038957 sec 250 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.038959 sec 500 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.038961 sec 1000 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.038963 sec 1500 true {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.038964 sec 2000 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
停止接收和传输通道。
stop(rxCh); stop(txCh);
绘制收到的报文的标识符,可以看到通道接收了所有发出的报文。
plot(1, rxMsgs1.ID, "x") h_gca = gca; h_gca.XTick = 0:1:2; h_gca.XTickLabel = ["", "Transmit 1", ""]; axis([0 2 0 2047]) xlabel("Message Transmits") ylabel("CAN Identifiers")
使用标识符过滤器接收报文
使用 filterAllowOnly
命令来只接收由 CAN 标识符和标识符类型指定的报文。将接收通道配置为仅接收具有标准标识符 500 和 2000 的报文。
filterAllowOnly(rxCh, [500 2000], "Standard");
显示通道的 FilterHistory
属性以查看报文过滤器的配置状态。
rxCh.FilterHistory
ans = 'Standard ID Filter: Allow Only | Extended ID Filter: Allow All'
再次将报文传输到接收通道。请注意,这次收到的报文少了几条。
start(rxCh); start(txCh); transmit(txCh, txMsgs); pause(0.5); rxMsgs2 = receive(rxCh, Inf, "OutputFormat", "timetable")
rxMsgs2=3×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ____ ________ __________ ___________________ ______ ____________ _____ ______
0.037472 sec 500 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.037473 sec 1500 true {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.037474 sec 2000 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
停止接收和传输通道。
stop(rxCh); stop(txCh);
将新接收的数据添加到图中,查看哪些报文通过了过滤器。具有扩展标识符 1500 的消息未被过滤器阻止,因为过滤器仅针对标准标识符进行了配置。
plot(1, rxMsgs1.ID, "x", 2, rxMsgs2.ID, "x"); h_gca = gca; h_gca.XTick = 0:1:3; h_gca.XTickLabel = ["", "Transmit 1", "Transmit 2", ""]; axis([0 3 0 2047]) xlabel("Message Transmits") ylabel("CAN Identifiers")
重置报文过滤器
使用 filterAllowAll
命令将报文过滤器重置为默认状态,以便允许所有标准标识符。
filterAllowAll(rxCh, "Standard");
显示通道的 FilterHistory
属性以查看报文过滤器的配置状态。
rxCh.FilterHistory
ans = 'Standard ID Filter: Allow All | Extended ID Filter: Allow All'
第三次传输和接收,可以看到所有报文再次通过过滤器并被接收通道接收。
start(rxCh); start(txCh); transmit(txCh, txMsgs); pause(0.5); rxMsgs3 = receive(rxCh, Inf, "OutputFormat", "timetable")
rxMsgs3=5×8 timetable
Time ID Extended Name Data Length Signals Error Remote
____________ ____ ________ __________ ___________________ ______ ____________ _____ ______
0.037884 sec 250 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.037885 sec 500 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.037885 sec 1000 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.037888 sec 1500 true {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
0.037888 sec 2000 false {0×0 char} {[0 0 0 0 0 0 0 0]} 8 {0×0 struct} false false
停止接收和传输通道。
stop(rxCh); stop(txCh);
将新数据添加到绘图中,观察第一次和第三次传输是相同的,因为报文过滤器在这两种情形下均为完全开放。
plot(1, rxMsgs1.ID, "x", 2, rxMsgs2.ID, "x", 3, rxMsgs3.ID, "x") h_gca = gca; h_gca.XTick = 0:1:4; h_gca.XTickLabel = ["", "Transmit 1", "Transmit 2", "Transmit 3", ""]; axis([0 4 0 2047]) xlabel("Message Transmits") ylabel("CAN Identifiers")
在具有名称过滤器的情况下接收报文
在使用 DBC 文件时,filterAllowOnly
命令也可以按名称过滤报文。仅允许名称为 EngineMsg
的报文。
db = canDatabase("demoVNT_CANdbFiles.dbc"); rxCh.Database = db; filterAllowOnly(rxCh, "EngineMsg"); rxCh.FilterHistory
ans = 'Standard ID Filter: Allow Only | Extended ID Filter: Allow All'
阻止特定标识符类型的所有报文
您可使用 filterBlockAll
命令轻松设置过滤器以阻止所有标准或扩展标识符类型的报文。阻止所有具有扩展标识符的报文。
filterBlockAll(rxCh, "Extended");
rxCh.FilterHistory
ans = 'Standard ID Filter: Allow Only | Extended ID Filter: Block All'
停止通道
停止接收和传输通道,并从工作区中清除它们。
stop(rxCh); stop(txCh); clear rxCh txCh
关闭 DBC 文件
通过从工作区中清除 DBC 文件的变量,关闭对该 DBC 文件的访问。
clear db