[STM32F1] Stm32f103的can硬件滤波配置与调试

[复制链接]
542|7
 楼主| 等你下课 发表于 2022-4-30 23:52 | 显示全部楼层 |阅读模式
需要实现一条can总线上连接许多can设备,如果can设备都接收can中断数据的话,cpu会消耗较多资源,于是想到了使用can模块的硬件滤波功能,can设备自身需要的几个stdid信号可以接收到,其他的都做硬件滤波过滤掉。
can的硬件滤波分精准识别(标识符识别列表)和mask(部分过滤)两种方式;有两个32bit寄存器,分别设置为16bit过滤或者32bit过滤,入下图所示(全0为不使用过滤器):
  1.   sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID                  不使用过滤器
  2.   sFilterConfig.FilterIdLow = 0x0000;
  3.   sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK
  4.   sFilterConfig.FilterMaskIdLow = 0x0000;       
标准std和扩展std的时序,如下图所示,扩展std跟stm32的filter寄存器正好偏移三位;标准std则是偏移5bit,需要在函数处理的时候,进行移位处理。
19790626d5b5900103.png

 楼主| 等你下课 发表于 2022-4-30 23:53 | 显示全部楼层
 楼主| 等你下课 发表于 2022-4-30 23:54 | 显示全部楼层
上图为stm32屏蔽寄存器对应的std的映射图,例字如下:
  1.   CAN_FilterTypeDef  sFilterConfig;
  2.   
  3.   uint32_t StdId = 0x321;                                //这里写入两个CAN ID,一个位标准CAN ID
  4.   uint32_t ExtId = 0x1800f001;                        //一个位扩展CAN ID
  5.   
  6.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;                //设为列表模式
  7.   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;        //配置为32位宽
  8.   sFilterConfig.FilterIdHigh = StdId<<5;                        //基本ID放入到STID中
  9.   sFilterConfig.FilterIdLow = 0|CAN_ID_STD;                        //设置IDE位为0
  10.   
  11.   sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;
  12.   sFilterConfig.FilterMaskIdLow = (ExtId<<3)&0xffff|CAN_ID_EXT;        //设置IDE位为1
 楼主| 等你下课 发表于 2022-4-30 23:55 | 显示全部楼层
