Pet
Pet

Reputation: 1

STM8A CAN Filtering in Standard Peripheral Library

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!

Upvotes: 0

Views: 562

Answers (2)

Pet
Pet

Reputation: 1

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

Thank you @Tagli.

Upvotes: 0

Tagli
Tagli

Reputation: 2592

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.

Upvotes: 1

Related Questions