STM32-19 CAN-BUS (下)

结构体介绍

CAN_FilterTypeDef
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的板子上有用

CAN_TxHeaderTypeDef
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) 需要开启时间捕获模式

CAN_RxHeaderTypeDef
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


Filter设定说明

只有在CAN接收时会需要设置到Filter

接着来看看手册当中的Filter说明
http://img2.58codes.com/2024/20146325HKl44iHRqy.png
这一段说明的其实就是CAN2.0A与CAN2.0B的Arbitration Field

一个32bit的Filter,可以看到在CAN2.0B当中STDID的确有10个bit,EXTID有17个bit而剩余的就是IDE与RTR共 32bit,所以32位元的可以实现对标準与扩展的讯息过滤
http://img2.58codes.com/2024/20146325zKyc47Vb0o.png两个16bit的Filter,包含了CAN2.0A当中的11个STDID、1个IDE、1个RTR与3个EXTID,只能实现对标準模式的讯息过滤。
http://img2.58codes.com/2024/20146325CtOtqSEOxz.png

Filter模式

IDMASK : 当设置为1则会去比对所接收到的ID与Register当中的ID相不相符,0则不比对。像下方这张图来说红色的部分就是会比对的ID位置必须与暂存器当中相同才可以通过。
http://img2.58codes.com/2024/20146325UB39qM9Dvu.png
以32bit来看最多只能写入一组ID去过滤而已
http://img2.58codes.com/2024/20146325qLtlsPXpHw.png
以16bit来看最多可写入两组ID,但只能识别标準模式下的ID
http://img2.58codes.com/2024/2014632523jjYgbMy7.pngIDLIST : 所接收到的讯息当中ID必须与Filter Register当中所有的bit相同才会接收,只要有任何一个不相同则不接收
http://img2.58codes.com/2024/20146325eyPkKBvCr2.png
以32位元来看因为是IDLIST模式,可以设置两种ID来进行过滤
http://img2.58codes.com/2024/20146325iT2AL6FvNN.png
以16位元来看最多可设置四种ID来进行过滤
http://img2.58codes.com/2024/20146325qIouE0rlDA.png

程式码範例

全域变数宣告

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选为Mask
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);}

http://img2.58codes.com/2024/20146325jag8SQOFoD.png
经过逻辑分析仪后测试ID为105,这边是将Filter设定为Mask模式,且将MASKID都设置为1需要检验所接收到了ID是否与暂存器中ID相同。

CAN2.0A 标準模式且Filter选为IDLIST
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;}

http://img2.58codes.com/2024/201463251VTKYoBRu3.png
可以看到使用逻辑分析仪后的测试结果,在ID为103与104时可通过Filter成功接收回来。

上方左移五位的原因是为了对齐32bit的高位,STDID为11位需要左移才能对齐。

CAN2.0B 扩展模式且Filter选为Mask
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);}

http://img2.58codes.com/2024/20146325brNZ10mZVl.png

CAN2.0B 扩展模式且Filter选为IDLIST
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);}

http://img2.58codes.com/2024/20146325GJWwubqh7Y.png
上图可以看到对应的ID为0x1234ABCD与0x1234ABCE,Filter为LIST模式而32位宽的Filter当中可以设置两组EXTID来过滤。

当有好几组需要通过Filter时
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);}

http://img2.58codes.com/2024/20146325V9gQop4fTn.png
当有好几组需要设置的时候,这时候就可以使用编组来设置其余的过滤器ID,这边设置了编组0与编组1的ID。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章