CAN总线的标准帧和扩展帧主要决定帧ID的长度,标准帧的帧ID长度是11位,也就是帧ID的范围是000-7FF。扩展帧的帧ID长度是29位,也就是帧ID的范围是0000 0000-1FFF FFFF。CANopen帧ID最多是11位的,因此是标准帧;而SAE 1939协议通常是18XX XXXX的帧ID,是29位的,因此是扩展帧。
在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时-根据标识符的值决定软件是否需要该报文;如果需要,就拷贝到RAM里;如果不需要,报文就被丢弃且无需软件的干预。为满足这一需求,beCAN为应用程序提供了个可配置的、位宽可变的6个(0-5)过滤器组,用于只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件进行过滤,从而占用一定的CPU资源。每个过滤器组x包含8个8位寄存器 CAN_FxR[8:1].
STM8S208的beCAN有6个过滤器,它们之间是并联的,也就是说只要通过任意一个过滤器,报文就会被拷贝到RAM。
beCAN位宽可变性:
每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过可以配置成以下位宽:
─ 1 个32 位过滤器,包括: STDID[10:0]/EXTID[28:18]、IDE、 EXID[17:0] RTR
─ 2个 16 位过滤器,包括: STDID[10:0]/EXTID[28:18]、IDE、 RTR
─ 4个8 位过滤器,包括:STDID[10:3]/EXTID[28:21],其他位可以不用关心;
─ 1个16位过滤器和 2个 8位过滤器,具体的过滤器描述如上16位和 8位过滤器描述。
STDID:标准ID,有11位。
EXTID: 扩展ID,有29位。
IDE :当等于0时表示标准ID, 当等于1时表示扩展ID
RTR:当等于0时表示数据帧, 当等于1时表示远程帧(remote frame)。
beCAN的工作模式:
beCAN提供了两种工作模式:屏蔽位模式和标识符列表模式。如下例所示:
typedef enum
{
CAN_FilterMode_IdMask = ((uint8_t)0x00), /*!< id/mask mode */
CAN_FilterMode_IdMask_IdList = ((uint8_t)0x10), /*!< Id/Mask mode First and IdList mode second */
CAN_FilterMode_IdList_IdMask = ((uint8_t)0x11), /*!< IdList mode First and IdMask mode second */
CAN_FilterMode_IdList = ((uint8_t)0x01) /*!< identifier list mode */
}CAN_FilterMode_TypeDef;
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。
在标识符列表模式下,屏蔽寄存器当作标识符寄存器用。因此,使用2个标识符来代替上面的标识符加屏蔽位的方式。接收报文标识的每一位都必须跟过滤器标识符相同。
32位过滤器寄存器定义如下:
举个例子:设置过滤器0只接收ID为0x1828A0EF的数据帧。(工作在屏蔽位模式)
该帧ID超过11位,为扩展帧ID。二进制表示为
1 1000 0010 1000 1010 0000 1110 1111
前11位ID(EXID[28:18],对应寄存器位置[31:21])为1100 0001 010,EXID[17:15](寄存器位置[20:18])为001,EXID[14:7](寄存器位置[15:8])为0100 0001,EXID[6:0](寄存器位置[7:1])为1101 111。
寄存器的第17位为IDE,设置为1时表示扩展帧ID,设置为0表示标准帧ID。寄存器的第16位为RTR,设置为1时表示远程帧,设置为0时表示数据帧。寄存器第一位([0])为保留位,设为0。
本例中RTR应设为0,IDE应设为1。
所以32位寄存器的设置为1100 0001 0100 1001 0100 0001 1101 1110。
其中绿色位置为RTR,黄色位为IDE,红色为为保留位0。16进制表示为0xC1 49 41 DE。
工作在屏蔽位模式时,我们可以指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。如果Can_FxR5、Can_FxR6、Can_FxR7、Can_FxR7
都为0xFF时报文ID必须匹配所有的位才能通过过滤器。当Can_FxR5、Can_FxR6、Can_FxR7、Can_FxR7都为0x00时,所有的报文都可以通过过滤器。CAN_FilterIDMask1~4对应Can_FxR5、Can_FxR6、Can_FxR7、Can_FxR7。本例中应该都设置为0xFF。
设置代码如下所示:
CAN_FilterNumber =CAN_FilterNumber_0;
CAN_FilterMode =CAN_FilterMode_IdMask;
CAN_FilterScale =CAN_FilterScale_32Bit;
CAN_FilterID1=0xc1;
CAN_FilterID2=0x49;
CAN_FilterID3=0x41;
CAN_FilterID4=0xde;
CAN_FilterIDMask1=0xFF;//CAN_FilterIDMask1~4是一个32位的寄存器,用来设置Can_FxR5、Can_FxR6、Can_FxR7、Can_FxR8。
CAN_FilterIDMask2=0xFF;
CAN_FilterIDMask3=0xFF;
CAN_FilterIDMask4=0xFF;
CAN_FilterIDMask1~4也是一个32位的寄存器,用来设置Can_FxR5、Can_FxR6、Can_FxR7、Can_FxR8,与CAN_FilterID1~4的32位一一对应。IDMask寄存器里的某一位设为1代表传进来的报文必须和过滤器Identifier寄存器对应的该位匹配,设为0代表Identifier寄存器中的该位不需要关心是否匹配。
再看一个例子:设置ID过滤器0只接收ID为0x20XXXX的数据帧。
首先这个ID大于0x7FF,是扩展帧。因为还是数据帧,所以IDE设为1,RTR设为0。拓展ID第29位到17位([28:16])为0 0000 0010 0000。
过滤器ID寄存器设置为0000 0001 0000 1000 0000 0000 0000 0000.
其中绿色位置为RTR,黄色位为IDE,棕色位及以后的都不影响最后的ID。红色为为保留位0。16进制表示为0x01 08 00 00。
IDMask寄存器应在棕色位以前为1,棕色位起以后为0。即1111 1111 1111 1110 0000 0000 0000 0000,16进制为0xFF FE 00 00。设置代码如下所示:
CAN_FilterNumber =CAN_FilterNumber_0;
CAN_FilterMode =CAN_FilterMode_IdMask;
CAN_FilterScale =CAN_FilterScale_32Bit;
CAN_FilterID1=0x01;
CAN_FilterID2=0x08;
CAN_FilterID3=0x00;
CAN_FilterID4=0x00;
CAN_FilterIDMask1=0xFF;//CAN_FilterIDMask1~4是一个32位的寄存器,用来设置Can_FxR5、Can_FxR6、Can_FxR7、Can_FxR8。
CAN_FilterIDMask2=0xFE;
CAN_FilterIDMask3=0x00;
CAN_FilterIDMask4=0x00;
如果IDMask寄存器没有正确配置好的话,会使得ID寄存器的某些位不起作用(比如对应的IDMask被设置成了0)。比如下面的例子:
CAN_Filter_Structure.FilterNumber = CAN_FilterNumber_0;//ID过滤
CAN_Filter_Structure.FilterActivation = ENABLE;
CAN_Filter_Structure.FilterMode = CAN_FilterMode_IdMask;
CAN_Filter_Structure.FilterScale = CAN_FilterScale_32Bit;
CAN_Filter_Structure.FilterID1=0x01;
CAN_Filter_Structure.FilterID2=0x00;
CAN_Filter_Structure.FilterID3=0;
CAN_Filter_Structure.FilterID4=0;
CAN_Filter_Structure.FilterIDMask1=0xff;
CAN_Filter_Structure.FilterIDMask2=0xe6;
CAN_Filter_Structure.FilterIDMask3=0;
CAN_Filter_Structure.FilterIDMask4=0;