CAN

CAN

屏蔽码/验证码

也就是说,屏蔽码设得宽度,得到其验证码

img

ID

标准

11位

img

扩展

29位(不够用之后拓宽

img

过滤器

掩码和列表模式

​ 定义在CAN_FM1R寄存器中FBMx位上,bxCAN共有28个过滤器,于是上图的每一个位对应地表示这28个过滤器的工作模式,供用户设置。”0”表示掩码模 式,”1”表示列表模式。

img

表示CAN ID位宽

​ 寄存器CAN_FS1R来表示CAN ID的位宽,每一个位对应着bxCAN中28个过滤器的位宽,这个需要用户来设置

img

各种组合模式

img

具体工作模式(解决方案

每个过滤器都存在这么两个寄存器CAN_FxR1和CAN_FxR2,这两个寄存器都是32位的

掩码模式—32

img

​ CAN_FxR1用做32位宽的验证码,而CAN_FxR2则用作32位宽的屏蔽码

只针对标准CAN ID

​ 对于验证码,任意一个期望通过的CAN ID都是可以设为验证码的,但屏蔽码,却是所有期望通过的CAN ID相互同或后的最终结果,这个即是屏蔽码

static void CANFilterConfig_Scale32_IdMask_StandardIdOnly(void)
{
  CAN_FilterConfTypeDef  sFilterConfig;
  uint16_t StdIdArray[10] ={0x7e0,0x7e1,0x7e2,0x7e3,0x7e4,
                                0x7e5,0x7e6,0x7e7,0x7e8,0x7e9}; //定义一组标准CAN ID
  uint16_t      mask,num,tmp,i;

  sFilterConfig.FilterNumber = 2;				//使用过滤器2
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;		//配置为掩码模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//设置为32位宽
  sFilterConfig.FilterIdHigh =(StdIdArray[0]<<5);		//验证码可以设置为StdIdArray[]数组中任意一个,这里使用StdIdArray[0]作为验证码
  sFilterConfig.FilterIdLow =0;

  mask =0x7ff;						//下面开始计算屏蔽码
  num =sizeof(StdIdArray)/sizeof(StdIdArray[0]);
  for(i =0; i<num; i++)		//屏蔽码位StdIdArray[]数组中所有成员的同或结果
  {
    tmp =StdIdArray[i] ^ (~StdIdArray[0]);	//所有数组成员与第0个成员进行同或操作
    mask &=tmp;
  }
  sFilterConfig.FilterMaskIdHigh =(mask<<5);
  sFilterConfig.FilterMaskIdLow =0|0x02; 		//只接收数据帧

  sFilterConfig.FilterFIFOAssignment = 0;		//设置通过的数据帧进入到FIFO0中
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
只针对扩展CAN ID

​ 扩展CAN ID的验证码与屏蔽码放入到相对应的寄存器时所移动的位数与标准CAN ID时有所差别,其他的都一样

static void CANFilterConfig_Scale32_IdMask_ExtendIdOnly(void)
{
  CAN_FilterConfTypeDef  sFilterConfig;
  //定义一组扩展CAN ID用来测试
uint32_t ExtIdArray[10] ={0x1839f101,0x1835f102,0x1835f113,0x1835f124,0x1835f105,
                            0x1835f106,0x1835f107,0x1835f108,0x1835f109,0x1835f10A};
  uint32_t      mask,num,tmp,i;

  sFilterConfig.FilterNumber = 3;					//使用过滤器3
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			//配置为掩码模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;		//设为32位宽
  sFilterConfig.FilterIdHigh =((ExtIdArray[0]<<3) >>16) &0xffff;//数组任意一个成员都可以作为验证码
  sFilterConfig.FilterIdLow =((ExtIdArray[0]<<3)&0xffff) | CAN_ID_EXT;

  mask =0x1fffffff;
  num =sizeof(ExtIdArray)/sizeof(ExtIdArray[0]);
  for(i =0; i<num; i++)				//屏蔽码位数组各成员相互同或的结果
  {
    tmp =ExtIdArray[i] ^ (~ExtIdArray[0]);	//都与第一个数据成员进行同或操作
    mask &=tmp;
  }
  mask <<=3;    								//对齐寄存器
  sFilterConfig.FilterMaskIdHigh = (mask>>16)&0xffff;
  sFilterConfig.FilterMaskIdLow = (mask&0xffff)|0x02; 		//只接收数据帧
  sFilterConfig.FilterFIFOAssignment = 0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
标准和扩展混合过滤

​ 在混合的情况下,只需稍微修改下屏蔽码的计算方式就可以了,其他的基本没有什么变化。

static void CANFilterConfig_Scale32_IdMask_StandardId_ExtendId_Mix(void)
{
  CAN_FilterConfTypeDef  sFilterConfig;
  //定义一组标准CAN ID
uint32_t StdIdArray[10] ={0x711,0x712,0x713,0x714,0x715,
                          0x716,0x717,0x718,0x719,0x71a};
  //定义另外一组扩展CAN ID
uint32_t ExtIdArray[10] ={0x1900fAB1,0x1900fAB2,0x1900fAB3,0x1900fAB4,0x1900fAB5,
                            0x1900fAB6,0x1900fAB7,0x1900fAB8,0x1900fAB9,0x1900fABA};
  uint32_t      mask,num,tmp,i,standard_mask,extend_mask,mix_mask;

  sFilterConfig.FilterNumber = 4;				//使用过滤器4
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;		//配置为掩码模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//设为32位宽
  sFilterConfig.FilterIdHigh =((ExtIdArray[0]<<3) >>16) &0xffff;	//使用第一个扩展CAN  ID作为验证码
  sFilterConfig.FilterIdLow =((ExtIdArray[0]<<3)&0xffff);

  standard_mask =0x7ff;		//下面是计算屏蔽码
  num =sizeof(StdIdArray)/sizeof(StdIdArray[0]);
  for(i =0; i<num; i++)			//首先计算出所有标准CAN ID的屏蔽码
  {
    tmp =StdIdArray[i] ^ (~StdIdArray[0]);
    standard_mask &=tmp;
  }

  extend_mask =0x1fffffff;
  num =sizeof(ExtIdArray)/sizeof(ExtIdArray[0]);
  for(i =0; i<num; i++)			//接着计算出所有扩展CAN ID的屏蔽码
  {
    tmp =ExtIdArray[i] ^ (~ExtIdArray[0]);
    extend_mask &=tmp;
  }
  mix_mask =(StdIdArray[0]<<18)^ (~ExtIdArray[0]);	//再计算标准CAN ID与扩展CAN ID混合的屏蔽码
  mask =(standard_mask<<18)& extend_mask &mix_mask;	//最后计算最终的屏蔽码
  mask <<=3;    						//对齐寄存器

  sFilterConfig.FilterMaskIdHigh = (mask>>16)&0xffff;
  sFilterConfig.FilterMaskIdLow = (mask&0xffff);
  sFilterConfig.FilterFIFOAssignment = 0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
掩码模式—16

img

CAN_FxR1和CAN_FxR2都要各自拆分成两个16位宽的寄存器来使用,CAN_FxR1的低16位是作为验证码,对应的16位屏蔽码为CAN_FxR1的高16位,同样的,CAN_FxR2的低16位是作为验证码,对应与CAN_FxR2的高16位为屏蔽码

static void CANFilterConfig_Scale16_IdMask(void)
{
  CAN_FilterConfTypeDef  sFilterConfig;
  uint16_t StdIdArray1[10] ={0x7D1,0x7D2,0x7D3,0x7D4,0x7D5,	//定义第一组标准CAN ID
                          0x7D6,0x7D7,0x7D8,0x7D9,0x7DA};
  uint16_t StdIdArray2[10] ={0x751,0x752,0x753,0x754,0x755,	//定义第二组标准CAN ID
                          0x756,0x757,0x758,0x759,0x75A};
  uint16_t      mask,tmp,i,num;

  sFilterConfig.FilterNumber = 5;					//使用过滤器5
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;			//配置为掩码模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;		//设为16位宽

  //配置第一个过滤对
  sFilterConfig.FilterIdLow =StdIdArray1[0]<<5;			//设置第一个验证码
  mask =0x7ff;
  num =sizeof(StdIdArray1)/sizeof(StdIdArray1[0]);
  for(i =0; i<num; i++)							//计算第一个屏蔽码
  {
    tmp =StdIdArray1[i] ^ (~StdIdArray1[0]);
    mask &=tmp;
  }
  sFilterConfig.FilterMaskIdLow =(mask<<5)|0x10;    //只接收数据帧

  //配置第二个过滤对
  sFilterConfig.FilterIdHigh = StdIdArray2[0]<<5;	//设置第二个验证码
  mask =0x7ff;
  num =sizeof(StdIdArray2)/sizeof(StdIdArray2[0]);
  for(i =0; i<num; i++)					//计算第二个屏蔽码
  {
    tmp =StdIdArray2[i] ^ (~StdIdArray2[0]);
    mask &=tmp;
  }
  sFilterConfig.FilterMaskIdHigh = (mask<<5)|0x10;  //只接收数据帧


  sFilterConfig.FilterFIFOAssignment = 0;		//通过的CAN 消息放入到FIFO0中
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
列表模式—32

img

static void CANFilterConfig_Scale32_IdList(void)
{
  CAN_FilterConfTypeDef  sFilterConfig;
  uint32_t StdId =0x321;				//这里写入两个CAN ID,一个位标准CAN ID
  uint32_t ExtId =0x1800f001;			//一个位扩展CAN ID

  sFilterConfig.FilterNumber = 0;				//使用过滤器0
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;		//设为列表模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//配置为32位宽
  sFilterConfig.FilterIdHigh = StdId<<5;			//基本ID放入到STID中
  sFilterConfig.FilterIdLow = 0|CAN_ID_STD;			//设置IDE位为0
  sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;
  sFilterConfig.FilterMaskIdLow = (ExtId<<3)&0xffff|CAN_ID_EXT;	//设置IDE位为1
  sFilterConfig.FilterFIFOAssignment = 0;			//接收到的报文放入到FIFO0中
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

存储某个具体的期望通过的CAN ID,这样就可以存入2个期望通过的CAN ID(标准CAN ID和扩展CAN ID均可)

CAN_FxR1寄存器的高16位对应着上面代码中的FilterIdHigh,低16位对应着FilterIdLow,而CAN_FxR2寄存器的高16位对应着FilterMaskIdHigh,低16位对应着FilterMaskIdLow(看成4个变量来用)

列表模式—16

img

static void CANFilterConfig_Scale16_IdList(void)
{
  CAN_FilterConfTypeDef  sFilterConfig;
  uint32_t StdId1 =0x123;						//这里采用4个标准CAN ID作为例子
  uint32_t StdId2 =0x124;
  uint32_t StdId3 =0x125;
  uint32_t StdId4 =0x126;

  sFilterConfig.FilterNumber = 1;				//使用过滤器1
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;		//设为列表模式
  sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;	//位宽设置为16位
  sFilterConfig.FilterIdHigh = StdId1<<5;	 //4个标准CAN ID分别放入到4个存储中
  sFilterConfig.FilterIdLow = StdId2<<5;
  sFilterConfig.FilterMaskIdHigh = StdId3<<5;
  sFilterConfig.FilterMaskIdLow = StdId4<<5;
  sFilterConfig.FilterFIFOAssignment = 0;			//接收到的报文放入到FIFO0中
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.BankNumber = 14;

  if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}

2对验证码+屏蔽码组合来用,但它只能对标准CAN ID进行过滤

在16位宽的列表模式下,FilterIdHigh,FilterIdLow,FilterMaskIdHigh,FilterMaskIdLow这4个16位变量都是用来存储一个标准CAN ID

发送和接收

发送

img

设置邮箱,设置ID,设置CAN_TlxR(邮箱标识符寄存器)的TXRQ为1请求发送,邮箱挂号(等待成为最高优先级),预定发送,发送,邮箱空值

接收

img

通过读取FIFO输出邮箱来读取最先收到的报文(有效报文:正确被接收且通过标识符过滤的报文)。 CAN 的接收有 2 个 FIFO,我们每个滤波器组都可以设置其关联的 FIFO,通过 CAN_FFA1R 的设置,可以将滤波器组关联到FIFO0/FIFO1。

注意事项

屏蔽码和验证码的设置

​ 验证码可以设置为某个确定的ID

​ 屏蔽码是所有期望通过的CAN ID相互同或后的最终结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值