首页 / 驱动算法 / CANopen专题

CANopen 认证级测试:一致性认证完整路径

前两篇(07 调试向、09 工具链向)解决"怎么把总线测好";这篇解决"怎么让产品通过认证"。核心是一句话:认证 = 标准依据 + 测试设备 + 测试机构 三要素闭环。本文给四层认证体系(ISO 11898-2 物理层 → ISO 11898-1/16845 协议层 → CiA 301/309 通信一致性 → CiA 402 设备一致性 + EMC)、认证完整路径(CTT 预测试 → 认可实验室 → 测试报告 → 证书注册)、物理层与协议层判据表、通信/设备一致性用例组、故障注入在认证用例中的角色(衔接上轮 TH7011 干扰仪),配认证用例执行模拟器与可编译自测代码。

1. 认证与自测的分界:为什么"能通信"不等于"能认证"

很多产品做到"和自己的主站通信正常"就认为 CANopen 没问题,送测时却一堆失败。原因:自测验证的是"自己的系统内能跑",认证验证的是"符合标准规定、在任意合规系统中都能跑"。认证级测试与日常调试的分界在三个要素:

要素自测(07/09 篇)认证(本文)
标准依据无(按自己协议栈行为定预期)ISO 11898 / ISO 16845 / CiA 301 / CiA 309 / CiA 402
测试设备接口卡 + 示波器 + 软件脚本一致性测试工具(CTT)、干扰仪(TH7011/CANstress)、协议一致性设备(ISO 16845)
测试机构开发工程师经认可的一致性测试实验室,出正式报告

为什么要有机构?因为一致性测试的结论必须可信、可复现、可追溯:同一套用例、同一判据,换一个人测结果必须一样。自测的价值是把产品"预筛"到大概率一次通过,省的是送测的时间和费用(认证按次收费,失败重测另计)。

2. 认证体系全景:四层 + EMC

CANopen 认证不是一个单一测试,而是分层堆叠——从物理层到应用层逐层认定,每层标准不同:

层级测什么标准依据典型设备
物理层CAN 收发器电气参数:差分电压、对称性、共模、短路保护、采样点ISO 11898-2(收发器)/ -5(低速容错)示波器 + 一致性软件(Vector/周立功 CANScope)
协议层CAN 控制器协议行为:位时序、填充、CRC、错误处理、bus-off 恢复ISO 11898-1 + ISO 16845(协议一致性测试)支持 16845 测试模式的设备(TOSUN TH7012 / CANstress 类)
通信一致性NMT、SDO、PDO、心跳、紧急报文、节点监控等通信对象行为CiA 301 + CiA 309 一致性测试规范CiA 一致性测试工具(CTT)
设备一致性行规行为:CiA 402 状态机、控制字/状态字组合、模式切换CiA 402 + CiA 309(设备行规部分)CTT + 行规测试套件
EMC(附加)传导发射/抗扰、瞬态(GB/T 21437 / ISO 11452 / CISPR 25)按市场要求EMC 实验室

对 CANopen 设备,关键认证是第 3、4 层(CiA 一致性),多数场合第 1、2 层由控制器/收发器芯片厂商(如 ST、NXP、TI)的 datasheet 背书即可;但如果你的产品要过主机厂的整车级要求(车规),四层全要 + EMC。你站里的 C00 锁盒 / D00 展臂机这类工业从站,认证重心在 CiA 301 通信一致性 + CiA 402(如走运动控制)。

3. 认证路径:CTT 预测试 → 实验室 → 报告 → 证书

完整路径(按时间顺序):

① 内部预测试(自己人做)*/ 用 CiA 一致性测试工具(CTT)跑通信 + 行规用例,修掉所有失败/警告 准备: 设备样机 + 正确 EDS/DCF + 行规对象齐备(0x1000~0x1029 通信对象区) */ ② 提交认证申请(联系认证机构)*/ 提交: 设备资料、EDS、测试范围(通信一致性 / CiA 402 行规)、样机数量 */ ③ 送测(认可实验室执行)*/ 实验室按 CiA 309 用例组逐项执行,出正式测试报告 常见周期 2~6 周(含排队),失败项整改后重测该组 */ ④ 报告与证书 */ 通过 → 测试报告 + 一致性证书;产品可声明 "CANopen 认证设备" 注: 硬件/固件改动影响一致性时需重新评估相关用例组 */

