机器人关节多轴CAN网络报文过滤实战:SJA1000验收滤波器ACR/AMR四种模式讲透

六轴关节驱动器加一个网关挂在同一根 CAN 总线上,报文能通不代表 CPU 不被无关帧淹没。SJA1000 用 4 个验收码寄存器 ACR 加 4 个验收屏蔽寄存器 AMR,在硬件层决定收不收,单滤波/双滤波乘标准帧/扩展帧共四种模式。本文讲清屏蔽规则、位映射、ID 规划与初始化代码,附六坑对照表。

2026-10-06
SJA1000验收滤波器CAN总线机器人关节报文过滤ID规划

机器人多轴关节驱动器、伺服网关、物联网 RTU 常常挂在同一根 CAN 总线上,波特率 500kbps 时总线每秒可跑几千帧,其中绝大多数与某个节点无关。能通不等于能用:如果所有帧都进 CPU 中断再由软件判断 ID,主循环会被无关报文切得七零八落,实时任务抖动、控制周期被拖长。SJA1000 的 验收滤波器把"收不收"这件事搬到硬件层——它用 4 个验收码寄存器(ACR0~ACR3)和 4 个验收屏蔽寄存器(AMR0~AMR3)组成滤波器,只有通过验收的帧才写入接收 FIFO 并置位接收标志。三条可落地的结论:第一,AMR 的某一位为 0 表示该位必须与 ACR 相同才接收,为 1 表示该位被屏蔽、与验收结果无关;第二,单滤波与双滤波、标准帧与扩展帧组合出四种滤波方式,双滤波可以拿一组专门做广播或组播;第三,滤波器必须在复位状态下写入,改完再退出复位。下面用四张表把它讲透。

一、为什么多轴关节网络必须做硬件验收滤波

CAN 是广播式总线,每个节点都能在物理层收到所有帧,是否"收下"由控制器的验收滤波器决定。软件过滤与硬件验收滤波的差别,在多轴高帧率场景下会被放大。

对比维度 软件过滤(全部进中断再判 ID) 硬件验收滤波(ACR/AMR)
过滤位置 CPU 中断服务程序内 CAN 控制器内部,进 FIFO 之前
中断次数 总线每一帧都触发一次 只有验收通过的帧触发
CPU 占用 随总线负载线性上升 与无关帧数量无关
实时性影响 无关帧挤占控制周期,抖动大 无关帧不产生中断,周期稳定
接收缓冲压力 无关帧可能挤占接收缓冲区造成超载 无关帧不进入 FIFO
适用场景 总线负载极低、帧种单一的调试阶段 多轴关节网络、网关、高帧率工业现场

关键判断是中断的"性价比"。以 6 轴关节网络为例,每轴每 1ms 上报一次位置、速度、电流,再加上网关轮询,总线负载很容易到 40%~60%。若所有帧都进中断,CPU 每秒要处理数千次与己无关的中断,而真正有用的可能只有几百次——硬件滤波就是把这几千次砍到几百次的那把刀。

二、ACR 与 AMR:一位一位决定"收不收"

验收滤波的规则只有一句话:所有 AMR 为 0 的位,ACR 与 CAN 帧的对应位必须相同才算验收通过;所有 AMR 为 1 的位,其验收功能被屏蔽,帧的该位与验收结果无关。ACR 与 AMR 永远成对工作,一个给"期望值",一个给"关心哪些位"。

一句话记住规则:AMR=0 的位是"必须匹配的位",AMR=1 的位是"随便的位"。把 AMR 全写 0,就是要求 ACR 与帧逐位相等;把 AMR 全写 1,就是无条件接收所有帧。

因此,AMR 决定了滤波器的"粗细":只想按高几位区分节点,就把低位对应的 AMR 置 1;要精确到某个 ID 的某一帧,就把对应位 AMR 置 0。这也是 CAN 网络上"分组地址"和"广播地址"能共存的底层机制。

三、四种滤波模式与位映射

SJA1000 兼容 CAN2.0B,既有标准帧(11 位标识符)又有扩展帧(29 位标识符),每种帧格式都有单滤波和双滤波,因此实际共有四种滤波方式。模式由方式寄存器 MOD 的验收滤波方式位 AFM 选择:AFM=1 为单滤波,AFM=0 为双滤波;帧格式则由发送信息帧的第 1 个字节最高位 FF 决定(FF=1 扩展帧,FF=0 标准帧)。

