一,CAN通讯的简单理解
对于CAN通讯来说,主机发送一段数据给从机,数据主要由 {....ID帧,数据帧,..} 组成。从机通过过滤器过滤掉ID不符合的数据,经过过滤器过滤的数据进入接收邮箱——FIFO0,FIFO1.在接收邮箱中,数据能够被读取到。
二,CAN通讯的过滤器。
关于过滤器的设置。ID可以分为32个二进制的,也可以分为16个二进制的。滤波器可以对这两种ID进行滤波。
(2)滤波的方式
滤波的方式可以分为两种,第一种,是要求ID的部分相同。第二种是要求ID完全相同。第二种被叫为列表模式。
三,我在列表模式上踩的坑。
我用32位字节的ID,列表模式。
void Can_Filter_Config(void)
{
/*过滤器的三个ID*/
u32 EXID1 = 0x5200;
u32 EXID2 = 0x5201;
u32 EXID3 = 0x5101;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
// CAN筛选器0初始化,筛选器关联到FIFO0
CAN_FilterInitStructure.CAN_FilterNumber = 0; //筛选器组0
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList; //工作在列表模式
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; //使用32位扩展帧。
// 使能筛选器,按照标志的内容进行比对筛选,扩展ID不是如下的就抛弃掉,是的话,会存入FIFO0。
CAN_FilterInitStructure.CAN_FilterIdHigh = (((EXID1 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF0000) >> 16; //列表ID高位
CAN_FilterInitStructure.CAN_FilterIdLow = ((EXID1 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF; //列表的ID低位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (((EXID3 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF0000) >> 16; //列表ID高位
CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((EXID3 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF; //列表ID高位
CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_Filter_FIFO0; //筛选器被关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation = ENABLE; //使能筛选器
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // FIFO0中断
}
这是我最终调试好的代码。在列表模式下,过滤器寄存器都可以存放ID。
如上所示,本来是放掩码的,可以放ID了。
在列表模式下,只有ID跟滤波器上的ID完全一致才会通过滤波器。
所以说我踩的坑是什么呢?
我以为直接把32位的ID的高位放在Hight上,把ID的低8位放在LOW上,就可以了。
结果不是的。
数据帧是分段的。
void CAN_SetMsg(CanTxMsg *TxMessage, u32 ID, u8 data1, u8 data2)
{
// TxMessage->StdId = 0x202;
TxMessage->ExtId = ID; //
TxMessage->IDE = CAN_ID_EXT; //使用扩展帧发送数据
TxMessage->RTR = CAN_RTR_DATA; //发送的是数据
TxMessage->DLC = 8; //数据长度为8字节
/*设置要发送的数据0-7*/
TxMessage->Data[0] = data1;
TxMessage->Data[1] = data2;
}
通过对发送邮箱的初始化。你将ID,数据类型,长度等信息写入数据帧。并且发送出去。
所以滤波寄存器不仅会识别你发送的ID,还有数据类型,ID长度。
ID要写在红圈处。其余的IDE,RTR也要写对。
方法如上。
就像上面的代码
CAN_FilterInitStructure.CAN_FilterIdHigh = (((EXID1 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF0000) >> 16; //先ID向左移动3位,再补上32位字节的信息和数据帧的信息,放进滤波器中
CAN_FilterInitStructure.CAN_FilterIdLow = ((EXID1 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF; //列表的ID低位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (((EXID3 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF0000) >> 16; //列表ID高位
CAN_FilterInitStructure.CAN_FilterMaskIdLow = ((EXID3 << 3) | CAN_ID_EXT | CAN_RTR_DATA) & 0xFFFF; //列表ID高位
先ID向左移动3位,再补上32位字节的信息和数据帧的信息,放进滤波器中。