CANID-MCP2518FD屏蔽寄存器赋值(11bit,CAN2.0标准帧)

在使用MCP2518FD时,需要多个标准帧接收,但是需要用到屏蔽器和过滤器,否则庞大的数据量会导致设备接收处理不过来。若使用接收中断(中断或查询方式),会导致设备工作异常。

程序处理环境:

1、需要接收多个id

2、自动计算屏蔽器赋值

---------------------------------------------------------------

原理讲解

MCP2518FD的(大多数的CAN芯片或者芯片内的CAN接收)接收数据,需要用到接收屏蔽和过滤器。

过滤器对象寄存器简而言之就是需要接收到的id。

屏蔽寄存器简而言之就是对过滤器对象寄存器哪些位必须对应,哪些无所谓。

例如1:

需要接收1个id - 0x50D

那么:

过滤对象寄存器 = 0x50D = 101 0000 1101

屏蔽寄存器 = 7FF = 111 1111 1111

得到的接收id的结果即为0x50D(两个寄存器配合接收id的规则为:屏蔽对象寄存器为1,则接收的id对应bit必须和过滤对象寄存器bit相同)。

上面屏蔽寄存器bit都为1,所以接收的id必须 = 过滤对象寄存器的值。

解释:

分析1
二进制
过滤对象寄存器0x0000050D0000 0000 0000 0000 0000 0101 0000 1101
屏蔽寄存器0x400007FF0100 0000 0000 0000 0000 0111 1111 1111
只看后11bit(后面的11bit为标准帧id)
接收的id0x50D101 0000 1101

例如2:

根据上面规则,若是有多个id需要接收。

分析2
二进制
过滤对象寄存器(需要的id)0x0000050D0000 0000 0000 0000 0000 0101 0000 1101
0x0000050B0000 0000 0000 0000 0000 0101 0000 1011
屏蔽寄存器0x400007F90100 0000 0000 0000 0000 0111 1111 1001
只看后11bit,屏蔽对象寄存器为0则接收可为0/1
可以接收的id为101 0000 1xx1
接收的id0x509101 0000 1001
0x50B101 0000 1011
0x50D101 0000 1101
0x50F101 0000 1111

如表格内容:想要接收id,0x50D、0x50B。此时屏蔽寄存器不能为0x7FF,因为此时有两个id,不能写死。对比0x50D、0x50B的二进制位。可以看到,低(从0开始)1、2bit都不相同,可能为0,也可能为1。所以屏蔽寄存器的低(从0开始)1、2bit需要为0。屏蔽寄存器 = 0x7F9。这样我们可以接收到0x509、0x50B、0x50D、0x50F共四种id。我们只需要在软件中将接收到的id进行判断即可。

例如3:

那如果是有2个以上或者很多id呢???

我们先通过2个id和3个id查看规律。可以看到,我们得到屏蔽寄存器的值都是通过 同或(异或取反)运算 得到的,即bit相同为1,不同为0。

2个id我们还可以直接使用同或计算。3个即以上却没有办法了,本人基础差,只能询问AI,AI表示只能逐位比较得到。于是我自己写了程序。

先放一下3bit计算的结果。

分析3
二进制
过滤对象寄存器(需要的id)0x0000050D0000 0000 0000 0000 0000 0101 0000 1101
0x0000050A0000 0000 0000 0000 0000 0101 0000 1010
0x0000050B0000 0000 0000 0000 0000 0101 0000 1011
屏蔽寄存器0x400007F80100 0000 0000 0000 0000 0111 1111 1000
只看后11bit,屏蔽对象寄存器为0则接收可为0/1
101 0000 1101
101 0000 1010
101 0000 1011
同或运算结果111 1111 1000

逐位比较程序(直接放程序,我现在devC上面测试的,可以直接移植到自己的程序上):

#include "stdio.h"
#define CANReveiveIDNum 2  //需要接收的CANid数量
unsigned  int CAN_Response_ID[CANReveiveIDNum] = {0x50B,0x50D};//id,数量对应CANReveiveIDNum
unsigned  int CAN_ReceiveID_FilterValue= 0x40000000;//用于配置屏蔽寄存器,过滤寄存器使用其中1个需要接收的id即可

