STM32 双CAN中Filter配置
过滤器配置示例代码:
1 CAN_FilterConfTypeDef can_filter; 2 3 /* CAN's filter banks configuration. */ 4 // can_filter.BankNumber = 5; // Valid after the last time configration. 5 can_filter.FilterNumber = 3; 6 can_filter.FilterMode = CAN_FILTERMODE_IDMASK; 7 can_filter.FilterScale = CAN_FILTERSCALE_32BIT; 8 can_filter.FilterIdHigh = 0; 9 can_filter.FilterIdLow = 0; 10 can_filter.FilterMaskIdHigh = 0; 11 can_filter.FilterMaskIdLow = 0; 12 can_filter.FilterFIFOAssignment = CAN_FIFO0; 13 can_filter.FilterActivation = ENABLE; 14 HAL_CAN_ConfigFilter(&hcan1, &can_filter); // Only CAN1 own filter banks, CAN2 just read it. 15 16 // can_filter.BankNumber = 5; // Valid after the last time configration. 17 can_filter.FilterNumber = 4; 18 can_filter.FilterMode = CAN_FILTERMODE_IDMASK; 19 can_filter.FilterScale = CAN_FILTERSCALE_32BIT; 20 can_filter.FilterIdHigh = 0; 21 can_filter.FilterIdLow = 0; 22 can_filter.FilterMaskIdHigh = 0; 23 can_filter.FilterMaskIdLow = 0; 24 can_filter.FilterFIFOAssignment = CAN_FIFO0; 25 can_filter.FilterActivation = ENABLE; 26 HAL_CAN_ConfigFilter(&hcan1, &can_filter); // Only CAN1 own filter banks, CAN2 just read it. 27 28 // can_filter.BankNumber = 5; // Valid after the last time configration. 29 can_filter.FilterNumber = 5; 30 can_filter.FilterMode = CAN_FILTERMODE_IDMASK; 31 can_filter.FilterScale = CAN_FILTERSCALE_32BIT; 32 can_filter.FilterIdHigh = 0; 33 can_filter.FilterIdLow = 0; 34 can_filter.FilterMaskIdHigh = 0; 35 can_filter.FilterMaskIdLow = 0; 36 can_filter.FilterFIFOAssignment = CAN_FIFO0; 37 can_filter.FilterActivation = ENABLE; 38 HAL_CAN_ConfigFilter( &hcan1, &can_filter ); // Only CAN1 own filter banks, CAN2 just read it. 39 40 can_filter.BankNumber = 5; // Valid after this time configration. 41 can_filter.FilterNumber = 6; 42 can_filter.FilterMode = CAN_FILTERMODE_IDMASK; 43 can_filter.FilterScale = CAN_FILTERSCALE_32BIT; 44 can_filter.FilterIdHigh = 0; 45 can_filter.FilterIdLow = 0; 46 can_filter.FilterMaskIdHigh = 0; 47 can_filter.FilterMaskIdLow = 0; 48 can_filter.FilterFIFOAssignment = CAN_FIFO0; 49 can_filter.FilterActivation = ENABLE; 50 HAL_CAN_ConfigFilter( &hcan1, &can_filter ); // Only CAN1 own filter banks, CAN2 just read it.
请注意:
1. 以上配置均通过调用 "HAL_CAN_ConfigFilter( &hcan1, &can_filter)" 生效。这是因为STM32F107中的双路CAN共用过滤器组,而且过滤器组寄存器与CAN1配置寄存器在物理上是挨着的,HAL库将这些寄存器合并在一个结构里访问而已。
1 /** 2 * @brief Controller Area Network 3 */ 4 5 typedef struct 6 { 7 __IO uint32_t MCR; 8 __IO uint32_t MSR; 9 __IO uint32_t TSR; 10 __IO uint32_t RF0R; 11 __IO uint32_t RF1R; 12 __IO uint32_t IER; 13 __IO uint32_t ESR; 14 __IO uint32_t BTR; 15 uint32_t RESERVED0[88]; 16 CAN_TxMailBox_TypeDef sTxMailBox[3]; 17 CAN_FIFOMailBox_TypeDef sFIFOMailBox[2]; 18 uint32_t RESERVED1[12]; 19 __IO uint32_t FMR; 20 __IO uint32_t FM1R; 21 uint32_t RESERVED2; 22 __IO uint32_t FS1R; 23 uint32_t RESERVED3; 24 __IO uint32_t FFA1R; 25 uint32_t RESERVED4; 26 __IO uint32_t FA1R; 27 uint32_t RESERVED5[8]; 28 CAN_FilterRegister_TypeDef sFilterRegister[28]; 29 } CAN_TypeDef;
显然对于CAN2->FMR及后面的寄存器没有意义。
2. 最后一组过滤器配置中使用了 “can_filter.BankNumber” 项。作用是将过滤器组分成两个段,第一段为CAN1使用(范围是:0~BankNumber-1),第二段为CAN2使用(范围是:BankNumber~27)。
也就是说当CAN1上收到消息,STM32会在0~BankNumer-1这些过滤器中依次查询是否通过过滤,如果通过则将消息放入配置好的CAN1的FIFO里面等待使用,否则就丢弃。
当CAN2上收到消息,STM32会在BankNumer~27这些过滤器中依次查询是否通过过滤,如果通过则将消息放入配置好的CAN2的FIFO里面等待使用,否则就丢弃。
上述代码配置了四组过滤器(滤波内容无意义,这里只讨论过滤器组是否可用)。
1. 编号为3的过滤器
2. 编号为4的过滤器
3. 编号为5的过滤器
4. 编号为6的过滤器
并在最后一组配置中使BankNumber=5,意味着CAN1可以使用编号为3,4的过滤器,CAN2可以使用编号为5,6的过滤器。
结论:STM32F107中CAN1和CAN2共用过滤器组,通过FMR寄存器中的CAN2SB段将过滤器组分为两段分别给CAN1和CAN2使用,也可以完全配置给一路CAN使用。应该说增加了CAN的使用灵活性,但配套的API却不全面,难以使用。
最后附上BankNumber配置不同的值时的测试结果:
BankNumber(FMR->CAN2SB) |
对于CAN1生效的过滤器段 |
对于CAN2生效的过滤器段 |
0 |
0 |
0~27 |
num = 1~27 |
0~num-1 |
num~27 |