结构体介绍
CAN_FilterTypeDeftypedef 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的板子上有用
CAN_TxHeaderTypeDeftypedef 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) 需要开启时间捕获模式
CAN_RxHeaderTypeDeftypedef 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
Filter设定说明
只有在CAN接收时会需要设置到Filter
接着来看看手册当中的Filter说明
这一段说明的其实就是CAN2.0A与CAN2.0B的Arbitration Field


Filter模式
IDMASK : 当设置为1则会去比对所接收到的ID与Register当中的ID相不相符,0则不比对。像下方这张图来说红色的部分就是会比对的ID位置必须与暂存器当中相同才可以通过。
以32bit来看最多只能写入一组ID去过滤而已

以16bit来看最多可写入两组ID,但只能识别标準模式下的ID


以32位元来看因为是IDLIST模式,可以设置两种ID来进行过滤

以16位元来看最多可设置四种ID来进行过滤

程式码範例
全域变数宣告
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);}
CAN2.0A 标準模式且Filter选为Maskint 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; //第一组可通过的IDCAN1Filter.FilterIdLow = 0x0000;CAN1Filter.FilterMaskIdHigh = 0x104<<5; //第二组可通过的IDCAN1Filter.FilterMaskIdLow = 0x0000;CAN1Filter.SlaveStartFilterBank = 0;}
可以看到使用逻辑分析仪后的测试结果,在ID为103与104时可通过Filter成功接收回来。
上方左移五位的原因是为了对齐32bit的高位,STDID为11位需要左移才能对齐。
CAN2.0B 扩展模式且Filter选为Maskint 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。