//根据宏定义的id进行配置,,获取屏蔽寄存器的算法在数学上为a XNOR b = (a AND b) OR (NOT a AND NOT b)简化为a XNOR b = NOT (a XOR b)
//使用代码处理则需要进行逐位比较
void CAN_ReceiveID_FilterConfig(void){
  unsigned char ResultBit;//用于存储当前位比较的结果
  unsigned char NowBit,NextBit;//分别用于存储 当前的比较位,和下个id的比较位
  unsigned short int CAN_ReceiveID_FilterID = 0;//用于存储当前获取的id
  if(CANReveiveIDNum>0){//如果有id
    if(CANReveiveIDNum>1){//如果id数量大于1
      for(unsigned char i=0;i<11;i++){//id 11bit
        for(unsigned char j=0;j<CANReveiveIDNum-1;j++){//id数量
          NowBit = (CAN_Response_ID[j]>>i)&0x01;//当前比较的bit
          NextBit = (CAN_Response_ID[j+1]>>i)&0x01;//下一个id的比较bit
          if(NowBit == NextBit){
            ResultBit = 1;
          }else{
            ResultBit = 0;
            break;
          }
        }
        CAN_ReceiveID_FilterID |= ResultBit<<i;
      }
    }else{
      CAN_ReceiveID_FilterValue = 0x400007FF;//如果只有1个id
    }
  }else{//如果没有id
    ;
  }
  CAN_ReceiveID_FilterValue += CAN_ReceiveID_FilterID;
  printf("%x",CAN_ReceiveID_FilterValue);
}
int main(){
	CAN_ReceiveID_FilterConfig();
	return 0;
}

上面的运行结果(例子2)为:

修改参数运行:

#include "stdio.h"
#define CANReveiveIDNum 3  //需要接收的CANid数量
unsigned  int CAN_Response_ID[CANReveiveIDNum] = {0x50B,0x50D,0x50A};//id,数量对应CANReveiveIDNum
unsigned  int CAN_ReceiveID_FilterValue= 0x40000000;//用于配置屏蔽寄存器,过滤寄存器使用其中1个需要接收的id即可

//根据宏定义的id进行配置,,获取屏蔽寄存器的算法在数学上为a XNOR b = (a AND b) OR (NOT a AND NOT b)简化为a XNOR b = NOT (a XOR b)
//使用代码处理则需要进行逐位比较
void CAN_ReceiveID_FilterConfig(void){
  unsigned char ResultBit;//用于存储当前位比较的结果
  unsigned char NowBit,NextBit;//分别用于存储 当前的比较位,和下个id的比较位
  unsigned short int CAN_ReceiveID_FilterID = 0;//用于存储当前获取的id
  if(CANReveiveIDNum>0){//如果有id
    if(CANReveiveIDNum>1){//如果id数量大于1
      for(unsigned char i=0;i<11;i++){//id 11bit
        for(unsigned char j=0;j<CANReveiveIDNum-1;j++){//id数量
          NowBit = (CAN_Response_ID[j]>>i)&0x01;//当前比较的bit
          NextBit = (CAN_Response_ID[j+1]>>i)&0x01;//下一个id的比较bit
          if(NowBit == NextBit){
            ResultBit = 1;
          }else{
            ResultBit = 0;
            break;
          }
        }
        CAN_ReceiveID_FilterID |= ResultBit<<i;
      }
    }else{
      CAN_ReceiveID_FilterValue = 0x400007FF;//如果只有1个id
    }
  }else{//如果没有id
    ;
  }
  CAN_ReceiveID_FilterValue += CAN_ReceiveID_FilterID;
  printf("%x",CAN_ReceiveID_FilterValue);
}
int main(){
	CAN_ReceiveID_FilterConfig();
	return 0;
}

修改的地方(改成了例子3):

 运行结果:

可见和例子中手算的结果相同。 

-------------------------

其他:

程序中没有说过滤对象寄存器需要赋值多少,过滤对象寄存器只需要赋值需要接收的id的其中一个就行,因为频闭寄存器对应的bit = 0,都可以接收到。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值