1. 从站开发全景与对象字典定位

CANopen 从站开发的第一步,不是急着写代码,而是先建立一张“全景图”:一个从站设备由哪些部分组成,对象字典处在什么位置,通信服务如何映射到设备行为,以及一个最小工程应该长什么样。只有把这张图想清楚,后面的对象字典编写、PDO 映射、SDO 服务实现和心跳监控才不会变成零散的知识点堆砌。

一、从站设备的基本组成

一个典型的 CANopen 从站,从硬件到应用可以划分为四层。最底层是 CAN 控制器与收发器,负责位定时、报文收发、错误计数与总线仲裁;往上是 CANopen 协议栈,它实现 CAN 帧与 CANopen 报文之间的封装与解析,包括 NMT、SDO、PDO、SYNC、EMCY、心跳/节点保护等通信对象;再往上是 对象字典,它是协议栈与应用之间的唯一数据接口;最上层是 应用代码,例如电机控制、IO 采集、传感器处理等具体业务逻辑。

这四层的关系可以概括为:应用不直接碰 CAN 帧,协议栈不直接碰业务变量,二者通过对象字典中的索引(Index)和子索引(Subindex)完成读写。对象字典因此成为从站的“数据中枢”,也是配置工具、主站和从站应用三方共同约定的契约。

二、对象字典在协议栈中的核心地位

对象字典本质上是一张按 16 位索引组织的参数表,每个条目包含索引、子索引、数据类型、访问权限、默认值以及是否可映射到 PDO。按 CiA 301 的约定,索引被划分为若干功能区:

  • 0x1000–0x1FFF:通信参数区,如 0x1000 设备类型、0x1005 SYNC COB-ID、0x1017 心跳周期、0x1018 厂商 ID。
  • 0x2000–0x5FFF:制造商特定参数区,用于存放厂商自定义的配置与状态。
  • 0x6000–0x9FFF:标准设备子协议区,如 CiA 402 驱动与运动控制、CiA 401 IO 模块。
  • 0xA000–0xFFFF:标准接口子协议区,用于网络变量等。

对象字典之所以“核心”,是因为它同时承担三种角色:对主站而言,它是可读写的服务访问点;对协议栈而言,它是 SDO/PDO 的数据来源与目标;对应用而言,它是配置与状态的存放处。任何一次 SDO 上传下载、任何一帧 PDO 的映射,最终都落到对象字典的某个条目上。

CANopen 从站四层结构与对象字典中枢 应用层 电机控制 / IO 采集 / 传感器处理 / 状态机业务逻辑 业务变量 对象字典(OD)— 数据中枢 0x1000–0x1FFF 通信参数区 0x2000–0x5FFF 制造商特定区 0x6000–0x9FFF 设备子协议区 0xA000–0xFFFF 接口子协议区 CANopen 协议栈 NMT SDO PDO SYNC EMCY 心跳 CAN 控制器 / 收发器 位定时 · 报文收发 · 错误计数 · 总线仲裁 CAN_H / CAN_L 读写变量 SDO/PDO 数据源与目标 CAN 帧封装/解析 CANopen 主站

三、通信服务与设备行为的映射关系

对象字典不是静态表格,它通过通信服务与设备行为发生动态映射。理解这层映射,是从站开发的关键。

SDO(服务数据对象)用于配置和诊断,采用客户端/服务器模型,通过 0x1200–0x12FF 定义服务器参数。主站写 0x1017 心跳周期,从站收到后更新对象字典并改变心跳发送节奏;主站读 0x1000 设备类型,从站从 OD 取出 32 位值返回。SDO 的特点是可靠、有应答、可分段传输大数据。

PDO(过程数据对象)用于实时数据交换,采用生产者/消费者模型。PDO 本身不携带索引,而是通过映射参数(0x1600–0x17FF 接收映射、0x1A00–0x1BFF 发送映射)预先约定“第几个字节对应哪个 OD 条目”。例如把 0x2000:01(目标速度)映射到 RPDO1 的前 2 字节,主站发送一帧 PDO,从站协议栈就自动把数据写入 0x2000:01,应用代码只需读取该条目即可。

NMT、SYNC、EMCY、心跳则分别承担网络管理、同步触发、紧急事件上报和节点存活监控。它们同样通过 OD 中的通信参数条目进行配置,例如 0x1017 心跳周期、0x1014 EMCY COB-ID、0x1005 SYNC COB-ID。

因此,从站开发的一条主线是:先定义对象字典条目,再配置通信参数,最后把应用变量与 OD 条目绑定。顺序颠倒会导致 PDO 映射找不到数据源、SDO 访问越界或心跳周期不生效。

四、最小从站工程的文件结构与构建流程

一个可运行的最小 CANopen 从站工程,通常包含以下文件:

  • OD 定义文件(如 demo_slave.od 或 objectlist.c):描述所有索引、子索引、数据类型、默认值和访问权限。
  • 协议栈配置头文件(如 canopen_cfg.h):定义节点 ID、波特率、支持的通信对象数量、缓冲区大小。
  • 应用代码(如 app.c):实现业务逻辑,通过读写 OD 条目与协议栈交互。
  • 硬件抽象层(如 can_port.c):封装 CAN 控制器初始化、发送和接收中断。
  • 构建脚本(如 Makefile 或 CMakeLists.txt):把 OD 文件编译为 C 源文件,再与协议栈、应用一起链接。

构建流程一般分为四步:第一步,用对象字典编辑器或脚本把 .od 文件转换为 od.c 和 od.h;第二步,配置节点 ID 与波特率,例如节点 ID 设为 0x02、波特率 500 kbit/s;第三步,编译协议栈、OD 和应用代码,生成可执行文件;第四步,烧录到目标板,用 CAN 分析仪或主站工具验证 0x1000、0x1018 等条目是否可读,心跳是否按 0x1017 设定周期发出。

判断最小从站是否“跑通”的三个观察点:① 主站能通过 SDO 读取 0x1000 设备类型;② 心跳报文按 0x1017 配置的周期稳定发出;③ 一帧 RPDO 写入后,对应 OD 条目的值发生变化。三者都满足,说明对象字典、协议栈和应用之间的映射链路已经打通。