STM32 CAN

别的不多说,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;        

}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值