Skip to main content
Associate II
December 10, 2024
Solved

Struggling with CAN Filter

Dear Community,

 

Once again I am struggling with CAN Filters for extended IDs using CAN2 on a STM32F765.

I have the ID 0x010100 and the filter should look like 0xXX0101XX where the X hex should be ignored.

One of my early approaches:

uint32_t filter_id = 0x010100;
uint32_t filter_mask = 0x1F0000FF;

CAN_FilterTypeDef can_addr_filter;
can_addr_filter.FilterActivation = CAN_FILTER_ENABLE;
can_addr_filter.FilterFIFOAssignment = CAN_FILTER_FIFO0;
can_addr_filter.FilterBank = 0;
can_addr_filter.SlaveStartFilterBank = 0;
can_addr_filter.FilterMode = CAN_FILTERMODE_IDMASK;
can_addr_filter.FilterScale = CAN_FILTERSCALE_32BIT;

can_addr_filter.FilterIdHigh = filter_id << 3; //Tried different shifts, didn't worked
can_addr_filter.FilterIdLow = 0;

can_addr_filter.FilterMaskIdHigh = filter_mask << 3; //Tried different shifts, didn't worked
can_addr_filter.FilterMaskIdHigh = 0;

if(HAL_CAN_ConfigFilter(&hcan2, &can_addr_filter) != HAL_OK)
{
 error_handler(CAN_HW_ERROR);
 return;
}

When sending a message to 0x010112 it works as expected

But when sending a message to 0x010013 it works against my expectations

Sending a message to 0x020112 does not work as expected.

Using different FilterIdHigh and FilterIdLow aswell different FilterMaskIdHigh and FilterMaskIdLow settings I can't get it working.

I probably made a *** mistake at one point...


I would be very grateful if someone could help me so that I can finally understand the CAN filter and find my error. Preferably as an explanation for a 5 year old so I don't have to ask again about filters.

 

Warmest regards
Anno

This topic has been closed for replies.
mƎALLEm
mƎALLEmBest answer
ST Technical Moderator
December 10, 2024

Hello,

For filter mask mode when you set a bit to 1 in the mask it means that this bit needs to match the ID, if 0, that bit is don't care.

So as I understood you want to receive the pattern in the form of 0xXX0101XX in Extended ID:
So you need to have the ID value set to 0x00010100 and mask value 0x00FFFF00.
If you AND bit wise both you will get something in the form of 0xXX0101XX.

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.

8 replies

mƎALLEm
mƎALLEmBest answer
ST Technical Moderator
December 10, 2024

Hello,

For filter mask mode when you set a bit to 1 in the mask it means that this bit needs to match the ID, if 0, that bit is don't care.

So as I understood you want to receive the pattern in the form of 0xXX0101XX in Extended ID:
So you need to have the ID value set to 0x00010100 and mask value 0x00FFFF00.
If you AND bit wise both you will get something in the form of 0xXX0101XX.

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
Tesla DeLorean
Guru
December 10, 2024

>>Preferably as an explanation for a 5 year old so I don't have to ask again about filters.

Would suggest looking at the Picture/Diagram in the RM showing the relationship between the bits in the register and those on the wire you wish to identify. Randomly shifting won't get you to the answer, and as I recall the Extended ID spans more bits and probably not contiguous, as the two registers are 16-bit wide

The test is of the form (Bits in Register & FilterMask) == FilterID

Where the high order bit in the high order register is first over the wire

f7canbits.jpg

This is for the NORMAL 11-Bit ID (observe where the 5 bit shift comes from above)

 

void CanFilterConfig ( uint8_t filterNum, uint8_t fifoNum, uint32_t canId )
{
 CAN_FilterTypeDef sFilterConfig;

 sFilterConfig.FilterBank = filterNum;
 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
 sFilterConfig.FilterIdHigh = canId << 5; // Comparator
 sFilterConfig.FilterIdLow = 0x00000000U;
 sFilterConfig.FilterMaskIdHigh = 0x7FFU << 5; // Mask 11-bit
 sFilterConfig.FilterMaskIdLow = 0;
 sFilterConfig.FilterFIFOAssignment = fifoNum;
 sFilterConfig.FilterActivation = ENABLE;
 sFilterConfig.SlaveStartFilterBank = 14; // CAN1 / CAN2 split for FilterBank

 (void)HAL_CAN_ConfigFilter( &hcan, &sFilterConfig );
}

 

 

 

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
AnnoAuthor
Associate II
December 11, 2024

Hello again,

thank you @mƎALLEm and @Tesla DeLorean for your quick responses.

I changed my filter mask to 0x00FFFF00 as mentioned and had a closer look at the diagram. 

As I understand it now, this would be the correct way:

 

 

uint32_t filter_id = 0x010100;
uint32_t filter_mask = 0x00FFFF00;
/* .. */
can_addr_filter.FilterIdHigh = (filter_id >> 13) & 0xFFFF;
can_addr_filter.FilterIdLow = ((filter_id & 0x1FFF) << 3) & 0xFFFF;
/* ... */
can_addr_filter.FilterMaskIdHigh = (filter_mask >> 13) & 0xFFFF;
can_addr_filter.FilterMaskIdLow = ((filter_mask & 0x1FFF) << 3) & 0xFFFF;

 

 

It works and I have understood the filters! Thanks again!

mƎALLEm
ST Technical Moderator
December 11, 2024

Hi @Anno Anno,

Years ago I developed an API that builds CAN filters but I didn't validate it because I didn't have much time to do it.

I've attached a project that I used that API replicating your case and it's working as expected:

It's working in loopback mode. These are the IDs I'm sending:

 

uint32_t ext_id[] = {0x010112, 0x010013,0x020112, 0x1010115};

 

The only accepted IDs are 0x010112 and 0x1010115.

The API is this:

 

int8_t CAN_Build_Filter(CAN_Filter* usr_param, CAN_FilterTypeDef* hal_param)

 

In the example, I used the API as the following:

 

// 32 bit mask mode:	
 sFilterConfig.SlaveStartFilterBank = 0; 
 sFilterConfig.FilterBank = 0;
 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	
 can_fltr_param.filter.m32.id = 0x010100; 
 can_fltr_param.filter.m32.idext = EXTENDED_FRAME;
 can_fltr_param.filter.m32.idremote = REMOTE_FRAME;
	
 can_fltr_param.filter.m32.mask = 0x00FFFF00; 	
 can_fltr_param.filter.m32.maskext = 1;
 can_fltr_param.filter.m32.maskremote = 0;

 if(CAN_Build_Filter(&can_fltr_param,&sFilterConfig) != 0)
 {
 Error_Handler();
 }
	
 sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
 sFilterConfig.FilterActivation = ENABLE;
 if (HAL_CAN_ConfigFilter(&hcan2, &sFilterConfig) != HAL_OK)
 {
 /* Filter configuration Error */
 Error_Handler();
 }

 

It was many years ago, I even forgot how to use it. But ok if you can test it from your side and tell what do you think.

 

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
AnnoAuthor
Associate II
December 11, 2024

Very interesting indeed and it is not hard to use.

I included the can_filter etc. files in my project, set up the CAN_Filter struct just like you did in MX_CAN2_Init().

Works like a charm in real environment!

I can imagine that this would be very handy if you have to build a lot of filters.

Thanks for sharing