总线 CAN 帧 单滤波:一组滤波器 ACR0~3 + AMR0~3 双滤波:滤波器 1 ACR0/1 + AMR0/1(+ACR3/AMR3 部分位) 双滤波:滤波器 2 ACR2(/3) + AMR2(/3) 接收 FIFO 64 字节,置位 RBS 通过 双滤波:任一滤波器通过即接收
图1:单滤波只有一组 ACR/AMR;双滤波把 4 组寄存器拆成两个滤波器,任一通过即收下
滤波方式 帧格式 参与滤波的位 寄存器映射
单滤波(AFM=1) 标准帧 11 位标识符 + RTR + 数据场前 2 字节 ID 与 RTR → ACR0/AMR0、ACR1/AMR1(低 4 位未用);Data1 → ACR2/AMR2;Data2 → ACR3/AMR3
扩展帧 29 位标识符 + RTR 依次对应 ACR0~ACR3、AMR0~AMR3(ACR3/AMR3 低 2 位未用)
双滤波(AFM=0) 标准帧 滤波器1:11 位 ID + RTR + 数据场第 1 字节(共 20 位);滤波器2:11 位 ID + RTR 滤波器1 = ACR0/1 + AMR0/1 及 ACR3/AMR3 低 4 位;滤波器2 = ACR2/AMR2 及 ACR3/AMR3 高 4 位
扩展帧 滤波器1 与滤波器2 均只匹配 29 位标识符的高 16 位 滤波器1 = ACR0/1 + AMR0/1;滤波器2 = ACR2/3 + AMR2/3

这里有两个容易踩的坑。第一,标准帧单滤波时数据场的前两个字节参与了滤波,它们不能再当普通用户数据用;如果接收的标准帧数据场长度不足 2 字节,缺少的部分可以不参与滤波。第二,扩展帧双滤波只匹配 29 位标识符的高 16 位,低 13 位是"随便的位",这意味着用双滤波做扩展帧分组时,组内 ID 的低 13 位可以自由分配给不同节点。

四、ID 规划实战:双滤波同时做"单播 + 广播"

关节网络的典型需求是:节点既要收发给自己的单播帧,又要收全网广播帧。双滤波正好对应两个地址窗口。下面以一个 6 轴关节网络为例做 ID 规划,假设采用扩展帧、标识符高 16 位用于分组。

报文用途 标识符高 16 位 目标节点 滤波器归属 AMR 设置
本节点运动指令(单播) 0x1122 关节 1 驱动器 滤波器 1(ACR0/ACR1) AMR0/AMR1 = 0x00,逐位精确匹配
全网广播(同步/急停) 0x3344 所有节点 滤波器 2(ACR2/ACR3) AMR2/AMR3 = 0x00,逐位精确匹配
关节组组播(可选) 0x33xx 同一组关节 并入滤波器 2 AMR3 = 0x00FF,屏蔽低 8 位做组播
本节点状态上报(发送) 0x2211 网关 不参与接收滤波 由发送缓冲区第 2~4 字节写入

这样配置后,节点只会在"自己的单播帧"和"广播帧"到来时产生接收中断,其余关节的帧一律被硬件丢弃。若总线节点与消息种类不多,应尽量使用标准帧,每帧字节少、通讯速率更快;若要支持广播或组播,则宜采用双滤波,拿出一个滤波器专门做广播/组播地址,灵活性和抗干扰性都更好。

五、初始化与发送:代码怎么写

ACR 与 AMR 只能在复位状态下设置,所以初始化顺序必须是"进复位 → 写 ACR/AMR → 选模式 → 退出复位"。下面这段 C 代码对应上表的双滤波配置,可直接套到 8051/STM32 外扩 SJA1000 的驱动里。

/* SJA1000 验收滤波器初始化(PeliCAN 模式 + 双滤波)
 * 对应规划:滤波器1 = 0x1122(单播),滤波器2 = 0x3344(广播)
 * 注意:ACR/AMR 只能在复位状态下写入
 */
#define SJA_BASE   0x8000            /* 片选基址,按实际总线地址修改 */
#define REG(off)   (*(volatile unsigned char *)(SJA_BASE + (off)))

#define MOD   0x00   /* 方式寄存器 */
#define CMR   0x01   /* 命令寄存器 */
#define SR    0x02   /* 状态寄存器 */
#define CDR   0x1F   /* 时钟分频寄存器 */
#define ACR0  0x10   /* 验收码 0 */
#define AMR0  0x14   /* 验收屏蔽 0 */

void sja_filter_init(void)
{
    REG(MOD) = 0x01;                 /* MOD.0=1:进入复位状态(必须) */
    REG(CDR) = 0x80;                 /* CDR.7=1:选择 PeliCAN 模式 */

    /* 滤波器1:高16位 = 0x1122,AMR=0 表示逐位精确匹配 */
    REG(ACR0) = 0x11;
    REG(ACR0 + 1) = 0x22;
    /* 滤波器2:高16位 = 0x3344 */
    REG(ACR0 + 2) = 0x33;
    REG(ACR0 + 3) = 0x44;

    /* 屏蔽寄存器全 0:所有位都参与匹配(要组播可把对应位置 1) */
    REG(AMR0 + 0) = 0x00;
    REG(AMR0 + 1) = 0x00;
    REG(AMR0 + 2) = 0x00;
    REG(AMR0 + 3) = 0x00;

    REG(MOD) = 0x00;                 /* AFM=0 选双滤波,同时退出复位进入工作态 */
}