后面的为完整的函数,各种掩码、不同滤波方式
  1. #include "FreeRTOS.h"
  2. #include "main.h"
  3. #include "cmsis_os.h"
  4. #include "can.h"
  5. #include "can_filter.h"
  6. #include "stdlib.h"
  7. #include "string.h"

  8. #ifdef USE_CAN_FILTER_IN_BOARD_XIANSHU
  9. extern int g_device_id;
  10. #endif

  11. extern CAN_HandleTypeDef hcan;


  12. /*******************************************************************************
  13. * 函数名 : CANFilterConfig_AnyId
  14. * 描  述 : 过滤器关闭,任何id数据都能接收
  15. * 输  入 : 无
  16. * 输  出 : 无
  17. * 返回值 : 无
  18. * 说  明 :
  19. *******************************************************************************/
  20. void CANFilterConfig_AnyId(void)
  21. {
  22.   //CAN_FilterConfTypeDef  sFilterConfig;
  23.   CAN_FilterTypeDef sFilterConfig;

  24.   sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID                  不使用过滤器
  25.   sFilterConfig.FilterIdLow = 0x0000;
  26.   sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK
  27.   sFilterConfig.FilterMaskIdLow = 0x0000;          
  28.   sFilterConfig.FilterBank = 0;                  //过滤器0
  29.   sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //过滤器0关联到FIFO0
  30.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  31.   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  32.   sFilterConfig.FilterActivation = ENABLE; //激活过滤器0
  33.   
  34.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  35.   {
  36.         Error_Handler();
  37.   }
  38. }


  39. /*******************************************************************************
  40. * 函数名 : CANFilterConfig_Scale32_IdMask_StandardIdOnly
  41. * 描  述 : 32bit掩码滤波 只过滤接收函数中设置的那几个标准帧id的数据
  42. * 输  入 : 无
  43. * 输  出 : 无
  44. * 返回值 : 无
  45. * 说  明 :
  46. *******************************************************************************/
  47. void CANFilterConfig_Scale32_IdMask_StandardIdOnly(void)
  48. {
  49.   //CAN_FilterConfTypeDef  sFilterConfig;
  50.   CAN_FilterTypeDef sFilterConfig;
  51.   uint16_t                mask,num,tmp,i;

  52.   #ifdef USE_CAN_FILTER_IN_BOARD_XIANSHU
  53.   uint16_t StdIdArray[4] = {0}; //定义一组标准CAN ID

  54.   StdIdArray[0] = BASE_ID_RECV | (g_device_id << 4) | CAN_HEART_BEAT;  //0x200,0x210...0x270
  55.   StdIdArray[1] = BASE_ID_RECV | (g_device_id << 4) | CAN_GPIO_SET;  //0x201,0x211...0x271
  56.   StdIdArray[2] = BASE_ID_RECV | (g_device_id << 4) | CAN_GPIO_GET;  //0x202,0x212...0x272
  57.   StdIdArray[3] = BASE_ID_RECV | (g_device_id << 4) | CAN_VOICE_SET;  //0x203,0x213...0x273
  58.   #else
  59.   
  60.   uint16_t StdIdArray[10] ={0x200,0x201,0x202,0x203,0x204,
  61.                                                                 0x205,0x206,0x207,0x208,0x209}; //定义一组标准CAN ID
  62.   #endif
  63.   
  64.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;         //配置为掩码模式
  65.   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;        //设置为32位宽
  66.   sFilterConfig.FilterIdHigh =(StdIdArray[0]<<5);                //验证码可以设置为StdIdArray[]数组中任意一个,这里使用StdIdArray[0]作为验证码
  67.   sFilterConfig.FilterIdLow =0;
  68.   
  69.   mask =0x7ff;                                                //下面开始计算屏蔽码
  70.   num =sizeof(StdIdArray)/sizeof(StdIdArray[0]);
  71.   for(i =0; i<num; i++)         //屏蔽码位StdIdArray[]数组中所有成员的同或结果
  72.   {
  73.         tmp =StdIdArray[i] ^ (~StdIdArray[0]);        //所有数组成员与第0个成员进行同或操作
  74.         mask &=tmp;
  75.   }
  76.   sFilterConfig.FilterMaskIdHigh =(mask<<5);
  77.   sFilterConfig.FilterMaskIdLow =0|0x02;                //只接收数据帧
  78.   
  79.   sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;                //设置通过的数据帧进入到FIFO0中
  80.   sFilterConfig.FilterActivation = ENABLE;                                                //激活过滤器
  81.   sFilterConfig.FilterBank = 0;                  //过滤器0     0~13 数字越小,优先级越高
  82.   
  83.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  84.   {
  85.         Error_Handler();
  86.   }
  87. }



  88. /*******************************************************************************
  89. * 函数名 : CANFilterConfig_Scale32_IdList
  90. * 描  述 : 32bit列表滤波 精确识别id,可以同时识别出标准和扩展id号
  91. * 输  入 : 无
  92. * 输  出 : 无
  93. * 返回值 : 无
  94. * 说  明 :
  95. *******************************************************************************/
  96. void CANFilterConfig_Scale32_IdList(void)
  97. {
  98.   CAN_FilterTypeDef  sFilterConfig;
  99.   
  100.   uint32_t StdId = 0x321;                                //这里写入两个CAN ID,一个位标准CAN ID
  101.   uint32_t ExtId = 0x1800f001;                        //一个位扩展CAN ID
  102.   
  103.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;                //设为列表模式
  104.   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;        //配置为32位宽
  105.   sFilterConfig.FilterIdHigh = StdId<<5;                        //基本ID放入到STID中
  106.   sFilterConfig.FilterIdLow = 0|CAN_ID_STD;                        //设置IDE位为0
  107.   
  108.   sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;
  109.   sFilterConfig.FilterMaskIdLow = (ExtId<<3)&0xffff|CAN_ID_EXT;        //设置IDE位为1
  110.   
  111.   sFilterConfig.FilterFIFOAssignment = 0;                        //接收到的报文放入到FIFO0中
  112.   sFilterConfig.FilterActivation = ENABLE;
  113.   sFilterConfig.FilterBank = 14;                        //过滤器14     0~13 数字越小,优先级越高
  114.   
  115.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  116.   {
  117.     Error_Handler();
  118.   }
  119. }

  120. /*******************************************************************************
  121. * 函数名 : CANFilterConfig_Scale16_IdList
  122. * 描  述 : 16bit列表滤波 精确识别id(只能识别标准id),一个滤波器只能识别4个标准id
  123. * 输  入 : 无
  124. * 输  出 : 无
  125. * 返回值 : 无
  126. * 说  明 :
  127. *******************************************************************************/
  128. void CANFilterConfig_Scale16_IdList(void)
  129. {
  130.   CAN_FilterTypeDef  sFilterConfig;
  131.   uint32_t StdId1 =0x123;                                                //这里采用4个标准CAN ID作为例子
  132.   uint32_t StdId2 =0x124;
  133.   uint32_t StdId3 =0x125;
  134.   uint32_t StdId4 =0x126;
  135.   

  136.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;                //设为列表模式
  137.   sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;        //位宽设置为16位
  138.   sFilterConfig.FilterIdHigh = StdId1<<5;         //4个标准CAN ID分别放入到4个存储中
  139.   sFilterConfig.FilterIdLow  = StdId2<<5;
  140.   sFilterConfig.FilterMaskIdHigh = StdId3<<5;
  141.   sFilterConfig.FilterMaskIdLow  = StdId4<<5;
  142.   sFilterConfig.FilterFIFOAssignment = 0;                        //接收到的报文放入到FIFO0中
  143.   sFilterConfig.FilterActivation = ENABLE;
  144.   sFilterConfig.FilterBank = 14;
  145.   
  146.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  147.   {
  148.     Error_Handler();
  149.   }
  150. }


  151. /*******************************************************************************
  152. * 函数名 : CANFilterConfig_Scale32_IdMask_ExtendIdOnly
  153. * 描        述 : 32bit掩码滤波 只过滤接收函数中设置的那几个扩展帧数据
  154. * 输        入 : 无
  155. * 输        出 : 无
  156. * 返回值 : 无
  157. * 说        明 :
  158. *******************************************************************************/
  159. void CANFilterConfig_Scale32_IdMask_ExtendIdOnly(void)
  160. {
  161.   CAN_FilterTypeDef  sFilterConfig;
  162.   //定义一组扩展CAN ID用来测试
  163.   uint32_t ExtIdArray[10] ={0x1839f101,0x1835f102,0x1835f113,0x1835f124,0x1835f105,
  164.                             0x1835f106,0x1835f107,0x1835f108,0x1835f109,0x1835f10A};
  165.   uint32_t      mask,num,tmp,i;
  166.   
  167.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;                        //配置为掩码模式
  168.   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;                //设为32位宽
  169.   sFilterConfig.FilterIdHigh =((ExtIdArray[0]<<3) >>16) &0xffff;//数组任意一个成员都可以作为验证码
  170.   sFilterConfig.FilterIdLow =((ExtIdArray[0]<<3)&0xffff) | CAN_ID_EXT;
  171.   
  172.   mask =0x1fffffff;
  173.   num =sizeof(ExtIdArray)/sizeof(ExtIdArray[0]);
  174.   for(i =0; i<num; i++)                                //屏蔽码位数组各成员相互同或的结果
  175.   {
  176.     tmp =ExtIdArray[i] ^ (~ExtIdArray[0]);        //都与第一个数据成员进行同或操作
  177.     mask &=tmp;
  178.   }
  179.   mask <<=3;                                                                    //对齐寄存器
  180.   sFilterConfig.FilterMaskIdHigh = (mask>>16)&0xffff;
  181.   sFilterConfig.FilterMaskIdLow = (mask&0xffff)|0x02;                 //只接收数据帧
  182.   sFilterConfig.FilterFIFOAssignment = 0;
  183.   sFilterConfig.FilterActivation = ENABLE;
  184.   sFilterConfig.FilterBank = 14;
  185.   
  186.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  187.   {
  188.     Error_Handler();
  189.   }
  190. }


  191. /*******************************************************************************
  192. * 函数名 : CANFilterConfig_Scale32_IdMask_StandardId_ExtendId_Mix
  193. * 描  述 : 32bit掩码滤波 只过滤接收函数中设置的那几个扩展帧和标准帧数据
  194. * 输  入 : 无
  195. * 输  出 : 无
  196. * 返回值 : 无
  197. * 说  明 :
  198. *******************************************************************************/
  199. void CANFilterConfig_Scale32_IdMask_StandardId_ExtendId_Mix(void)
  200. {
  201.   CAN_FilterTypeDef  sFilterConfig;
  202.   //定义一组标准CAN ID
  203.   uint32_t StdIdArray[10] ={0x711,0x712,0x713,0x714,0x715,
  204.                           0x716,0x717,0x718,0x719,0x71a};
  205.   //定义另外一组扩展CAN ID
  206.   uint32_t ExtIdArray[10] ={0x1900fAB1,0x1900fAB2,0x1900fAB3,0x1900fAB4,0x1900fAB5,
  207.                             0x1900fAB6,0x1900fAB7,0x1900fAB8,0x1900fAB9,0x1900fABA};
  208.   uint32_t      mask,num,tmp,i,standard_mask,extend_mask,mix_mask;
  209.   
  210.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;                //配置为掩码模式
  211.   sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;        //设为32位宽
  212.   sFilterConfig.FilterIdHigh =((ExtIdArray[0]<<3) >>16) &0xffff;        //使用第一个扩展CAN  ID作为验证码
  213.   sFilterConfig.FilterIdLow =((ExtIdArray[0]<<3)&0xffff);
  214.   
  215.   standard_mask =0x7ff;                //下面是计算屏蔽码
  216.   num =sizeof(StdIdArray)/sizeof(StdIdArray[0]);
  217.   for(i =0; i<num; i++)                        //首先计算出所有标准CAN ID的屏蔽码
  218.   {
  219.     tmp =StdIdArray[i] ^ (~StdIdArray[0]);
  220.     standard_mask &=tmp;
  221.   }
  222.   
  223.   extend_mask =0x1fffffff;
  224.   num =sizeof(ExtIdArray)/sizeof(ExtIdArray[0]);
  225.   for(i =0; i<num; i++)                        //接着计算出所有扩展CAN ID的屏蔽码
  226.   {
  227.     tmp =ExtIdArray[i] ^ (~ExtIdArray[0]);
  228.     extend_mask &=tmp;
  229.   }
  230.   mix_mask =(StdIdArray[0]<<18)^ (~ExtIdArray[0]);        //再计算标准CAN ID与扩展CAN ID混合的屏蔽码
  231.   mask =(standard_mask<<18)& extend_mask &mix_mask;        //最后计算最终的屏蔽码
  232.   mask <<=3;                                                    //对齐寄存器

  233.   sFilterConfig.FilterMaskIdHigh = (mask>>16)&0xffff;
  234.   sFilterConfig.FilterMaskIdLow = (mask&0xffff);
  235.   sFilterConfig.FilterFIFOAssignment = 0;
  236.   sFilterConfig.FilterActivation = ENABLE;
  237.   sFilterConfig.FilterBank = 14;
  238.   
  239.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  240.   {
  241.     Error_Handler();
  242.   }
  243. }




  244. /*******************************************************************************
  245. * 函数名 : CANFilterConfig_Scale16_IdMask
  246. * 描        述 : 16bit掩码滤波 可以识别两组标准帧
  247. * 输        入 : 无
  248. * 输        出 : 无
  249. * 返回值 : 无
  250. * 说        明 :
  251. *******************************************************************************/
  252. void CANFilterConfig_Scale16_IdMask(void)
  253. {
  254.   CAN_FilterTypeDef  sFilterConfig;
  255.   uint16_t StdIdArray1[10] ={0x7D1,0x7D2,0x7D3,0x7D4,0x7D5,        //定义第一组标准CAN ID
  256.                           0x7D6,0x7D7,0x7D8,0x7D9,0x7DA};
  257.   uint16_t StdIdArray2[10] ={0x751,0x752,0x753,0x754,0x755,        //定义第二组标准CAN ID
  258.                           0x756,0x757,0x758,0x759,0x75A};
  259.   uint16_t      mask,tmp,i,num;
  260.   
  261.   sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;                        //配置为掩码模式
  262.   sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;                //设为16位宽
  263.   
  264.   //配置第一个过滤对
  265.   sFilterConfig.FilterIdLow =StdIdArray1[0]<<5;                        //设置第一个验证码
  266.   mask =0x7ff;
  267.   num =sizeof(StdIdArray1)/sizeof(StdIdArray1[0]);
  268.   for(i =0; i<num; i++)                                                        //计算第一个屏蔽码
  269.   {
  270.     tmp =StdIdArray1[i] ^ (~StdIdArray1[0]);
  271.     mask &=tmp;
  272.   }
  273.   sFilterConfig.FilterMaskIdLow =(mask<<5)|0x10;    //只接收数据帧
  274.   
  275.   //配置第二个过滤对
  276.   sFilterConfig.FilterIdHigh = StdIdArray2[0]<<5;        //设置第二个验证码
  277.   mask =0x7ff;
  278.   num =sizeof(StdIdArray2)/sizeof(StdIdArray2[0]);
  279.   for(i =0; i<num; i++)                                        //计算第二个屏蔽码
  280.   {
  281.     tmp =StdIdArray2[i] ^ (~StdIdArray2[0]);
  282.     mask &=tmp;
  283.   }
  284.   sFilterConfig.FilterMaskIdHigh = (mask<<5)|0x10;  //只接收数据帧
  285.   

  286.   sFilterConfig.FilterFIFOAssignment = 0;                //通过的CAN 消息放入到FIFO0中
  287.   sFilterConfig.FilterActivation = ENABLE;
  288.   sFilterConfig.FilterBank = 14;
  289.   
  290.   if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
  291.   {
  292.     Error_Handler();
  293.   }
  294. }



 楼主| 等你下课 发表于 2022-4-30 23:55 | 显示全部楼层