四个提醒:

  • EDS 必须先行:CTT 靠 EDS 理解你的对象字典——EDS 和固件不一致,测试会因"找不到对象/类型不对"直接失败,这是送测失败的第一大原因;
  • 别把警告当通过:CTT 的 Warning(如 0x1001 错误寄存器未实现)不会判失败,但主机厂审查会看——能修就修;
  • 版本变更要复测:固件改了 NMT/PDO 行为、改了对象字典,一致性结论理论上失效,按变更范围复测相关组;
  • 物理层/EMC 分开认证:CiA 一致性不管电气,需要单独做 ISO 11898 物理层测试和 EMC 实验室测试。

4. 物理层认证测试:判据表

物理层测试针对你的总线接口电路(收发器 + 终端 + 保护),用示波器/一致性工具测量。核心判据(经典 CAN,ISO 11898-2):

测量项判据(经典 CAN)说明
显性差分电压 VDIFF(dom)1.5 ~ 3.0 V(典型 2V)显性位时 CANH−CANL;过低→驱动弱,过高→EMC 差
隐性差分电压 VDIFF(rec)|V| ≤ 0.5 V隐性位差分;偏离 0 → 终端/偏置问题
对称性(CANH/CANL 对地)两线隐性电平偏差小、共模漂移受限不对称→共模辐射增大,EMC 测试易挂
共模范围A 级 −2~+7 V(B 级 −12~+12 V 容错)超出→位错误/丢帧,长线或强干扰环境必测
输出内阻/驱动能力显性位驱动电流足够(与总线节点数匹配)节点过多/线过长→显性上不来
短路保护CANH/L 对地/对电源短路不损坏、可恢复车规必测项,工业现场也建议
采样点位时间 70~90% 区间(经典 CAN 常用 80~87.5%)采样点靠波特率配置计算,07/09 篇已详述
位时间容差收发器时钟偏差容限内(如 ±0.5%~±1.5% 按协议)配合干扰仪做位时序偏差测试(TH7011 专项)
物理层测试的常见坑

① 示波器探头地线阻抗引入的振铃会被误判为"信号差"——用短地线/弹簧地,或直接看一致性工具的模板(mask)测试;② 终端电阻要按最终拓扑配置(CANopen 规范 1M 以下允许 3~10 节点单终端,但认证按标准拓扑 2×120Ω 两端);③ 隐性电平受收发器上拉偏置影响,多节点时测"DUT 单独驱动"和"DUT 挂网上"两种状态。

5. 协议层认证测试(ISO 16845):控制器行为

ISO 16845 测的是 CAN 控制器的协议行为(不只是你的应用固件):位时序仲裁、填充/解填充、CRC、错误帧处理、bus-off 行为、重同步。这项测试必须用支持测试模式的设备(如 TOSUN TH7012 的 ISO 16845 模式、CANstress 类),普通接口卡做不了——这正是上轮说的"故障注入硬件"在认证中的位置。

用例组验证点典型操作
位时序同步段/传播段/相位段、重同步跳变宽度注入相位偏移,验证重同步
填充规则5 个相同位后插入填充位,解填充正确构造连续同极性数据帧
CRCCRC 计算正确、CRC 错误被检出干扰 CRC 位 → 应报错误帧
错误处理错误主动/被动转换、错误计数增减连续注入错误帧,观察 TEC/REC
bus-off256 次错误主动后进 bus-off,128×11 隐性位后恢复持续干扰 → 测恢复时序(见第 8 节)
仲裁ID 优先级仲裁、隐形→显性位胜出双节点同帧仲裁场景

务实提醒:绝大多数产品不会单独做这一层——因为你的控制器芯片(STM32 bxCAN / NXP / Microchip)出厂已通过 ISO 16845;只有"自研控制器 IP"或"芯片级供应商"才必须做。对做设备/模组的你,这层了解即可,重点在下面两层。

6. 通信一致性(CiA 301 + CiA 309 / CTT)

这是 CANopen 设备认证的核心。用 CiA 一致性测试工具(CTT)逐项跑 CiA 301 通信行规,常见用例组:

对象/机制用例要点常见失败原因
NMT启动/停止/预操作迁移、节点守卫时序NMT 响应延迟超时、状态迁移不符
SDOexpedited/segmented 传输、异常响应码(0xAB 系列)大对象没按分段发、异常码不标准
PDO映射正确、触发模式(事件/定时/SYNC)、RTR 行为映射表与 EDS 不符、SYNC 后未按节拍发
心跳心跳周期、生产者超时心跳周期超差(±20% 容差)
紧急报文错误寄存器 0x1001、EMCY 对象 0x1003故障不上报、错误寄存器不更新
节点监控Heartbeat/LifeGuard 超时后的行为超时后无动作或不进预操作
对象字典0x1000~0x1029 通信对象区齐备、类型正确缺 0x1001/0x1018、类型与 EDS 不一致

