You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32F105双CAN总线16位列表模式过滤器仅前2组可用求助

双CAN总线STM32F105的16位列表模式CAN过滤器异常问题

配置具备双CAN总线的STM32F105时,遇到以下异常:16位列表模式下仅前2个过滤器组可正常工作,但相同配置在单CAN总线的STM32F103上运行正常。

相关代码

bool CanSetFilter(CAN_HandleTypeDef *can, uint8_t bank, uint16_t id1, uint16_t id2, uint16_t id3, uint16_t id4) {
  return CanSetFilterList16bit(can, bank, (uint32_t(id1)<<21) | (uint32_t(id2)<<5), (uint32_t(id3)<<21) | (uint32_t(id4)<<5), CAN_FILTERMODE_IDLIST, CAN_FILTERSCALE_16BIT, CAN_FILTER_FIFO0);
}

bool CanSetFilterList16bit(CAN_HandleTypeDef *can, uint8_t bank_num, uint32_t filter_id, uint32_t mask, uint32_t filter_mode, uint32_t filter_scale, uint32_t fifo) {
  CAN_FilterTypeDef sFilterConfig;
  sFilterConfig.FilterBank = bank_num;
  sFilterConfig.FilterMode = filter_mode;
  sFilterConfig.FilterScale = filter_scale;
  sFilterConfig.FilterFIFOAssignment = fifo;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.FilterIdHigh = filter_id&0xFFFF;
  sFilterConfig.FilterIdLow = filter_id>>16;
  sFilterConfig.FilterMaskIdHigh = mask&0xFFFF;
  sFilterConfig.FilterMaskIdLow = mask>>16;
  bool result = (HAL_CAN_ConfigFilter(can, &sFilterConfig ) == HAL_OK);
  return result;
}

// 应用过滤器
uint16_t canFilterIds[] = {
    0x076, 0x077, 0x07D, 0x167, 
    0x171, 0x204, 0x213, 0x217, 
    0x230, 0x3B3, 0x42F, 0x43E, // 这组分配到bank3,实际不生效
};

const int canFiltersCount = sizeof(canFilterIds) / sizeof(canFilterIds[0]);
int filter = 0;
for (int i=0; (i<canFiltersCount) && (filter<28); filter++) {
    uint32_t f1 = (i<canFiltersCount) ? canFilterIds[i++] : canFilterIds[i];
    uint32_t f2 = (i<canFiltersCount) ? canFilterIds[i++] : canFilterIds[i];
    uint32_t f3 = (i<canFiltersCount) ? canFilterIds[i++] : canFilterIds[i];
    uint32_t f4 = (i<canFiltersCount) ? canFilterIds[i++] : canFilterIds[i];
    CanSetFilter(&hcan1, filter, f1, f2, f3, f4);
}

调试情况

三次CanSetFilter(...)调用均执行成功,对应CAN_FilterTypeDef的配置参数符合预期:

  • 第1次调用配置bank0,对应ID:0x076、0x077、0x07D、0x167
  • 第2次调用配置bank1,对应ID:0x171、0x204、0x213、0x217
  • 第3次调用配置bank2,对应ID:0x230、0x3B3、0x42F、0x43E

但只有前两个过滤器组能正常匹配报文,第三个组完全不生效。

解决思路及修正示例

1. 检查双CAN过滤器组分配

STM32F105的28个过滤器组默认会在CAN1和CAN2之间拆分(通常前14组给CAN1,后14组给CAN2)。如果未手动指定分配规则,后续的过滤器组可能被分配给了CAN2,导致CAN1无法使用。

修正方法:在CAN初始化阶段,将所有过滤器组分配给CAN1:

// 在HAL_CAN_Init之后添加过滤器组分配配置
void MX_CAN1_Init(void) {
  CAN_FilterTypeDef sFilterConfig;

  hcan1.Instance = CAN1;
  hcan1.Init.Prescaler = 12;
  hcan1.Init.Mode = CAN_MODE_NORMAL;
  hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
  hcan1.Init.TimeSeg1 = CAN_BS1_8TQ;
  hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
  hcan1.Init.TimeTriggeredMode = DISABLE;
  hcan1.Init.AutoBusOff = ENABLE;
  hcan1.Init.AutoWakeUp = DISABLE;
  hcan1.Init.AutoRetransmission = ENABLE;
  hcan1.Init.ReceiveFifoLocked = DISABLE;
  hcan1.Init.TransmitFifoPriority = DISABLE;
  
  if (HAL_CAN_Init(&hcan1) != HAL_OK) {
    Error_Handler();
  }

  // 将所有28个过滤器组分配给CAN1(SlaveStartFilterBank设置为28表示CAN2无过滤器组)
  sFilterConfig.SlaveStartFilterBank = 28;
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
  sFilterConfig.FilterActivation = DISABLE;
  if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK) {
    Error_Handler();
  }
}

2. 修正16位列表模式的ID位映射

STM32 16位列表模式下,每个过滤器组的4个ID需要按照正确的位格式存储:标准ID(11位)需要左移5位,同时要带上帧类型标志(CAN_ID_STD、CAN_RTR_DATA)。原代码的位偏移(<<21、<<5)不符合16位过滤器的存储规则。

修正后的过滤器配置函数:

bool CanSetFilter(CAN_HandleTypeDef *can, uint8_t bank, uint16_t id1, uint16_t id2, uint16_t id3, uint16_t id4) {
  // 标准ID+数据帧的格式:(ID <<5) | CAN_ID_STD | CAN_RTR_DATA
  uint16_t id1_formatted = (id1 << 5) | CAN_ID_STD | CAN_RTR_DATA;
  uint16_t id2_formatted = (id2 << 5) | CAN_ID_STD | CAN_RTR_DATA;
  uint16_t id3_formatted = (id3 << 5) | CAN_ID_STD | CAN_RTR_DATA;
  uint16_t id4_formatted = (id4 << 5) | CAN_ID_STD | CAN_RTR_DATA;

  // 组合成32位值:高16位是第二个ID,低16位是第一个ID
  uint32_t filter_ids = ((uint32_t)id2_formatted << 16) | id1_formatted;
  // 列表模式下,Mask寄存器存储另外两个ID
  uint32_t filter_ids_ext = ((uint32_t)id4_formatted << 16) | id3_formatted;

  return CanSetFilterList16bit(can, bank, filter_ids, filter_ids_ext, CAN_FILTERMODE_IDLIST, CAN_FILTERSCALE_16BIT, CAN_FILTER_FIFO0);
}

bool CanSetFilterList16bit(CAN_HandleTypeDef *can, uint8_t bank_num, uint32_t filter_id, uint32_t mask, uint32_t filter_mode, uint32_t filter_scale, uint32_t fifo) {
  CAN_FilterTypeDef sFilterConfig;
  sFilterConfig.FilterBank = bank_num;
  sFilterConfig.FilterMode = filter_mode;
  sFilterConfig.FilterScale = filter_scale;
  sFilterConfig.FilterFIFOAssignment = fifo;
  sFilterConfig.FilterActivation = ENABLE;
  // 16位模式下:FilterIdHigh是第二个ID,FilterIdLow是第一个ID
  sFilterConfig.FilterIdHigh = (filter_id >> 16) & 0xFFFF;
  sFilterConfig.FilterIdLow = filter_id & 0xFFFF;
  // Mask寄存器存储第三、第四个ID,FilterMaskIdHigh是第四个,FilterMaskIdLow是第三个
  sFilterConfig.FilterMaskIdHigh = (mask >> 16) & 0xFFFF;
  sFilterConfig.FilterMaskIdLow = mask & 0xFFFF;

  return (HAL_CAN_ConfigFilter(can, &sFilterConfig ) == HAL_OK);
}

3. 验证单个过滤器组

单独测试第三个过滤器组,只配置bank2的4个ID,确认对应的报文是否能被接收,排除循环索引错误或报文本身的问题。


内容的提问来源于stack exchange,提问作者brigadir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 17:57:04