上述函数在can初始化的时候进行调用就行了,
 楼主| 等你下课 发表于 2022-4-30 23:56 | 显示全部楼层
  1. void MX_CAN_Init(void)
  2. {
  3.         CAN_FilterTypeDef sFilterConfig;

  4.   hcan.Instance = CAN1;
  5.   hcan.Init.Prescaler = 32;//32;                //pclk0=32Mhz            /16=2Mhz   ;/32=1Mhz(default:100k)
  6.   hcan.Init.Mode = CAN_MODE_NORMAL;
  7.   hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  8.   hcan.Init.TimeSeg1 = CAN_BS1_4TQ;
  9.   hcan.Init.TimeSeg2 = CAN_BS2_5TQ;
  10.   hcan.Init.TimeTriggeredMode = DISABLE;
  11.   hcan.Init.AutoBusOff = DISABLE;
  12.   hcan.Init.AutoWakeUp = DISABLE;
  13.   hcan.Init.AutoRetransmission = DISABLE;
  14.   hcan.Init.ReceiveFifoLocked = DISABLE;
  15.   hcan.Init.TransmitFifoPriority = DISABLE;


  16. #if 1                //500k config   bitrate = 2Mhz/(SyncJumpWidth+TimeSeg1+TimeSeg2) = 500k
  17.         hcan.Init.Prescaler = 16;                  //pclk0=32Mhz          /16=2Mhz
  18.         hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
  19.         hcan.Init.TimeSeg1 = CAN_BS1_2TQ;//CAN_BS1_2TQ
  20.         hcan.Init.TimeSeg2 = CAN_BS2_1TQ;
  21. #endif

  22.   if (HAL_CAN_Init(&hcan) != HAL_OK)
  23.   {
  24.     Error_Handler();
  25.   }


  26. #if 1
  27.         //CANFilterConfig_AnyId();
  28.         CANFilterConfig_Scale32_IdMask_StandardIdOnly();
  29.         //CANFilterConfig_Scale32_IdList();
  30.         //CANFilterConfig_Scale16_IdList();
  31.         //CANFilterConfig_Scale32_IdMask_ExtendIdOnly();
  32.         //CANFilterConfig_Scale32_IdMask_StandardId_ExtendId_Mix();
  33.         //CANFilterConfig_Scale16_IdMask();       
  34. #endif       

  35.         __HAL_CAN_ENABLE_IT(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);//使能can中断
  36.         //        CAN_ITConfig(CAN1,CAN_IT_FMP0,ENABLE);//FIFO0消息挂号中断允许.
  37.         //CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE);

  38.         //buffer init
  39.         Can_FifoBuf_Init(&gpcan_rx, mag_rxbuffer, CAN_RXBUFFER_SIZE);

  40. }

sadicy 发表于 2022-5-1 17:19 | 显示全部楼层
can的话,除了在汽车上,其他地方还有哪里应用多
kiwis66 发表于 2022-5-2 14:58 | 显示全部楼层
学习了,开始使用can了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

538

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部