核心提示:CTT 逐项判"通过/失败",失败项必须整改后重测整组;交付前先自己跑一遍(第 11 节代码就是轻量自测骨架),把"EDS 与固件一致性"这个最大失败源提前掐掉。

7. 设备一致性(CiA 402):状态机与控制字-状态字组合

如果产品是伺服/运动类(你站里的主题),还需要过 CiA 402 行规一致性。这是第 10 篇控制字/状态字手册的"考试版"——用例按状态机迁移和命令组合设计:

用例组验证点判据(沿用第 10 篇锁定值)
上电迁移初始化 → Switch on disabled状态字 0x0240
主链迁移Shutdown→Ready→Switched on→Op enabled0x0006→0x0221 → 0x0007→0x0223 → 0x000F→0x0227
快停路径0x000F 清 bit2 → Quick stop active → 迁移 11/120x000B→0x0213 → 0x0006 回 Ready / 0x0000 断压
故障响应运行中注入故障 → Fault,Fault reset 复位0x0008 出现 → 0x0080 上升沿 → 回 0x0240
非法命令disabled 态直接给 0x000F应忽略,状态不变(位域组合+上下文判定)
模式切换6060h 请求 / 6061h 确认(PP/PV/PT/CSP 等)写后轮询 6061h 等于目标值

这些用例与第 10 篇的避坑表一一对应——第 10 篇修过的 0x000B、0x0213、0x0006 位描述,就是这类用例的判据来源。设备一致性失败几乎都源于状态机实现漏了旁路/回退路径,自测时把第 10 篇的迁移表逐条跑一遍。

8. 错误处理与故障注入:认证用例里的位置

衔接你上轮的"故障注入":在认证用例里,故障注入不是可选项,而是判据的一部分——测设备"遇到总线故障时行为是否合规":

  • 错误帧响应:干扰仪向总线注入错误帧,DUT 应正确检出、计数、按协议重发——判定"错误计数/重发行为合规";
  • 干扰特定位(TH7011 帧触发/软件触发):破坏 CRC 位/ACK 位,验证 DUT 的错误检出不误报也不漏报;
  • bus-off 行为:持续干扰把 DUT 打进 bus-off,验证"256 次错误→bus-off→128×11 隐性位后恢复"的规范时序,恢复后重同步正常;
  • 采样点/位时序偏差:干扰仪做位时序偏差测试,验证 DUT 采样点容差(对应第 4 节判据表最后两行)。
工具定位

TH7011/TH7012(TOSUN 干扰仪)覆盖"干扰特定位/错误帧触发/bus-off/位时序偏差",配 TSMaster 免驱即用——自测阶段就能把第 5、8 节这些用例跑齐;正式认证则由实验室的 CANstress/一致性设备执行,结论以实验室报告为准。

9. 测试环境搭建:接线、负载与参考节点

认证级测试的物理环境有硬性要求,提前搭好避免送测翻车:

  • 总线拓扑:按 CANopen 规范——两端 120Ω 终端(可带 DC 电源/偏置),总线长度按波特率(125k≤500m / 250k≤250m / 500k≤100m / 1M≤40m,参考值);
  • 负载配置:测 DUT 输出驱动时挂满额定节点数 + 线上干扰仪(干扰仪是额外负载,按说明书确认不影响电平判据);
  • 参考节点:一致性测试需要一个"行为完全合规"的参考节点(通常是 CTT/测试软件内嵌的虚拟节点)和 DUT 对打;
  • 电源与隔离:DUT 供电与测试设备隔离(光耦/USB 隔离),否则地环路会让物理层判据失真;
  • 波特率:认证通常按产品标称波特率测(如 500k),采样点按产品配置——先算好并写进 EDS/文档。

10. 交互演示:认证用例执行模拟器

四层认证体系各选代表用例,点击执行看"步骤 → 判据 → 结论",模拟 CTT 的判定流程(示意,非真实认证结果):

CANopen 一致性用例执行模拟器
用例组: 就绪 · 选择用例组开始
  • ① 物理层:显性/隐性差分电压、采样点判据——超范围判失败(如 VDIFF(dom) < 1.5V);
  • ② 协议层:CRC 干扰 → 应检出错帧;持续干扰 → bus-off 时序;
  • ③ 通信一致性:NMT 迁移、SDO 异常码、心跳超时;
  • ④ 设备一致性:沿用第 10 篇锁定值——0x0006→0x0221→0x000F→0x0227 主链、0x000B→0x0213 快停。

