2. CANopen协议核心机制
在Anybus CANopen设备网关工程中,网关并不是简单地“转发CAN帧”,而是要在CANopen应用层语义上理解从站设备的行为。CANopen把每个节点的可访问数据组织成一张对象字典(Object Dictionary, OD),并用索引(Index,16位)与子索引(Subindex,8位)定位。网关要做的第一件事,就是建立“索引/子索引 → 物理量/状态”的映射表,否则收到的报文只是无意义的字节流。
对象字典中与通信最相关的区域是:0x1000~0x1029的通信参数区(设备类型、错误寄存器、心跳/节点保护时间、PDO映射与通信参数等),0x1400/0x1600的RPDO通信与映射参数,0x1800/0x1A00的TPDO通信与映射参数,以及0x2000以上的制造商自定义区。网关通常只解析自己关心的条目,例如0x1018厂商ID、0x1001错误寄存器、0x1800子索引2的传输类型、0x1A00映射内容等。
CANopen的通信对象分为四类:PDO(过程数据对象,用于实时I/O)、SDO(服务数据对象,用于参数读写)、NMT(网络管理,控制节点状态)、以及心跳/节点保护(用于节点存活监控)。网关必须同时处理这四类报文,才能既保证实时性,又保证配置与诊断能力。
PDO是实时性最高的通信对象。它由“通信参数”和“映射参数”共同定义:通信参数(如0x1800)决定COB-ID、传输类型和禁止时间;映射参数(如0x1A00)决定这个PDO的1~8字节里,每个字节段对应对象字典中的哪个条目。例如某从站TPDO1映射为:0x2000:01(INT16温度)、0x2001:01(UINT8状态)、0x2002:01(UINT16压力),则网关收到8字节后,按映射顺序拆出2+1+2字节,再按数据类型还原为工程量。若映射顺序或数据类型判断错误,就会出现“数值跳变”或“高低字节颠倒”的典型故障。
SDO用于参数读写,采用客户端/服务器模型。网关作为SDO客户端,向从站发送请求(COB-ID=0x600+NodeID),从站用0x580+NodeID响应。加速SDO可一次传4字节以内数据;超过4字节则进入分段传输,通过“下载/上传”命令字和Toggle位交替完成。网关在配置阶段常用SDO写入0x1800子索引2的传输类型、0x1017的心跳周期等参数,运行阶段则用SDO读取0x1001错误寄存器做诊断。
NMT负责节点状态管理。CANopen节点有初始化、预操作、运行、停止四个主要状态。上电后节点进入预操作,此时只有SDO和心跳可用,PDO被禁止;网关发送NMT启动命令(COB-ID=0x000,数据为0x01+NodeID)后,节点进入运行态,PDO才开始传输。网关自身也要维护一张节点状态表,记录每个从站当前处于哪个状态,避免在预操作态误判PDO丢失。
心跳与节点保护用于存活监控。心跳模式下,从站按0x1017设定的周期主动发送0x700+NodeID,数据字节为状态码(0x00启动、0x04停止、0x05运行、0x7F预操作)。网关为每个节点维护一个超时计时器,若在“心跳周期×超时倍数”内未收到心跳,则判定该节点离线。节点保护则是网关主动轮询(0x700+NodeID发送远程帧),从站响应状态。两者选其一即可,Anybus网关通常优先使用心跳,因为它不需要网关周期性发起请求,网络负载更低。
实际工程中,网关还需要处理SYNC同步报文(COB-ID=0x080)和紧急报文(EMCY,COB-ID=0x080+NodeID)。SYNC用于触发同步PDO,网关若配置为同步模式,需在收到SYNC后统一刷新过程数据;EMCY则携带错误码和错误寄存器内容,是快速定位从站故障的重要来源。建议网关在启动阶段用SDO读取每个从站的0x1018(厂商ID、产品代码、版本号)建立设备指纹,运行阶段用心跳状态字节和EMCY错误码联合判断节点健康度,而不是仅凭PDO是否刷新来推断。
下面给出一份网关侧“关键报文解析检查表”示例,可用于配置和排障时逐项核对:
| 报文类型 | COB-ID | 关键字段 | 网关动作 |
|---|---|---|---|
| NMT | 0x000 | 命令字 + NodeID | 更新节点状态表 |
| SYNC | 0x080 | 无数据 | 触发同步PDO刷新 |
| EMCY | 0x080+NodeID | 错误码 + 错误寄存器 | 记录故障并告警 |
| TPDO1 | 0x180+NodeID | 映射数据 | 按0x1A00拆解变量 |
| RPDO1 | 0x200+NodeID | 映射数据 | 按0x1600打包下发 |
| SDO请求 | 0x600+NodeID | 命令字+索引+子索引 | 发起参数读写 |
| SDO响应 | 0x580+NodeID | 命令字+数据 | 校验并回填结果 |
| 心跳 | 0x700+NodeID | 状态字节 | 刷新超时计时器 |
需要特别注意的是,PDO的COB-ID并非固定不变,可通过SDO修改0x1800子索引1来重新分配。若网关与从站的PDO COB-ID配置不一致,就会出现“从站明明在发,网关却收不到”的问题。因此,工程上建议在网关配置文件中显式记录每个从站的PDO COB-ID、映射条目和数据类型,并在上线前用SDO回读0x1800/0x1A00进行一致性校验。只有把对象字典、PDO、SDO、NMT、心跳这五类机制串起来理解,网关才能既做“数据搬运工”,又做“状态管理者”。