纪要
CAN(Controller Area Network)总线是一种广泛应用于工业控制和汽车电子领域的串行通信协议。在CAN总线中,节点间通过CAN总线发送和接收消息。每个CAN帧包含一个标准或扩展标识符(ID)和数据负载。
CAN总线帧过滤器是一个硬件组件,可用于过滤传输到节点的CAN帧。帧过滤器允许节点只处理其所需的CAN帧,从而降低总线负载和系统处理开销。帧过滤器可以配置为基于标准或扩展ID进行过滤,也可以使用ID掩码匹配特定的CAN帧。
实际应用中基本都用扩展帧,因为标准帧的11bit id实在是太捉急了,放不了什么内容
在配置了CAN过滤器后,发现指定的一些帧收不到但是总线上收到了这些帧
问题描述
目前所采用的为CAN的扩展帧模式,需要过滤出类似0x04FB2028
这种xxFBxxxx
的报文,但是发现一个问题FB16
的报文被接收到了,但是FB20
这种报文被滤除了,这时候我就怀疑了是Filter配置错误
CAN_FilterInitStructure.Filter_Num = CAN_FILTERNUM5;
CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode;
CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale;
CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_EXTID_H(0x04FB2028);
CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_EXTID_L(0x04FB2028);
CAN_FilterInitStructure.FilterMask_HighId = 0x00FF;
CAN_FilterInitStructure.FilterMask_LowId = 0x0000;
CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.Filter_Act = ENABLE;
CAN1_InitFilter(&CAN_FilterInitStructure);
宏
#define CAN_FILTER_EXTID_H(EXTID) ((uint16_t)(((EXTID) >> 13) & 0xFFFF))
#define CAN_FILTER_EXTID_L(EXTID) ((uint16_t)(((uint32_t)(EXTID) << 3U) | ((uint8_t)CAN_ID_EXT)))
问题解决
首先我们来看下扩展帧的报文格式
CAN扩展帧ID范围为0x00000000
到0x1FFFFFFF
是因为最后3位是 IDE RTR 0其实可用部分只有29bit
配置过滤器也是如此,下面是过滤器的寄存器内容
配置过滤器有两种模式精准过滤(filter list mode)
和 规则过滤(Mask mode)
,根据上面所述我们需要的是 Mask mode。
看上表中filter id
和 filter mask
每一位都是对齐的,并且开始的 3bits 对我们而言是无意义的,所以我们上面对filter id
配置了偏移,下面对应的对于filter mask
也需要做相同的操作。
CAN_FilterInitStructure.Filter_Num = CAN_FILTERNUM3;
CAN_FilterInitStructure.Filter_Mode = CAN_Filter_IdMaskMode;
CAN_FilterInitStructure.Filter_Scale = CAN_Filter_32bitScale;
CAN_FilterInitStructure.Filter_HighId = CAN_FILTER_EXTID_H(0x04FB2028);
CAN_FilterInitStructure.Filter_LowId = CAN_FILTER_EXTID_L(0x04FB2028);
CAN_FilterInitStructure.FilterMask_HighId = CAN_FILTER_EXTID_H(0x00FF0000);
CAN_FilterInitStructure.FilterMask_LowId = CAN_FILTER_EXTID_L(0x00FF0000);
CAN_FilterInitStructure.Filter_FIFOAssignment = CAN_FIFO0;
CAN_FilterInitStructure.Filter_Act = ENABLE;
CAN1_InitFilter(&CAN_FilterInitStructure);
如此配置后CAN可以正确过滤出 xxFBxxxx的报文了。