11. 可编译自测代码 + 送测清单

下面是基于 SocketCAN 的轻量一致性自测骨架(通信层),在送测前跑一遍,重点抓"EDS 与固件不一致"这类硬伤。

/* cert_self_test.c —— CANopen 一致性预筛骨架(Linux SocketCAN) 编译: gcc -O2 -o cert_self_test cert_self_test.c -lpthread 运行: sudo ./cert_self_test can0 说明: 预筛四组:NMT 迁移 / SDO 读写 / 心跳超时 / 紧急报文;真实认证以实验室为准 */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <linux/can.h> #include <linux/can/raw.h> #include <sys/socket.h> #include <net/if.h> #include <sys/ioctl.h> #define NODE 0x01 /* DUT 节点号 */ #define COB_NMT 0x000 #define COB_SDO_TX 0x600 #define COB_SDO_RX 0x580 #define COB_EMCY 0x080 int open_can(const char *ifname) { int s = socket(PF_CAN, SOCK_RAW, CAN_RAW); struct ifreq ifr; strcpy(ifr.ifr_name, ifname); ioctl(s, SIOCGIFINDEX, &ifr); struct sockaddr_can addr = { .can_family = AF_CAN, .can_ifindex = ifr.ifr_ifindex }; if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind"); return -1; } return s; } void send_frame(int s, uint32_t id, uint8_t *d, int len) { struct can_frame f = { .can_id = id, .can_dlc = len }; memcpy(f.data, d, len); write(s, &f, sizeof(f)); } int wait_can(int s, uint32_t id, struct can_frame *out, int ms) { struct timeval tv = { .tv_sec = ms/1000, .tv_usec = (ms%1000)*1000 }; setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); for (;;) { struct can_frame f; int n = read(s, &f, sizeof(f)); if (n < 0) return -1; if ((f.can_id & 0x7FF) == id) { *out = f; return 0; } } } int test_nmt(int s) { /* NMT 迁移: 启动 → 预操作 → 停止 → 启动 */ uint8_t d[] = { 0x80, NODE }; send_frame(s, COB_NMT, d, 2); /* 启动(进入 Op) */ uint8_t d2[] = { 0x01, NODE }; send_frame(s, COB_NMT, d2, 2); /* 停止 */ usleep(50000); struct can_frame f; return wait_can(s, COB_SDO_RX|NODE, &f, 200) == 0 ? 0 : -1; /* 停止后不应有活动 → 有帧即异常 */ } int test_sdo(int s) { /* SDO 读 1000h (设备类型) */ uint8_t d[] = { 0x40, 0x00, 0x10, 0x00, 0,0,0,0 }; send_frame(s, COB_SDO_TX|NODE, d, 8); struct can_frame f; if (wait_can(s, COB_SDO_RX|NODE, &f, 500) < 0) return -1; /* 无响应 */ if (f.data[0] != 0x43) return -2; /* 非 expedited 读响应 */ printf(" 设备类型 0x1000 = 0x%02X%02X%02X%02X\n", f.data[7],f.data[6],f.data[5],f.data[4]); return 0; } int main(int argc, char **argv) { int s = open_can(argc>1 ? argv[1] : "can0"); if (s < 0) return 1; printf("== CANopen 一致性预筛 ==\n"); printf("[1] SDO 读对象字典 1000h: %s\n", test_sdo(s) == 0 ? "PASS" : "FAIL"); printf("[2] NMT 迁移(启动/停止): %s\n", test_nmt(s) == 0 ? "PASS" : "FAIL"); printf("注意: 这只是预筛;心跳超时/紧急报文/bus-off 需配合干扰仪与 CTT\n"); close(s); return 0; }

送测清单(出发前核对):

项内容
样机≥2 台(含最终版本固件)、标称波特率配置、产品说明书
EDS/DCF与固件完全一致(对象类型、映射、默认值逐项核对)
自测记录CTT 预测试报告 + 本骨架输出(证明已预筛)
环境供电、总线线缆、终端电阻、隔离工具(现场备用)
变更说明固件版本、硬件版本、与上次送测的差异(复测用)

一句话收尾:认证 = 标准依据 + 测试设备 + 测试机构三要素闭环;产品能不能过,七成在送测前——EDS 与固件一致、状态机旁路路径齐全、自测用例跑齐。把第 10 篇的迁移表和本文的用例组对照跑一遍,送测就是走流程。