0

I am working with the STM8AF5286UDY and am trying to set up a CAN interface. For programming, I use the standard peripheral library. At the moment, my CAN interface works fine. The only thing, which does not work, is filtering.

I use extended IDs and want to get all IDs from 0x18FEC100 to 0x18FEC999. My code looks as follows:

/* CAN filter init */

 CAN_FilterNumber = CAN_FilterNumber_0;

 CAN_FilterActivation = ENABLE;

 CAN_FilterMode = CAN_FilterMode_IdMask;

 CAN_FilterScale = CAN_FilterScale_32Bit;

 CAN_FilterID1=0x18FEC101;

 CAN_FilterID2=0;

 CAN_FilterID3=0;

 CAN_FilterID4=0;

 CAN_FilterIDMask1=0x1FFFF000;

 CAN_FilterIDMask2=0;

 CAN_FilterIDMask3=0;

 CAN_FilterIDMask4=0;  

 CAN_FilterInit(CAN_FilterNumber, CAN_FilterActivation, CAN_FilterMode, 
         CAN_FilterScale,CAN_FilterID1, CAN_FilterID2, CAN_FilterID3,
         CAN_FilterID4,CAN_FilterIDMask1, CAN_FilterIDMask2, 
         CAN_FilterIDMask3, CAN_FilterIDMask4);

I would appreciate any help! Thank you!

EDIT: In my initial code, I forgot to include IDE and RTR at addressing. Also, in the library, each address and mask is an 8-bit value. Therefore, I have changed my code to the following:

/* CAN filter init */
  CAN_FilterNumber = CAN_FilterNumber_2;
  CAN_FilterActivation = ENABLE;
  CAN_FilterMode = CAN_FilterMode_IdMask; 
  CAN_FilterScale = CAN_FilterScale_32Bit; 
  CAN_FilterID1=0xc7;  
  CAN_FilterID2=0xed;
  CAN_FilterID3=0x02;
  CAN_FilterID4=0x02;
  CAN_FilterIDMask1=0xFF; 
  CAN_FilterIDMask2=0xE7; 
  CAN_FilterIDMask3=0xE0;
  CAN_FilterIDMask4=0x00; 
  CAN_FilterInit(CAN_FilterNumber, CAN_FilterActivation, CAN_FilterMode, 
                 CAN_FilterScale,CAN_FilterID1, CAN_FilterID2, CAN_FilterID3,
                 CAN_FilterID4,CAN_FilterIDMask1, CAN_FilterIDMask2, 
                 CAN_FilterIDMask3, CAN_FilterIDMask4);

This filter works for the first 16-bit, so at using 0x18FEC101 it filters the 0x18FE. Somehow, it does not work for the other 16-bit.

In the library, the following code is used for writing the addresses and masks in the filter bank at 32-bit:

else if (CAN_FilterScale == CAN_FilterScale_32Bit)
    {
      CAN->Page.Filter.FR01 = CAN_FilterID1;
      CAN->Page.Filter.FR02 = CAN_FilterID2;
      CAN->Page.Filter.FR03 = CAN_FilterID3;
      CAN->Page.Filter.FR04 = CAN_FilterID4;
      CAN->Page.Filter.FR05 = CAN_FilterIDMask1;
      CAN->Page.Filter.FR06 = CAN_FilterIDMask2;
      CAN->Page.Filter.FR07 = CAN_FilterIDMask3;
      CAN->Page.Filter.FR08 = CAN_FilterIDMask4;
    }

Are there any ideas, what my mistake might be? Thanks!

Pet
  • 1
  • 1

2 Answers2

1

Mask filtering works bitwise. So you can't create a filter to accept values between 0x18FEC100 - 0x18FEC999. You need to think binary.

In the filter mask registers, 1 means "must match" and 0 means "don't care".

ID = 0x18FEC101 and Mask = 0x1FFFF000 means that it will accept values between 0x18FEC000 - 0x18FECFFF as the filter won't care the least significant 12 bits.

However, the process is further complicated by the bit arrangement of the hardware registers. Be aware that RTR & IDE bits are also included in the filter registers. I don't know if the standard peripheral library handles this but probably not. You probably need to manually arrange the bits to determine the correct register values. In the reference manual (RM0016), refer to Figure 148.

Tagli
  • 2,412
  • 2
  • 11
  • 14
  • Thanks for your reply! I totally forgot about the RTR & IDE bits. I changed my code and it works at least better than before. I can filter the first 16 bit of the addresses, so up to 0x18FE, but somehow my messages can't pass, if I add the next 4 bit, so the "C" to the filter... Do you have any idea, any that might happen? – Pet Feb 19 '20 at 14:11
  • The current code looks like this (although posting it might be useless without the reference manual): CAN_FilterNumber = CAN_FilterNumber_2; CAN_FilterActivation = ENABLE; CAN_FilterMode = CAN_FilterMode_IdMask; CAN_FilterScale = CAN_FilterScale_32Bit; CAN_FilterID1=0xc7; CAN_FilterID2=0xed; CAN_FilterID3=0x02; CAN_FilterID4=0x02; CAN_FilterIDMask1=0xFF; CAN_FilterIDMask2=0xE7; CAN_FilterIDMask3=0xE0; CAN_FilterIDMask4=0x00; – Pet Feb 19 '20 at 14:14
  • I guess library variables don't match with the hardware register names. In 32 bit mode, you can have only 1 ID and 1 mask for each filter, and these are 32 bit variables. Populate only `CAN_FilterID1` & `CAN_FilterIDMask1` with 32 bit variables, but also consider the positions of RTR & IDE bits. Also, check library manual too. – Tagli Feb 19 '20 at 15:55
  • If I am not mistaken, those should match. In case of using 32 bit, the program writes each ID or Mask in the corresponding bank. else if (CAN_FilterScale == CAN_FilterScale_32Bit) { CAN->Page.Filter.FR01 = CAN_FilterID1; CAN->Page.Filter.FR02 = CAN_FilterID2; CAN->Page.Filter.FR03 = CAN_FilterID3; CAN->Page.Filter.FR04 = CAN_FilterID4; CAN->Page.Filter.FR05 = CAN_FilterIDMask1; CAN->Page.Filter.FR06 = CAN_FilterIDMask2; CAN->Page.Filter.FR07 = CAN_FilterIDMask3; CAN->Page.Filter.FR08 = CAN_FilterIDMask4; } – Pet Feb 20 '20 at 11:04
0

The code I posted (edited version) works now. Turns out I had a problem calculating the addresses by hand.

Thank you @Tagli.

Pet
  • 1
  • 1