3. CAN标准数据帧接收过滤配置

CAN标准数据帧接收过滤配置 学习卡片

任务目标

在CAN通信中,扩展帧使用29位标识符,当总线上存在多种报文时,控制器需要只接收特定ID的报文,过滤掉其余无关流量。本案例实现基于STM32 bxCAN外设的扩展帧ID过滤器配置,使硬件仅接收指定的扩展帧ID(例如0x18FF50E5),其余扩展帧报文全部被硬件过滤丢弃。

环境依赖

  • 硬件:STM32F103系列(bxCAN外设)
  • 软件:STM32CubeIDE 或 Keil MDK,HAL库
  • 时钟:CAN外设时钟已使能,波特率配置为500kbps(复用现有初始化)

核心实现

bxCAN提供14个过滤器组(F0~F13),每个过滤器组可配置为32位或16位模式。对于29位扩展帧ID过滤,使用32位过滤器组,将CAN_FxR1寄存器的高29位(STID[10:0]+EXID[17:0])与CAN_FxR2寄存器的高29位进行屏蔽比较。本案例配置过滤器组0,工作在屏蔽位模式,仅接收ID为0x18FF50E5的扩展帧。

/* 扩展帧ID过滤器配置 - 仅接收ID=0x18FF50E5 */
void CAN_Filter_ExtID_Config(CAN_HandleTypeDef *hcan)
{
    CAN_FilterTypeDef sFilterConfig;

    /* 过滤器组0,32位屏蔽位模式 */
    sFilterConfig.FilterBank = 0;
    sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
    sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;

    /* 期望接收的扩展帧ID: 0x18FF50E5
     * 29位ID在寄存器中的布局:
     * bit[31:21] = STID[10:0] (标准ID部分,扩展帧中为ID的高11位)
     * bit[20:3]  = EXID[17:0] (扩展ID部分)
     * bit[2:0]   = 不使用,置0
     */
    uint32_t ext_id = 0x18FF50E5;
    uint32_t filter_id = (ext_id & 0x1FFFFFFF) << 3;  /* 左移3位对齐到寄存器位 */

    /* 屏蔽寄存器:全部匹配,不允许忽略任何位 */
    uint32_t mask_id = 0x1FFFFFFF << 3;  /* 高29位全1,低3位为0 */

    sFilterConfig.FilterIdHigh = (uint16_t)(filter_id >> 16);
    sFilterConfig.FilterIdLow  = (uint16_t)(filter_id & 0xFFFF);
    sFilterConfig.FilterMaskIdHigh = (uint16_t)(mask_id >> 16);
    sFilterConfig.FilterMaskIdLow  = (uint16_t)(mask_id & 0xFFFF);

    sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
    sFilterConfig.FilterActivation = ENABLE;

    if (HAL_CAN_ConfigFilter(hcan, &sFilterConfig) != HAL_OK)
    {
        Error_Handler();
    }
}

/* 使用示例:在CAN初始化后调用 */
int main(void)
{
    /* ... 系统时钟、GPIO、CAN初始化代码 ... */

    CAN_Filter_ExtID_Config(&hcan);

    /* 启动CAN并开启FIFO0中断(或轮询接收) */
    HAL_CAN_Start(&hcan);
    HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);

    while (1)
    {
        /* 主循环 */
    }
}

验证方法

  1. 使用CAN分析仪或另一块开发板发送扩展帧ID=0x18FF50E5的报文,观察接收端能正常进入接收中断或查询到FIFO中有数据。
  2. 发送其他扩展帧ID(如0x18FF50E6、0x00FF1122)和任意标准帧,确认接收端不产生任何接收事件。
  3. 通过调试器查看寄存器CAN_FSR(过滤器状态寄存器)确认过滤器组0已激活,或观察HAL_CAN_GetRxFifoFillLevel返回值:仅当发送匹配ID时该值递增。

通过条件:发送匹配ID报文时接收成功;发送非匹配ID报文时,FIFO接收计数保持为0,证明硬件过滤生效。