過濾器配置示例代碼:
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 |