完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
需要实现一条can总线上连接许多can设备,如果can设备都接收can中断数据的话,cpu会消耗较多资源,于是想到了使用can模块的硬件滤波功能,can设备自身需要的几个stdid信号可以接收到,其他的都做硬件滤波过滤掉。
can的硬件滤波分精准识别(标识符识别列表)和mask(部分过滤)两种方式;有两个32bit寄存器,分别设置为16bit过滤或者32bit过滤,入下图所示(全0为不使用过滤器): sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID 不使用过滤器 sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK sFilterConfig.FilterMaskIdLow = 0x0000; 标准std和扩展std的时序,如下图所示,扩展std跟stm32的filter寄存器正好偏移三位;标准std则是偏移5bit,需要在函数处理的时候,进行移位处理。 上图为stm32屏蔽寄存器对应的std的映射图,例字如下: CAN_FilterTypeDef sFilterConfig; uint32_t StdId = 0x321; //这里写入两个CAN ID,一个位标准CAN ID uint32_t ExtId = 0x1800f001; //一个位扩展CAN ID 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 后面的为完整的函数,各种掩码、不同滤波方式 #include "FreeRTOS.h" #include "main.h" #include "cmsis_os.h" #include "can.h" #include "can_filter.h" #include "stdlib.h" #include "string.h" #ifdef USE_CAN_FILTER_IN_BOARD_XIANSHU extern int g_device_id; #endif extern CAN_HandleTypeDef hcan; /******************************************************************************* * 函数名 : CANFilterConfig_AnyId * 描 述 : 过滤器关闭,任何id数据都能接收 * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_AnyId(void) { //CAN_FilterConfTypeDef sFilterConfig; CAN_FilterTypeDef sFilterConfig; sFilterConfig.FilterIdHigh = 0x0000;//32 位 ID 不使用过滤器 sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000;//32 位 MASK sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterBank = 0; //过滤器0 sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //过滤器0关联到FIFO0 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterActivation = ENABLE; //激活过滤器0 if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } /******************************************************************************* * 函数名 : CANFilterConfig_Scale32_IdMask_StandardIdOnly * 描 述 : 32bit掩码滤波 只过滤接收函数中设置的那几个标准帧id的数据 * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_Scale32_IdMask_StandardIdOnly(void) { //CAN_FilterConfTypeDef sFilterConfig; CAN_FilterTypeDef sFilterConfig; uint16_t mask,num,tmp,i; #ifdef USE_CAN_FILTER_IN_BOARD_XIANSHU uint16_t StdIdArray[4] = {0}; //定义一组标准CAN ID StdIdArray[0] = BASE_ID_RECV | (g_device_id << 4) | CAN_HEART_BEAT; //0x200,0x210...0x270 StdIdArray[1] = BASE_ID_RECV | (g_device_id << 4) | CAN_GPIO_SET; //0x201,0x211...0x271 StdIdArray[2] = BASE_ID_RECV | (g_device_id << 4) | CAN_GPIO_GET; //0x202,0x212...0x272 StdIdArray[3] = BASE_ID_RECV | (g_device_id << 4) | CAN_VOICE_SET; //0x203,0x213...0x273 #else uint16_t StdIdArray[10] ={0x200,0x201,0x202,0x203,0x204, 0x205,0x206,0x207,0x208,0x209}; //定义一组标准CAN ID #endif 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 tmp =StdIdArray ^ (~StdIdArray[0]); //所有数组成员与第0个成员进行同或操作 mask &=tmp; } sFilterConfig.FilterMaskIdHigh =(mask<<5); sFilterConfig.FilterMaskIdLow =0|0x02; //只接收数据帧 sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0; //设置通过的数据帧进入到FIFO0中 sFilterConfig.FilterActivation = ENABLE; //激活过滤器 sFilterConfig.FilterBank = 0; //过滤器0 0~13 数字越小,优先级越高 if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } /******************************************************************************* * 函数名 : CANFilterConfig_Scale32_IdList * 描 述 : 32bit列表滤波 精确识别id,可以同时识别出标准和扩展id号 * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_Scale32_IdList(void) { CAN_FilterTypeDef sFilterConfig; uint32_t StdId = 0x321; //这里写入两个CAN ID,一个位标准CAN ID uint32_t ExtId = 0x1800f001; //一个位扩展CAN ID 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.FilterBank = 14; //过滤器14 0~13 数字越小,优先级越高 if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } /******************************************************************************* * 函数名 : CANFilterConfig_Scale16_IdList * 描 述 : 16bit列表滤波 精确识别id(只能识别标准id),一个滤波器只能识别4个标准id * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_Scale16_IdList(void) { CAN_FilterTypeDef sFilterConfig; uint32_t StdId1 =0x123; //这里采用4个标准CAN ID作为例子 uint32_t StdId2 =0x124; uint32_t StdId3 =0x125; uint32_t StdId4 =0x126; 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.FilterBank = 14; if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } /******************************************************************************* * 函数名 : CANFilterConfig_Scale32_IdMask_ExtendIdOnly * 描 述 : 32bit掩码滤波 只过滤接收函数中设置的那几个扩展帧数据 * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_Scale32_IdMask_ExtendIdOnly(void) { CAN_FilterTypeDef sFilterConfig; //定义一组扩展CAN ID用来测试 uint32_t ExtIdArray[10] ={0x1839f101,0x1835f102,0x1835f113,0x1835f124,0x1835f105, 0x1835f106,0x1835f107,0x1835f108,0x1835f109,0x1835f10A}; uint32_t mask,num,tmp,i; 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 tmp =ExtIdArray ^ (~ExtIdArray[0]); //都与第一个数据成员进行同或操作 mask &=tmp; } mask <<=3; //对齐寄存器 sFilterConfig.FilterMaskIdHigh = (mask>>16)&0xffff; sFilterConfig.FilterMaskIdLow = (mask&0xffff)|0x02; //只接收数据帧 sFilterConfig.FilterFIFOAssignment = 0; sFilterConfig.FilterActivation = ENABLE; sFilterConfig.FilterBank = 14; if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } /******************************************************************************* * 函数名 : CANFilterConfig_Scale32_IdMask_StandardId_ExtendId_Mix * 描 述 : 32bit掩码滤波 只过滤接收函数中设置的那几个扩展帧和标准帧数据 * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_Scale32_IdMask_StandardId_ExtendId_Mix(void) { CAN_FilterTypeDef 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.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 tmp =StdIdArray ^ (~StdIdArray[0]); standard_mask &=tmp; } extend_mask =0x1fffffff; num =sizeof(ExtIdArray)/sizeof(ExtIdArray[0]); for(i =0; i tmp =ExtIdArray ^ (~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.FilterBank = 14; if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } /******************************************************************************* * 函数名 : CANFilterConfig_Scale16_IdMask * 描 述 : 16bit掩码滤波 可以识别两组标准帧 * 输 入 : 无 * 输 出 : 无 * 返回值 : 无 * 说 明 : *******************************************************************************/ void CANFilterConfig_Scale16_IdMask(void) { CAN_FilterTypeDef 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.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 tmp =StdIdArray1 ^ (~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 tmp =StdIdArray2 ^ (~StdIdArray2[0]); mask &=tmp; } sFilterConfig.FilterMaskIdHigh = (mask<<5)|0x10; //只接收数据帧 sFilterConfig.FilterFIFOAssignment = 0; //通过的CAN 消息放入到FIFO0中 sFilterConfig.FilterActivation = ENABLE; sFilterConfig.FilterBank = 14; if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { Error_Handler(); } } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1885 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1663 浏览 1 评论
1149 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
763 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1720 浏览 2 评论
1965浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
790浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
616浏览 3评论
631浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
593浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-14 10:55 , Processed in 1.115981 second(s), Total 45, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (威廉希尔官方网站 图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号