别的不多说,CAN过滤器的过滤模式和消息的标识符才是最有意思的。(默认过滤器位宽为1个32位宽的过滤器)
在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的(个人理解,就是报文的ID,CAN的仲裁就是按照报文的ID来仲裁的)。因此,发送者乙广播的形式把报文发送给所有的接收者。节点在接收报文时-根据标识符的值-决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。标识符包括STDID[10:0]、 EXTID[17:0]、 IDE和RTR位,如图。所以,有了这些提示,看下面的代码理解起来就不难了。
CAN从机:提供了两种过滤模式,一种标识符列表模式,另一种是屏蔽位模式。赋值时标识符 0x0000 1314 左移三位是因为寄存器的低三位意义为保留位、RTR 位和 IDE 位。CAN_FilterIdHigh 成员中(0x00001314)左移后再与 0xFFFF0000 作“&”运算是为了取这个标识符的高 16 位,最后再右移 16 位赋值给 CAN_FilterIdHigh 成员。CAN_FilterIdLow 成 员 的 赋 值 运 算 类 似,( 0x00001314) 左 移 后 与 宏CAN_ID_EXT 和 宏 CAN_RTR_DATA 作“|”运算,即把报文的 IDE 位、RTR 位也加入到
过滤器进行过滤比较。看代码吧!
void CAN_Config(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送 ,在多个CAN从机通信时,这个应该DISABLE
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //工作模式设置
//波特率设置 现在是1M
//36000/[(tbs1+tbs2+1)*brp]=波特率
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq ; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_5tq;//Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=4; //分频系数(Fdiv)为brp+1 1~1024
CAN_Init(CAN1, &CAN_InitStructure);
//配置过滤器
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdList; //标志符列表模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位过滤器
CAN_FilterInitStructure.CAN_FilterIdHigh=(((u32)0x10<<3)&0xffff0000)>>16; //标志符MSB过滤
CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)0x10<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff; //标志符LSB过滤
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=(((u32)0x10<<3)&0xffff0000)>>16;//掩码 MASK MSB
CAN_FilterInitStructure.CAN_FilterMaskIdLow=(((u32)0x10<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff;//掩码 MASK LSB
// //配置过滤器
// CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
// CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
// CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位过滤器
// CAN_FilterInitStructure.CAN_FilterIdHigh=(((u32)0x10<<3)&0xffff0000)>>16; //标志符MSB
// CAN_FilterInitStructure.CAN_FilterIdLow=(((u32)0x10<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xffff;//标志符LSB
// CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0xFFFF; //掩码 MASK MSB
// CAN_FilterInitStructure.CAN_FilterMaskIdLow=0xFFFF; //掩码 MASK LSB
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许
}
u8 CAN1_Send_Msg(u8 byte,u8 len)
{
u8 mbox;
u16 i=0;
TxMessage.StdId=0; // 标准标识符为0
TxMessage.ExtId=0x10; // 设置扩展标示符(29位)
TxMessage.IDE=CAN_ID_EXT; // 使用扩展标识符
TxMessage.RTR=CAN_RTR_DATA; // 消息类型为数据帧,一帧8位
TxMessage.DLC=len;
TxMessage.Data[0]=byte; // 第一帧信息
mbox= CAN_Transmit(CAN1, &TxMessage);
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
if(i>=0XFFF)return 1;
return 0;
}
CAN主机:主机接收所有从机的数据,所以不需要屏蔽位。
void CAN_Config(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
//CAN单元设置
CAN_InitStructure.CAN_TTCM=DISABLE; //非时间触发通信模式
CAN_InitStructure.CAN_ABOM=DISABLE; //软件自动离线管理
CAN_InitStructure.CAN_AWUM=DISABLE;//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
CAN_InitStructure.CAN_NART=ENABLE; //禁止报文自动传送
CAN_InitStructure.CAN_RFLM=DISABLE; //报文不锁定,新的覆盖旧的
CAN_InitStructure.CAN_TXFP=DISABLE; //优先级由报文标识符决定
CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; //模式设置
//波特率设置 现在是1M
//36000/[(tbs1+tbs2+1)*brp]=波特率
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq ; //重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位
CAN_InitStructure.CAN_BS1=CAN_BS1_3tq; //Tbs1范围CAN_BS1_1tq ~CAN_BS1_16tq
CAN_InitStructure.CAN_BS2=CAN_BS2_5tq;//Tbs2范围CAN_BS2_1tq ~ CAN_BS2_8tq
CAN_InitStructure.CAN_Prescaler=4; //分频系数(Fdiv)为brp+1 1~1024
CAN_Init(CAN1, &CAN_InitStructure); // 初始化CAN1
//配置过滤器
CAN_FilterInitStructure.CAN_FilterNumber=0; //过滤器0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //屏蔽位模式
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //32位过滤器
CAN_FilterInitStructure.CAN_FilterIdHigh=0x0000; //标志符MSB过滤
CAN_FilterInitStructure.CAN_FilterIdLow=0x0000; //标志符LSB过滤
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; //掩码 MASK MSB
CAN_FilterInitStructure.CAN_FilterMaskIdLow=0x0000; //掩码 MASK LSB
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0;//过滤器0关联到FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //激活过滤器0
CAN_FilterInit(&CAN_FilterInitStructure);//滤波器初始化
CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许
}
u8 CAN1_Send_Msg(u8 byte,u8 len)
{
u8 mbox;
u16 i=0;
TxMessage.StdId=0; // 标准标识符为0
TxMessage.ExtId=0x10; // 设置扩展标示符(29位)
TxMessage.IDE=CAN_ID_EXT; // 使用扩展标识符
TxMessage.RTR=CAN_RTR_DATA; // 消息类型为数据帧,一帧8位
TxMessage.DLC=len;
TxMessage.Data[0]=byte; // 第一帧信息
mbox= CAN_Transmit(CAN1, &TxMessage);
while((CAN_TransmitStatus(CAN1, mbox)==CAN_TxStatus_Failed)&&(i<0XFFF))i++; //等待发送结束
if(i>=0XFFF)return 1;
return 0;
}