Reputation: 75
I'm try to use the acceptance filter from the SJA1000 CAN-Controller on a ESP23. The Messages should be filtered in a defined area (e.g. Arbitration ID from: 0x30 to: 0x35).
Example for filtering a single message (0x30):
#define CAN_FILTER_CONFIG_ACCEPT() {.acceptance_code = 0x1500000, .acceptance_mask = 0xffffff, .single_filter = true}
If I want to filter a defined area (0x30 - 0x35):
int calc_mask(int startID, int endID) {
int size_of_range = endID - startID;
unsigned int acceptance_mask = 0xFFFFFFFF;
int i;
for (i = startID; i <= endID; i++ {
acceptance_mask = ~(acceptance_mask & i);
}
return acceptance_mask;
}
acceptance_code = 0x30;
acceptance_mask = calc_mask(0x30, 0x35);
0x30 : 110000
NAND 0x31: 110001
NAND 0x32: 110010
NAND 0x33: 110011
NAND 0x34: 110100
NAND 0x35: 110101
0xF : 001111
acceptance_code = 0x6000000: 0000 0110 0000 0000 0000 0000 0000 0000
acceptance_mask = 0x1FFFFFF: 0000 0001 1111 1111 1111 1111 1111 1111
filtered Messages:
wanted:
14:21:17.754 -> CAN Message: 30 110000
14:21:17.754 -> CAN Message: 31 110001
14:21:17.787 -> CAN Message: 32 110010
14:21:17.787 -> CAN Message: 33 110011
14:21:17.787 -> CAN Message: 34 110100
14:21:17.821 -> CAN Message: 35 110101
unwanted:
14:21:17.821 -> CAN Message: 36 110110
14:21:17.821 -> CAN Message: 37 110111
14:21:17.855 -> CAN Message: 38 111000
14:21:17.855 -> CAN Message: 39 111001
14:21:17.855 -> CAN Message: 3A 111010
14:21:17.889 -> CAN Message: 3B 111011
14:21:17.889 -> CAN Message: 3C 111100
14:21:17.889 -> CAN Message: 3D 111101
14:21:17.923 -> CAN Message: 3E 111110
14:21:17.923 -> CAN Message: 3F 111111
Documentation ESP32 CAN-Controller (Acceptance Filter):
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/can.html#acceptance-filter
Documentation SJA1000 CAN-Controller (6.4.15 Acceptance filter): https://www.nxp.com/docs/en/data-sheet/SJA1000.pdf
Does anyone have an idea how to get the not wanted Messages filtered?
Upvotes: 4
Views: 2517
Reputation: 12404
You probably cannot filter all unwanted messages. But you can narrow down a bit. For a suitable mask you must treat the ones and the zeros separately.
uint32 mask_ones = mask_zeros = ~0;
for (int id = startId; id < endId; id++)
{
mask_ones &= id;
mask_zeros &= ~id;
}
uint32 mask = mask_ones | mask_zeroes;
uint32 value = startId & mask;
This creates a mask which includes all bits that are set to 1 in every allowed value and also all bits that are set to 0 in every allowed value.
This should get rid of all values above 0x37
.
Example:
ones = zeros = 11111111
CAN Message: 30 110000 => mask_ones = 00110000; mask_zeros = 11001111
CAN Message: 31 110001 => mask_ones = 00110000; mask_zeros = 11001110
CAN Message: 32 110010 => mask_ones = 00110000; mask_zeros = 11001100
CAN Message: 33 110011 => mask_ones = 00110000; mask_zeros = 11001100
CAN Message: 34 110100 => mask_ones = 00110000; mask_zeros = 11001000
CAN Message: 35 110101 => mask_ones = 00110000; mask_zeros = 11001000
unwanted:
CAN Message: 36 110110
CAN Message: 37 110111
CAN Message: 38 111000
mask = 00110000 | 11001000 = 11111000 = 0xF8
value = 00110000 & 11111000 = 00110000 = 0x30
Update: The calculation above was broken. Fixed it.
Upvotes: 1
Reputation: 3022
It seems to me that what you are trying to achieve is not possible if you are using a single filter. For example, you could define
.acceptance_code = 0x30,
.acceptance_mask = 0x03,
This would accept IDs in the range 0x30 to 0x33 - but exclude 0x34 and 0x35.
On the other hand, with acceptance code = 0x34
and acceptance mask = 0x01
you would be allowing 0x34 and 0x35 - but excluding 0x30 - 0x33.
I notice that the acceptance filter can be placed in a dual filter mode, however - with the proviso that it can not be used to filter an extended ID. Maybe this will allow you to define complementary filters as defined above.
Upvotes: 1