/* 发送一帧扩展帧(8 字节数据),标识符高16位 = 0x2211 */
void sja_send_frame(const unsigned char *data)
{
    while (!(REG(SR) & 0x04)) { }    /* SR.2=1 表示发送缓冲区已释放 */
    REG(16) = 0x88;                  /* 第1字节:FF=1 扩展帧 + DLC=8 */
    REG(17) = 0x22;                  /* 标识符高16位 */
    REG(18) = 0x11;
    REG(19) = 0x00;                  /* 标识符低13位(可任意) */
    REG(20) = 0x00;
    for (int i = 0; i < 8; i++) {
        REG(21 + i) = data[i];       /* CAN 地址 21~28 为数据场 */
    }
    REG(CMR) = 0x05;                 /* 请求发送 + 释放接收缓冲区 */
    while (!(REG(SR) & 0x08)) { }    /* SR.3=1 表示发送完成 */
}

两个细节:发送缓冲区与接收缓冲区共用 CAN 地址 16~28 这 13 个字节,发送时写入、接收时读出;地址 32~95 是接收 FIFO RAM,96~109 是发送信息备份,驱动里不要越界访问。接收侧通过访问接收信息计数器 RMC 可得知当前 FIFO 里已收到几帧。

六、与 STM32 bxCAN 滤波器组的对照

如果换成带 bxCAN 的 STM32,思路完全一样,只是寄存器换成了"滤波器组"。理解 ACR/AMR 之后,迁移到 bxCAN 只是查表换算。

概念 SJA1000 STM32 bxCAN
匹配值寄存器 ACR0~ACR3(4 个) FilterIdHigh / FilterIdLow
屏蔽寄存器 AMR0~AMR3(4 个) FilterMaskIdHigh / FilterMaskIdLow
滤波模式 单滤波 / 双滤波(AFM 位) 标识符掩码模式 / 标识符列表模式
资源数量 4 组 ACR/AMR STM32F1 为 14 个滤波器组,F4 双 CAN 可达 28 个
分配方式 固定映射,双滤波拆成两组 可绑定到 FIFO0/FIFO1,灵活分配
写入时机 必须在复位状态下写入 需先置 FINIT 位进入初始化模式

七、六个最容易踩的坑

现象 根因 处理
滤波器改了不生效 ACR/AMR 在非复位状态下写入被忽略 先置 MOD.0=1 进复位,写完再退出
收不到本该收到的帧 AMR 该位误置 1,把需要匹配的位屏蔽了 核对 AMR=0 的位是否与 ACR 一致
收到大量无关帧 AMR 全 1 或屏蔽位过多,等于放行所有帧 收紧 AMR,只屏蔽确实不关心的位
标准帧数据前 2 字节异常 单滤波下 Data1/Data2 被占用参与滤波 把需要过滤的数据放在第 3 字节之后
扩展帧双滤波分组失效 只匹配高 16 位,低 13 位被当成自由位 组播分组依据放在高 16 位,低 13 位规划给节点
总线重载时丢帧 接收 FIFO 溢出,超载能力不足 提高中断优先级及时读走,或提高波特率/降负载

八、总结

对多轴关节驱动器和工业物联网网关,验收滤波器的价值在于把"收不收"从 CPU 搬到硬件:4 个 ACR 加 4 个 AMR 组成滤波器,AMR=0 的位必须与 ACR 逐位相同,AMR=1 的位被屏蔽;单滤波/双滤波与标准帧/扩展帧组合出四种滤波方式,双滤波可拿一组专门做广播或组播,是"单播 + 广播"共存的标准做法。

落地记住三点:ACR/AMR 必须在复位状态下写入、AMR 决定滤波的粗细、标准帧单滤波会占用数据场前两个字节。把 ID 规划先做好再写滤波器,节点的中断次数和实时抖动都会明显下降。

还想接着看

本文基于《CAN 控制器 SJA1000 验收滤波器原理与应用》等技术资料整理优化,并结合机器人关节多轴 CAN 网络与工业物联网网关的工程实践进行了系统化梳理。

需要定制开发?

沧州艾诺威电子 — 国家高新技术企业,20+项国家专利
嵌入式系统开发 · 物联网方案 · AI智能硬件 · 一站式交付

立即微信咨询

电话:13930711029 | 邮箱:tech@czinv.com | 24小时内响应