ESP32CAN的Examples对于esp32can_filter的程序注释非常少,非常的不明确,所以我广泛查找了各种资料,包括ESP IDF的和ST32的,终于搞懂了它的滤波逻辑,这里贴出我的程序,里面有详细的注释说明它的滤波逻辑
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#include <ESP32CAN.h>
#include <CAN_config.h>
#include <Arduino.h>
#include <HuskyCANBoard2.h>
CAN_device_t CAN_cfg; // CAN Config
const int rx_queue_size = 10; // Receive Queue size
void setup() {
Serial.begin(115200);
Serial.println("Filter Demo - ESP32-Arduino-CAN");
CAN_cfg.speed = CAN_SPEED_1000KBPS;//注意这里的通信速率,挂载在一条总线上的所有的设备必须一致,我开始一致没调出来就是因为这里设置错误了
CAN_cfg.tx_pin_id = CAN_TX;
CAN_cfg.rx_pin_id = CAN_RX;
CAN_cfg.rx_queue = xQueueCreate(rx_queue_size, sizeof(CAN_frame_t));
// Set CAN Filter
// See in the SJA1000 Datasheet chapter "6.4.15 Acceptance filter"
// and the APPLICATION NOTE AN97076 chapter "4.1.2 Acceptance Filter"
// for PeliCAN Mode
CAN_filter_t p_filter;//创建一个滤波器对象
p_filter.FM = Single_Mode;//设置单滤波模式
p_filter.ACR0 = 0x00;//验收代码寄存器 这个代表你想要过滤出的ID号
p_filter.ACR1 = 0x20;//因为标准帧ID号的长度为11位,而这里的16进制有16位,所以你想要过滤出的ID号的值必须左移5位才是
p_filter.ACR2 = 0x00;//16位的两个16进制数,以这里为例,我想要过滤出的ID号为1,所以1左移5位的10进制数为32,也就是0x20,所以这
p_filter.ACR3 = 0x00;//里的ACR0为0x00,ACR1为0x20,再举个例子,比如我想过滤出ID号为1000的消息,则1000左移5位为的
//10进制数32000,16进制数为0x7D00,所以这里的ACR0为0x7D ACR1为0x00,
p_filter.AMR0 = 0x00;//验收屏蔽寄存器 这里的 1 代表可以与上面规定的不同的位,0 代表必须严格相同的位
p_filter.AMR1 = 0x0F;//这里我想严格的过滤出ID号为1的消息,所以这里的AMR0为0x00,代表前8位必须完全相同,
p_filter.AMR2 = 0xFF;//AMR1为0x0F代表高4位必须完全相同,后四位无所谓,而AMR2和AMR3都为0xFF则表示后面的都可以不一样,也可以一样,不做要求
p_filter.AMR3 = 0xFF;
ESP32Can.CANConfigFilter(&p_filter);
// Init CAN Module
ESP32Can.CANInit();
}
void loop() {
CAN_frame_t rx_frame;
unsigned long currentMillis = millis();
// Receive next CAN frame from queue
if (xQueueReceive(CAN_cfg.rx_queue, &rx_frame, 3 * portTICK_PERIOD_MS) == pdTRUE) {
if (rx_frame.FIR.B.FF == CAN_frame_std) {
printf("New standard frame");
} else {
printf("New extended frame");
}
if (rx_frame.FIR.B.RTR == CAN_RTR) {
printf(" RTR from 0x%08X, DLC %d\r\n", rx_frame.MsgID, rx_frame.FIR.B.DLC);
} else {
printf(" from 0x%08X, DLC %d, Data ", rx_frame.MsgID, rx_frame.FIR.B.DLC);
for (int i = 0; i < rx_frame.FIR.B.DLC; i++) {
printf("0x%02X ", rx_frame.data.u8[i]);
}
printf("\n");
}
}
}
本文详细介绍了ESP32CAN模块的滤波逻辑,并提供了示例代码进行说明。作者通过研究SJA1000数据手册和应用笔记,理解了CAN滤波器的工作原理,并设置了单模式滤波器,明确了验收代码和验收屏蔽寄存器的配置方法,以过滤特定ID的消息。在初始化CAN模块后,程序能够接收并打印符合滤波条件的CAN帧信息。


被折叠的 条评论
为什么被折叠?



