2024-12-10 08:04 AM - last edited on 2024-12-10 08:48 AM by SofLit
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
Solved! Go to Solution.
2024-12-10 08:35 AM - edited 2024-12-10 08:49 AM
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 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.
2024-12-10 08:35 AM - edited 2024-12-10 08:49 AM
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 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.
2024-12-10 09:54 AM - edited 2024-12-10 09:55 AM
>>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
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 );
}
2024-12-10 10:03 AM
See also
https://community.st.com/t5/stm32-mcus-products/stm32f103-can-filter-range-of-id-s/m-p/620967
2024-12-11 01:47 AM - edited 2024-12-11 03:37 AM
Hello again,
thank you @SofLit 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!
2024-12-11 05:27 AM - edited 2024-12-11 07:22 AM
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.
2024-12-11 06:09 AM - edited 2024-12-11 06:09 AM
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
2024-12-11 06:17 AM
It was designed to be generic, look at CAN_Build_Filter() core, it treats all the combinations 16 bit/32bit filters and ID mask and ID list configs.
If you have time to test it as a "beta tester" and tell me if there are some issues ;-).
2024-12-11 08:20 AM
Maybe I will implement it to our next project, in which I see a good reason to use the list config.
When an issue occurs I will let you know.
Or if I have some time left over in the next few weeks, I'll play around a bit too :)