Main Content

本页翻译不是最新的。点击此处可查看最新英文版本。

在 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