2. CAN标准数据帧发送配置

任务目标

在CAN控制器中配置标准帧(11位ID)的验收滤波器,使节点仅接收指定ID的报文,其余ID全部屏蔽。本案例以STM32F103的bxCAN外设为例,实现只接收ID为0x321的标准帧数据报文。

环境与依赖

  • 硬件:STM32F103系列开发板(含CAN收发器,如TJA1050)
  • 软件:STM32CubeIDE 或 Keil MDK,使用STM32标准外设库(SPL)
  • 已初始化:CAN外设时钟、GPIO(PA11=RX, PA12=TX)、CAN波特率(本案例使用500kbps)

核心原理

bxCAN提供28个滤波器组,每组可配置为掩码模式或列表模式。掩码模式下,通过ID掩码寄存器决定哪些位必须精确匹配、哪些位可忽略。本案例使用滤波器组0,掩码模式,仅匹配标准帧ID的bit[10:0]。

关键完整代码

#include "stm32f10x_can.h"

/* 滤波器配置:仅接收标准帧 ID = 0x321 */
void CAN_Filter_Config_StdID(void)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure;

    /* 使用滤波器组0 */
    CAN_FilterInitStructure.CAN_FilterNumber = 0;
    /* 掩码模式 */
    CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
    /* 32位宽度,适用于标准帧和扩展帧 */
    CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;

    /*
     * 标准帧ID存储在寄存器高16位(STID[10:0]对应bit[28:18])
     * 期望ID = 0x321,左移21位放入对应位置
     * 掩码 = 0x7FF 表示11位全部必须匹配
     */
    CAN_FilterInitStructure.CAN_FilterIdHigh = (uint16_t)(0x321 << 5);  // 高16位:ID左移5位
    CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
    CAN_FilterInitStructure.CAN_FilterMaskIdHigh = (uint16_t)(0x7FF << 5); // 掩码高16位
    CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;

    /* 关联到FIFO0 */
    CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FIFO0;
    CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;

    CAN_FilterInit(&CAN_FilterInitStructure);
}

/* 主程序调用示例(需先完成CAN外设初始化) */
void CAN_Receive_Only_0x321(void)
{
    CanRxMsg RxMessage;
    uint8_t data[8];

    /* 假设CAN已初始化并进入正常模式 */
    CAN_Filter_Config_StdID();

    while (1)
    {
        /* 等待FIFO0收到报文 */
        if (CAN_MessagePending(CAN1, CAN_FIFO0) > 0)
        {
            CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);

            /* 仅当ID匹配时处理(滤波器已保证,此处为双重校验) */
            if ((RxMessage.IDE == CAN_Id_Standard) && (RxMessage.StdId == 0x321))
            {
                for (int i = 0; i < RxMessage.DLC; i++)
                {
                    data[i] = RxMessage.Data[i];
                }
                /* 在此处处理接收到的数据 */
            }
        }
    }
}

配置说明

  • ID放置:标准帧11位ID在32位滤波器寄存器中位于bit[28:18],因此将0x321左移21位后,高16位为0x321 << 5,低16位为0。
  • 掩码设置:0x7FF左移5位得到0xFFE0,表示bit[28:18]全部为必须匹配位,其余位(RTR、IDE等)不参与过滤。
  • FIFO分配:匹配的报文进入FIFO0,通过CAN_MessagePending查询接收状态。

运行与验证

  1. 将上述代码加入已初始化CAN的工程中,编译下载至开发板。
  2. 使用另一块CAN节点或USB-CAN分析仪发送以下报文:
发送1:标准帧 ID=0x321, DLC=8, Data=0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08
发送2:标准帧 ID=0x322, DLC=8, Data=0xAA 0xBB 0xCC 0xDD 0xEE 0xFF 0x11 0x22
  1. 在CAN_Receive_Only_0x321的while循环中设置断点或通过串口打印接收到的数据。

通过条件:仅当发送ID=0x321的报文时,程序进入接收处理分支;发送ID=0x322的报文时,程序不进入接收分支(FIFO0无数据)。若需验证扩展帧也被屏蔽,可发送扩展帧ID=0x321,同样不应被接收。

常见问题

  • 滤波器配置后收不到任何报文:检查CAN_FilterIdHigh/IdLow的移位是否正确,确认掩码位与ID位对齐。
  • 所有ID都能收到:掩码寄存器被设为0,导致所有位不参与匹配。确认CAN_FilterMaskIdHigh值不为0。
  • 标准帧和扩展帧混淆:若需严格区分,可在掩码中增加IDE位(bit[2])的匹配,本案例未包含该设置,因此扩展帧ID=0x321也会通过滤波器(但代码中的双重校验会将其过滤)。