typedef struct
{
uint32_t FilterIdHigh;
uint32_t FilterIdLow;
uint32_t FilterMaskIdHigh;
uint32_t FilterMaskIdLow;
uint32_t FilterFIFOAssignment;
uint32_t FilterBank;
uint32_t FilterMode;
uint32_t FilterScale;
uint32_t FilterActivation;
uint32_t SlaveStartFilterBank;
} CAN_FilterTypeDef;
FilterIdHigh : 16bit 用來放STDID
FilterIdLow : 16 bit 用來放EXTID
FilterMaskIdHigh : 依模式選擇 Mask 1 需比對 0不比對 LIST模式下設置第二組ID
FilterMaskIdLow : 依模式選擇 Mask 1 需比對 0不比對 LIST模式下設置第二組ID
FilterFIFOAssignment : 選擇相關聯的FIFO編號 假設使用RX0 就填入 CAN_RX_FIFO0
FilterBank : 濾波器編組 根據板子不同可分為 0-13 or 0-27 (我這塊板子只有14個也就是0-13)
FilterMode : Filter模式選擇 有兩種 LIST 跟MASK
FilterScale : 選擇Filter位寬 分為16與32bit (CAN_FILTERSCALE_32BIT , CAN_FILTERSCALE_16BIT)
FilterActivation : 啟用Filter (CAN_FILTER_ENABLE)
SlaveStartFilterBank : 只有在雙CAN的板子上有用
typedef struct
{
uint32_t StdId;
uint32_t ExtId;
uint32_t IDE;
uint32_t RTR;
uint32_t DLC;
FunctionalState TransmitGlobalTime;
} CAN_TxHeaderTypeDef;
StdId : 標準模式ID (11 bit)
ExtId : 擴展模式ID (32 bit)
IDE : 表示是擴展還標準(CAN_ID_STD , CAN_ID_EXT)
RTR : 表示是資料訊息還是遠端請求 (CAN_RTR_DATA , CAN_RTR_REMOTE)
DLC : 表示傳送資料長度 0-8 bytes
TransmitGlobalTime : 指定是否在傳輸開始時捕獲時間戳計數器當中的值,透過DATA6 和 DATA7發送,也就是會替換 pData[6] 和 pData[7]。(ENABLE , DISABLE) 需要開啟時間捕獲模式
typedef struct
{
uint32_t StdId;
uint32_t ExtId;
uint32_t IDE;
uint32_t RTR;
uint32_t DLC;
uint32_t Timestamp;
uint32_t FilterMatchIndex;
} CAN_RxHeaderTypeDef;
StdId : 標準模式ID (11 bit)
ExtId : 擴展模式ID (32 bit)
IDE : 表示是擴展還標準(CAN_ID_STD , CAN_ID_EXT)
RTR : 表示是資料訊息還是遠端請求 (CAN_RTR_DATA , CAN_RTR_REMOTE)
DLC : 表示傳送資料長度 0-8 bytes
Timestamp : 指定在訊息接收開始時捕獲的時間戳計數器當中的值。 需要開啟時間捕獲模式
FilterMatchIndex : 指定配對哪一個Filter元素的Index
只有在CAN接收時會需要設置到Filter
接著來看看手冊當中的Filter說明
這一段說明的其實就是CAN2.0A與CAN2.0B的Arbitration Field
全域變數宣告
uint8_t send_data[8] = {0,1,2,3,4,5,6,7}; //傳送的資料
uint8_t rece_data[8]; //接收的Buffer
CAN_TxHeaderTypeDef TxHeader;
CAN_RxHeaderTypeDef RxHeader;
uint32_t TxMailBox;
使用RX中斷去接收訊息
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, rece_data);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
ConfigFliter();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
TxHeader.DLC =8;
TxHeader.ExtId = 0;
TxHeader.IDE = CAN_ID_STD;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.StdId = 0x105;
TxHeader.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, send_data, &TxMailBox);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void ConfigFliter(void)
{
CAN_FilterTypeDef CAN1Filter;
CAN1Filter.FilterActivation = CAN_FILTER_ENABLE;
CAN1Filter.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN1Filter.FilterMode = CAN_FILTERMODE_IDMASK;
CAN1Filter.FilterScale = CAN_FILTERSCALE_32BIT;
CAN1Filter.FilterBank = 0;
CAN1Filter.FilterIdHigh = 0x105<<5;
CAN1Filter.FilterIdLow = 0x0000;
CAN1Filter.FilterMaskIdHigh = 0x1111;
CAN1Filter.FilterMaskIdLow = 0x1111;
CAN1Filter.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan1, &CAN1Filter);
}
經過邏輯分析儀後測試ID為105,這邊是將Filter設定為Mask模式,且將MASKID都設置為1需要檢驗所接收到了ID是否與暫存器中ID相同。
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
ConfigFliter();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
for(int x = 0 ; x<2 ;x++)
{
TxHeader.DLC =8;
TxHeader.ExtId = 0;
TxHeader.IDE = CAN_ID_STD;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.StdId = 0x103+x;
TxHeader.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, send_data, &TxMailBox);
HAL_Delay(100);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void ConfigFliter(void)
{
CAN_FilterTypeDef CAN1Filter;
CAN1Filter.FilterActivation = CAN_FILTER_ENABLE;
CAN1Filter.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN1Filter.FilterMode = CAN_FILTERMODE_IDLIST;
CAN1Filter.FilterScale = CAN_FILTERSCALE_32BIT;
CAN1Filter.FilterBank = 0;
CAN1Filter.FilterIdHigh = 0x103<<5; //第一組可通過的ID
CAN1Filter.FilterIdLow = 0x0000;
CAN1Filter.FilterMaskIdHigh = 0x104<<5; //第二組可通過的ID
CAN1Filter.FilterMaskIdLow = 0x0000;
CAN1Filter.SlaveStartFilterBank = 0;
}
可以看到使用邏輯分析儀後的測試結果,在ID為103與104時可通過Filter成功接收回來。
上方左移五位的原因是為了對齊32bit的高位,STDID為11位需要左移才能對齊。
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
ConfigFliter();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
TxHeader.DLC =8;
TxHeader.IDE = CAN_ID_EXT;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.ExtId = 0x1234ABCD;
TxHeader.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, send_data, &TxMailBox);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void ConfigFliter(void)
{
CAN_FilterTypeDef CAN1Filter;
CAN1Filter.FilterActivation = CAN_FILTER_ENABLE;
CAN1Filter.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN1Filter.FilterMode = CAN_FILTERMODE_IDMASK;
CAN1Filter.FilterScale = CAN_FILTERSCALE_32BIT;
CAN1Filter.FilterBank = 0;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABCD<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter.FilterMaskIdHigh = 0;
CAN1Filter.FilterMaskIdLow = 0;
CAN1Filter.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan1, &CAN1Filter);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
ConfigFliter();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
for(int x = 0 ; x<2 ;x++)
{
TxHeader.DLC =8;
TxHeader.ExtId = 0x1234ABCD+x;
TxHeader.IDE = CAN_ID_EXT;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, send_data, &TxMailBox);
HAL_Delay(100);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void ConfigFliter(void)
{
CAN_FilterTypeDef CAN1Filter;
CAN1Filter.FilterActivation = CAN_FILTER_ENABLE;
CAN1Filter.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN1Filter.FilterMode = CAN_FILTERMODE_IDLIST;
CAN1Filter.FilterScale = CAN_FILTERSCALE_32BIT;
CAN1Filter.FilterBank = 0;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABCD<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABCE<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan1, &CAN1Filter);
}
上圖可以看到對應的ID為0x1234ABCD與0x1234ABCE,Filter為LIST模式而32位寬的Filter當中可以設置兩組EXTID來過濾。
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_CAN1_Init();
/* USER CODE BEGIN 2 */
ConfigFliter();
HAL_CAN_Start(&hcan1);
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
for(int x = 0 ; x<4 ;x++)
{
TxHeader.DLC =8;
TxHeader.ExtId = 0x1234ABCD+x;
TxHeader.IDE = CAN_ID_EXT;
TxHeader.RTR = CAN_RTR_DATA;
TxHeader.TransmitGlobalTime = DISABLE;
HAL_CAN_AddTxMessage(&hcan1, &TxHeader, send_data, &TxMailBox);
HAL_Delay(100);
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
void ConfigFliter(void)
{
CAN_FilterTypeDef CAN1Filter;
CAN1Filter.FilterActivation = CAN_FILTER_ENABLE;
CAN1Filter.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN1Filter.FilterMode = CAN_FILTERMODE_IDLIST;
CAN1Filter.FilterScale = CAN_FILTERSCALE_32BIT;
CAN1Filter.FilterBank = 0;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABCD<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABCE<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter.SlaveStartFilterBank = 0;
CAN_FilterTypeDef CAN1Filter1;
CAN1Filter1.FilterActivation = CAN_FILTER_ENABLE;
CAN1Filter1.FilterFIFOAssignment = CAN_RX_FIFO0;
CAN1Filter1.FilterMode = CAN_FILTERMODE_IDLIST;
CAN1Filter1.FilterScale = CAN_FILTERSCALE_32BIT;
CAN1Filter1.FilterBank = 1;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABCF<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter.FilterIdHigh = ((0x1234ABCD<<3)>>16) & 0xffff;
CAN1Filter.FilterIdLow =((0x1234ABD0<<3)& 0xffff) | CAN_ID_EXT;
CAN1Filter1.SlaveStartFilterBank = 0;
HAL_CAN_ConfigFilter(&hcan1, &CAN1Filter);
HAL_CAN_ConfigFilter(&hcan1, &CAN1Filter1);
}
當有好幾組需要設置的時候,這時候就可以使用編組來設置其餘的過濾器ID,這邊設置了編組0與編組1的ID。