使用 SJA1000 (ESP32) 的 CAN 控制器验收过滤
CAN-Controller acceptance filtering with the SJA1000 (ESP32)
我正在尝试在 ESP23 上使用 SJA1000 CAN 控制器的验收过滤器。
应在定义的区域中过滤消息(例如仲裁 ID 从:0x30 到:0x35)。
过滤单个消息 (0x30) 的示例:
#define CAN_FILTER_CONFIG_ACCEPT() {.acceptance_code = 0x1500000, .acceptance_mask = 0xffffff, .single_filter = true}
如果我要过滤定义区域(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
已过滤的消息:
想要:
14:21:17.754 -> CAN 消息:30 110000
14:21:17.754 -> CAN 消息:31 110001
14:21:17.787 -> CAN 消息:32 110010
14:21:17.787 -> CAN 消息:33 110011
14:21:17.787 -> CAN 消息:34 110100
14:21:17.821 -> CAN 消息:35 110101
不需要的:
14:21:17.821 -> CAN 消息:36 110110
14:21:17.821 -> CAN 消息:37 110111
14:21:17.855 -> CAN 消息:38 111000
14:21:17.855 -> CAN 消息:39 111001
14:21:17.855 -> CAN 报文:3A 111010
14:21:17.889 -> CAN 消息:3B 111011
14:21:17.889 -> CAN 消息:3C 111100
14:21:17.889 -> CAN 报文:3D 111101
14:21:17.923 -> CAN 报文:3E 111110
14:21:17.923 -> CAN 消息:3F 111111
文档 ESP32 CAN 控制器(验收过滤器):
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/can.html#acceptance-filter
文档 SJA1000 CAN 控制器(6.4.15 验收过滤器):
https://www.nxp.com/docs/en/data-sheet/SJA1000.pdf
有谁知道如何过滤不需要的消息吗?
在我看来,如果您使用单个过滤器,您将无法实现您想要实现的目标。例如,您可以定义
.acceptance_code = 0x30,
.acceptance_mask = 0x03,
这将接受 0x30 到 0x33 范围内的 ID - 但不包括 0x34 和 0x35。
另一方面,对于 acceptance code = 0x34
和 acceptance mask = 0x01
,您将允许 0x34 和 0x35 - 但不包括 0x30 - 0x33。
我注意到验收过滤器可以置于 双重 过滤器模式,但是 - 附带条件是它不能用于过滤扩展 ID。也许这将允许您定义上面定义的补充过滤器。
您可能无法过滤所有不需要的消息。但是你可以缩小范围。
对于合适的掩码,您必须分别处理 1 和 0。
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;
这将创建一个掩码,其中包括在每个允许值中设置为 1 的所有位以及在每个允许值中设置为 0 的所有位。
这应该摆脱 0x37
.
以上的所有值
示例:
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
更新:
上面的计算被打破了。已修复。
我正在尝试在 ESP23 上使用 SJA1000 CAN 控制器的验收过滤器。 应在定义的区域中过滤消息(例如仲裁 ID 从:0x30 到:0x35)。
过滤单个消息 (0x30) 的示例:
#define CAN_FILTER_CONFIG_ACCEPT() {.acceptance_code = 0x1500000, .acceptance_mask = 0xffffff, .single_filter = true}
如果我要过滤定义区域(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
已过滤的消息:
想要:
14:21:17.754 -> CAN 消息:30 110000
14:21:17.754 -> CAN 消息:31 110001
14:21:17.787 -> CAN 消息:32 110010
14:21:17.787 -> CAN 消息:33 110011
14:21:17.787 -> CAN 消息:34 110100
14:21:17.821 -> CAN 消息:35 110101
不需要的:
14:21:17.821 -> CAN 消息:36 110110
14:21:17.821 -> CAN 消息:37 110111
14:21:17.855 -> CAN 消息:38 111000
14:21:17.855 -> CAN 消息:39 111001
14:21:17.855 -> CAN 报文:3A 111010
14:21:17.889 -> CAN 消息:3B 111011
14:21:17.889 -> CAN 消息:3C 111100
14:21:17.889 -> CAN 报文:3D 111101
14:21:17.923 -> CAN 报文:3E 111110
14:21:17.923 -> CAN 消息:3F 111111
文档 ESP32 CAN 控制器(验收过滤器):
https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/can.html#acceptance-filter
文档 SJA1000 CAN 控制器(6.4.15 验收过滤器): https://www.nxp.com/docs/en/data-sheet/SJA1000.pdf
有谁知道如何过滤不需要的消息吗?
在我看来,如果您使用单个过滤器,您将无法实现您想要实现的目标。例如,您可以定义
.acceptance_code = 0x30,
.acceptance_mask = 0x03,
这将接受 0x30 到 0x33 范围内的 ID - 但不包括 0x34 和 0x35。
另一方面,对于 acceptance code = 0x34
和 acceptance mask = 0x01
,您将允许 0x34 和 0x35 - 但不包括 0x30 - 0x33。
我注意到验收过滤器可以置于 双重 过滤器模式,但是 - 附带条件是它不能用于过滤扩展 ID。也许这将允许您定义上面定义的补充过滤器。
您可能无法过滤所有不需要的消息。但是你可以缩小范围。 对于合适的掩码,您必须分别处理 1 和 0。
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;
这将创建一个掩码,其中包括在每个允许值中设置为 1 的所有位以及在每个允许值中设置为 0 的所有位。
这应该摆脱 0x37
.
示例:
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
更新: 上面的计算被打破了。已修复。