OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 6631|回复: 1

stm32F407ZET6的CAN1能配置28个32位的掩码筛选器吗

[复制链接]

4

主题

8

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2021-11-12
在线时间
6 小时
发表于 2022-12-5 16:09:19 | 显示全部楼层 |阅读模式
20金钱
本帖最后由 Chris1995 于 2022-12-5 16:25 编辑

需求:系统配置N个通道,CAN总线只接收0-N节点的数据。   
example:系统通道总数为51,那么只接收0,1,2,3,4,....51的数据。
如下为CAN协议格式

   

CAN协议

CAN协议

所以采用拓展帧,在筛选器的选择上选择了32位的掩码模式。
通过查阅F4的参考手册得知,bxCAN具有28个筛选器。
CAN特性.png
                                    bxCAN外设框图
            CAN外设框图.png

  CAN共有28个筛选器组,每个筛选器可配置4种模式,分别是1个32位掩码,2个32位标识符,2个16位掩码,4个16位标识符。
根据我32位的掩码模式使用场景,也就是说可以配置28个32位掩码的筛选器
  所以采用的算法思路:比如系统通道数为51,小于51的二次幂项是32,配置一个0-31的区间筛选器,然后32到51每个单独配置一个筛选器。所以筛选器数量为1个区间筛选器+20(51-32+1)指定筛选器。
  代码如下:

  1. void Bsp_Can_FilterConfig(void)
  2. {
  3.         CAN_FilterTypeDef sFilterConfig;
  4.         HAL_StatusTypeDef status;
  5.         const uint32_t Can_Id = 0x10000000;
  6.         const uint16_t packet_sum = 128;  //包总数
  7.         uint16_t ps_nearest_pow = 0;        //向上寻找包总数最近的二次幂
  8.         
  9.         struct
  10.         {
  11.                 uint8_t node_total;         //节点总数
  12.                 uint8_t pow_nearst_down;    //向下最近二次幂   
  13.                 uint8_t filter_num;         //滤波器编号
  14.                 uint8_t node_num;           //节点编号
  15.                
  16.                 uint32_t id;
  17.                 uint32_t mask_range;        //区间
  18.         }Can_Filter;

  19.         Can_Filter.filter_num = 0;
  20.         Can_Filter.node_total = Get_Mid_Property_Node_Total();
  21.         ps_nearest_pow = pow(2, ceil(log2(packet_sum)));
  22.         Can_Filter.pow_nearst_down = pow(2, floor(log2(Can_Filter.node_total)));
  23.         
  24.         Can_Filter.mask_range = 0x1fffffff;
  25.         Can_Filter.mask_range &= (~((ps_nearest_pow-1) << 0));
  26.         Can_Filter.mask_range &= (~((ps_nearest_pow-1) << 9));
  27.         Can_Filter.mask_range &= (~((Can_Filter.pow_nearst_down-1) << 20));
  28.         Can_Filter.mask_range <<= 3;
  29.         
  30.         /***************** 配置区间滤波器 *********************/
  31.         sFilterConfig.FilterActivation = ENABLE;                 
  32.         sFilterConfig.FilterBank = Can_Filter.filter_num;                           
  33.         sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;        
  34.         sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;      
  35.         sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;   

  36.         sFilterConfig.FilterMaskIdHigh = (Can_Filter.mask_range>>16)&0xffff;
  37.         sFilterConfig.FilterMaskIdLow =  (Can_Filter.mask_range&0xffff);
  38.         
  39.         sFilterConfig.FilterIdHigh = ((Can_Id<<3)>>16)&0xffff;
  40.         sFilterConfig.FilterIdLow = ((Can_Id<<3)&0xffff);        
  41.         sFilterConfig.SlaveStartFilterBank = 0;
  42.         HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
  43.         /********************************************************/
  44.         
  45.         /***************** 配置指定滤波器 *********************/
  46.         sFilterConfig.FilterMaskIdHigh = (0x0ff00000<<3) >> 16;
  47.         sFilterConfig.FilterMaskIdLow =  0;
  48.         
  49.         for(Can_Filter.node_num=Can_Filter.pow_nearst_down;
  50.                 Can_Filter.node_num<=Can_Filter.node_total;
  51.                 Can_Filter.node_num++)
  52.         {
  53.                 Can_Filter.id = 0;
  54.                 Can_Filter.filter_num++;
  55.                
  56.                 if( Can_Filter.filter_num < 14 )
  57.                 {
  58.                         sFilterConfig.SlaveStartFilterBank = 0;

  59.                 }
  60.                 else
  61.                 {
  62.                         sFilterConfig.SlaveStartFilterBank = 14;
  63.                 }
  64.                
  65.                 if( Can_Filter.filter_num > 28 )
  66.                 {
  67.                         log_i("Can Filter Num Over Range");
  68.                         break;
  69.                 }
  70.               
  71.                 sFilterConfig.FilterBank = Can_Filter.filter_num;
  72.                
  73.                 Can_Filter.id = Can_Filter.node_num << 20;
  74.                 sFilterConfig.FilterIdHigh = (Can_Filter.id <<3)>>16;
  75.                 sFilterConfig.FilterIdLow = 0;        
  76.                
  77.                 status = HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig);
  78.         }</font>
复制代码
   测试方法:一个CAN发送设备,每隔100ms发送设备地址0-128的数据。
作为接收设备,在接收中断把CAN EXID的设备地址打印出来。
如系统设置为51通道,串口每隔100ms显示0-51。
   测试现象:只收到0-44。

                   测试现象.png
   疑问点:从测试现象分析,31+13=44,CAN1好像只有14个筛选器起到了作用。只要筛选器编号超过14就不起作用,我在程序debug时查了所有筛选器硬件寄存器的值和算法是对应的。
   我再次查了资料,筛选器数量28还是14说的模棱两可。

                验收筛选器.png
              所以我的疑问是stm32F407ZET6,为什么CAN1的14-28筛选器不起作用?


正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

51

主题

2166

帖子

2

精华

论坛元老

Rank: 8Rank: 8

积分
10653
金钱
10653
注册时间
2017-4-14
在线时间
2780 小时
发表于 2022-12-5 21:12:21 | 显示全部楼层
记得是一个can 14个过滤器  不过你这场景配置成通过一组数据 3个好像就够了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-24 23:09

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表