文章目录
-
- [0. 前言](#0. 前言)
- [1. CANopen 核心概念](#1. CANopen 核心概念)
- [2. CANopen 核心组件](#2. CANopen 核心组件)
-
- [2.1 对象字典(Object Dictionary, OD)](#2.1 对象字典(Object Dictionary, OD))
- [2.2 通信对象(Communication Objects)](#2.2 通信对象(Communication Objects))
- [3. 核心通信机制](#3. 核心通信机制)
-
- [3.1 SDO(Service Data Object)- 服务数据对象](#3.1 SDO(Service Data Object)- 服务数据对象)
- [2.2 PDO(Process Data Object)- 过程数据对象](#2.2 PDO(Process Data Object)- 过程数据对象)
- [3.3 NMT(Network Management)- 网络管理](#3.3 NMT(Network Management)- 网络管理)
- [3.4 Heartbeat(心跳报文)](#3.4 Heartbeat(心跳报文))
- [4. CANopen COB-ID 详细解析映射表](#4. CANopen COB-ID 详细解析映射表)
- [5. 常用 SDO 命令字节解析规则表](#5. 常用 SDO 命令字节解析规则表)
- [6. 举个例子](#6. 举个例子)
-
- [第 1 步:主机 → 从节点(SDO 上传请求)](#第 1 步:主机 → 从节点(SDO 上传请求))
- [第 2 步:从节点 → 主机(SDO 上传响应)](#第 2 步:从节点 → 主机(SDO 上传响应))
- [7. 总结](#7. 总结)
0. 前言
📣按照国际惯例,首先声明:本文只是我自己学习的理解,虽然参考了他人的宝贵见解及成果,但是内容可能存在不准确的地方。如果发现文中错误,希望批评指正,共同进步。
本文介绍CANopen协议,并结合个人工作经验介绍一些实用的规则。
CANopen 是一种基于 CAN(Controller Area Network)总线 的高层通信协议,广泛应用于工业自动化、医疗设备、轨道交通、汽车电子等领域。它定义了标准化的通信机制、设备描述和网络管理功能,使不同厂商的设备能够互操作。
1. CANopen 核心概念
CANopen 属于 OSI 模型的 应用层协议(第 7 层),构建在 CAN 数据链路层(第 2 层)之上:
| OSI 层级 | CANopen 对应 |
|---|---|
| 应用层 (7) | CANopen 应用层(CiA 301) |
| 表示层 (6) | - |
| 会话层 (5) | - |
| 传输层 (4) | - |
| 网络层 (3) | - |
| 数据链路层 (2) | CAN 协议(ISO 11898) |
| 物理层 (1) | CAN 物理层(ISO 11898-2) |
2. CANopen 核心组件
2.1 对象字典(Object Dictionary, OD)
对象字典是 CANopen 设备的核心数据库,采用 索引(Index)+ 子索引(Sub-index) 的 16 位寻址方式,存储设备的所有参数和通信数据。
索引范围划分:
| 索引范围 | 区域名称 | 内容 |
|---|---|---|
| 0x0000 | - | 保留 |
| 0x0001 - 0x001F | 静态数据类型 | 标准数据类型定义 |
| 0x0020 - 0x003F | 复杂数据类型 | 数组、结构体定义 |
| 0x0040 - 0x005F | 制造商特定复杂数据类型 | 厂商自定义 |
| 0x0060 - 0x007F | 设备子协议静态数据类型 | 子协议标准类型 |
| 0x0080 - 0x009F | 设备子协议复杂数据类型 | 子协议复杂类型 |
| 0x1000 - 0x1FFF | 通信子协议区域 | 设备类型、错误寄存器、PDO/SDO 映射等 |
| 0x2000 - 0x5FFF | 制造商特定区域 | 厂商自定义参数 |
| 0x6000 - 0x9FFF | 标准化设备子协议区域 | 符合 CiA 子协议(如 402 驱动器) |
| 0xA000 - 0xFFFF | 保留 | 未来扩展 |
关键通用对象(0x1000-0x1FFF):
| 索引 | 对象名称 | 功能说明 |
|---|---|---|
| 0x1000 | 设备类型 | 标识设备类型(如 0x401 = 通用 I/O) |
| 0x1001 | 错误寄存器 | 设备当前错误状态 |
| 0x1008 | 制造商设备名称 | 设备型号字符串 |
| 0x1009 | 制造商硬件版本 | 硬件版本信息 |
| 0x100A | 制造商软件版本 | 软件版本信息 |
| 0x1017 | 生产者心跳时间 | 心跳报文发送间隔(ms) |
| 0x1018 | 身份对象 | 厂商ID、产品代码、修订号、序列号 |
| 0x1400-0x15FF | RPDO 通信参数 | 接收 PDO 配置(ID、传输类型等) |
| 0x1600-0x17FF | RPDO 映射参数 | RPDO 数据映射到对象字典 |
| 0x1800-0x19FF | TPDO 通信参数 | 发送 PDO 配置(ID、传输类型、禁止时间等) |
| 0x1A00-0x1BFF | TPDO 映射参数 | TPDO 数据映射到对象字典 |
2.2 通信对象(Communication Objects)
CANopen 定义了 4 种基本通信对象 ,通过 CAN 帧的 COB-ID(Communication Object Identifier) 区分:
| 通信对象 | COB-ID 范围 | 功能 | 优先级 |
|---|---|---|---|
| NMT(网络管理) | 0x000 | 节点状态管理、心跳监控 | 最高 |
| SYNC(同步对象) | 0x080 | 同步信号,协调 PDO 传输 | 高 |
| TIME(时间戳) | 0x100 | 系统时间广播 | 高 |
| EMCY(紧急报文) | 0x080-0x0FF | 紧急错误通知 | 高 |
| PDO(过程数据对象) | 0x180-0x57F | 实时过程数据传输 | 中 |
| SDO(服务数据对象) | 0x580-0x6FF | 参数配置、对象字典访问 | 低 |
3. 核心通信机制
3.1 SDO(Service Data Object)- 服务数据对象
作用 :用于参数配置和非实时数据访问,基于 客户端-服务器 模式。
特点:
- 确认通信(请求-响应机制,保证可靠传输)
- 传输任意长度数据(分段传输支持)
- 访问对象字典的任何条目
两种传输模式:
| 模式 | 数据长度 | 说明 |
|---|---|---|
| 快速 SDO(Expedited SDO) | ≤ 4 字节 | 单帧传输,最高效 |
| 分段 SDO(Segmented SDO) | > 4 字节 | 多帧分段传输 |
COB-ID 分配:
- 客户端请求 → 服务器:0x600 + Node-ID
- 服务器响应 → 客户端:0x580 + Node-ID
SDO 报文结构示例(下载,客户端→服务器):
字节 0: [命令字节]
bit 7-5: 101 (发起下载请求)
bit 1-0: 数据长度编码 (00=4字节, 01=3字节, 10=2字节, 11=1字节)
字节 1-2: 对象索引(小端序:低字节在前)
字节 3: 子索引
字节 4-7: 数据(4字节以内)
2.2 PDO(Process Data Object)- 过程数据对象
作用:用于实时、周期性过程数据传输,是 CANopen 高性能的关键。
特点:
- 无确认通信(广播/多播,不等待响应,低延迟)
- 单帧最多 8 字节 数据
- 传输延迟固定(确定性)
- 支持同步和异步触发
PDO 类型:
| 类型 | 名称 | 方向 | COB-ID 基础 |
|---|---|---|---|
| TPDO | Transmit PDO | 节点 → 网络 | 0x180 + Node-ID (TPDO1), 0x280 (TPDO2), 0x380 (TPDO3), 0x480 (TPDO4) |
| RPDO | Receive PDO | 网络 → 节点 | 0x200 + Node-ID (RPDO1), 0x300 (RPDO2), 0x400 (RPDO3), 0x500 (RPDO4) |
每个节点最多支持 4 个 TPDO 和 4 个 RPDO
PDO 传输类型(Transmission Type):
| 类型值 | 触发方式 | 说明 |
|---|---|---|
| 0 | 同步(循环) | 收到 SYNC 后触发,周期性发送 |
| 1-240 | 同步(非循环) | 每收到 N 个 SYNC 触发一次 |
| 254 | 异步(事件驱动) | 数据变化或特定事件触发 |
| 255 | 异步(制造商特定) | 由厂商定义触发条件 |
| 252 | 同步 RTR 触发 | 收到远程帧后同步发送 |
PDO 映射(Mapping):
PDO 映射决定 PDO 数据字节对应对象字典的哪些条目。例如,将 0x6041(状态字)和 0x6064(实际位置)映射到 TPDO1:
对象 0x1A00(TPDO1 映射参数):
Sub 0: 2 (映射条目数 = 2)
Sub 1: 0x60410010 (索引 0x6041, 子索引 0x00, 长度 0x10 = 16 位)
Sub 2: 0x60640020 (索引 0x6064, 子索引 0x00, 长度 0x20 = 32 位)
3.3 NMT(Network Management)- 网络管理
作用:管理所有节点的通信状态。
NMT 状态机:
初始化
预运行
运行
停止
状态说明:
| 状态 | 功能 |
|---|---|
| 初始化(Initializing) | 上电初始化,不可通信 |
| 预运行(Pre-operational) | 可配置参数(SDO),但禁止 PDO 通信 |
| 运行(Operational) | 全功能运行,SDO + PDO |
| 停止(Stopped) | 仅响应 NMT 命令,停止所有通信 |
NMT 命令报文(COB-ID = 0x000):
字节 0: 命令字
0x01 = 启动节点 (Start Remote Node)
0x02 = 停止节点 (Stop Remote Node)
0x80 = 进入预运行 (Enter Pre-operational)
0x81 = 节点复位 (Reset Node)
0x82 = 通信复位 (Reset Communication)
字节 1: Node-ID (0 = 广播所有节点)
3.4 Heartbeat(心跳报文)
作用:监控节点在线状态,替代传统的 Node Guarding。
机制:
- 每个节点周期性发送心跳报文(COB-ID = 0x700 + Node-ID)
- 消费者(主站/监控节点)监听心跳超时
- 单个字节状态:0x04(停止)、0x05(运行)、0x7F(预运行)
心跳时间配置:
- 对象 0x1017:生产者心跳时间(本节点发送间隔)
- 对象 0x1016:消费者心跳时间(监控其他节点)
4. CANopen COB-ID 详细解析映射表
| 功能码 (Function Code) | 通信对象 | COB-ID 范围(十六进制) | COB-ID 计算公式 | Node-ID 范围 | 方向 | 说明 |
|---|---|---|---|---|---|---|
| 0x0 | NMT | 0x000 |
固定 | --- | 主站 → 从站(广播或单播) | 网络管理命令(启动/停止/复位节点) |
| 0x0 | Heartbeat | 0x700 -- 0x77F |
0x700 + NodeID |
1--127 | 从站 → 网络(广播) | 周期性发送节点状态(0x04=Stopped, 0x05=Operational, 0x7F=Pre-op) |
| 0x1 | SYNC | 0x080 |
固定 | --- | 主站 → 网络(广播) | 同步信号,用于触发同步 PDO 传输 |
| 0x2 | TIME | 0x100 |
固定 | --- | 主站 → 网络(广播) | 广播系统时间(6 字节:ms + days) |
| 0x1--0xF | EMCY | 0x080 -- 0x0FF |
0x080 + NodeID |
1--127 | 从站 → 网络(广播) | 紧急错误报文(高优先级),含错误码和寄存器 |
| 0x3--0xA | TPDO1--4 | 0x180--0x27F 0x280--0x37F 0x380--0x47F 0x480--0x57F |
0x180 + (n−1)×0x100 + NodeID (n=1~4) |
1--127 | 从站 → 网络 | 实时过程数据输出(最多 4 个 TPDO) |
| 0xB--0xE | RPDO1--4 | 0x200--0x2FF 0x300--0x3FF 0x400--0x4FF 0x500--0x5FF |
0x200 + (n−1)×0x100 + NodeID (n=1~4) |
1--127 | 网络 → 从站 | 实时过程数据输入(最多 4 个 RPDO) |
| 0xC | SDO Tx | 0x580 -- 0x5FF |
0x580 + NodeID |
1--127 | 服务器 → 客户端 | SDO 响应(上传数据、确认、错误) |
| 0xD | SDO Rx | 0x600 -- 0x67F |
0x600 + NodeID |
1--127 | 客户端 → 服务器 | SDO 请求(下载、上传请求) |
- 主站(Master):指 CANopen 网络中的控制节点(通常是 PC、PLC 或运动控制器),负责发送 NMT 命令、SYNC 信号、SDO 请求,并协调整个网络的运行。
- 从站(Slave):指 CANopen 网络中的被控设备(如伺服驱动器、I/O 模块、传感器),响应主站命令,通过 PDO 发送/接收实时数据,并提供对象字典供 SDO 访问。
- 网络(Network):指由一个主站和多个从站通过 CAN 总线连接构成的 CANopen 通信系统,所有节点共享同一物理总线并遵循统一协议规则。
- 客户端(Client):在 SDO 通信中,指主动发起读写请求的一方(通常是主站),用于访问从站的对象字典,因此 SDO 客户端 ≈ 主站的 SDO 功能模块。
- 服务器(Server):在 SDO 通信中,指被动响应请求的一方(即每个从站),负责提供或接收对象字典中的数据,因此 SDO 服务器 ≈ 从站的 SDO 服务功能。
5. 常用 SDO 命令字节解析规则表
| 命令码(Hex) | 二进制(bit7--bit0) | 方向 | 操作类型 | 数据长度 | 功能说明 |
|---|---|---|---|---|---|
| 0x23 | 0010 0011 |
客户端 → 服务器 | 下载(Download) | 4 字节 | 写入 4 字节数据(如 UINT32、FLOAT) |
| 0x27 | 0010 0111 |
客户端 → 服务器 | 下载(Download) | 3 字节 | 写入 3 字节数据(较少用) |
| 0x2B | 0010 1011 |
客户端 → 服务器 | 下载(Download) | 2 字节 | 写入 2 字节数据(如 UINT16、INT16) |
| 0x2F | 0010 1111 |
客户端 → 服务器 | 下载(Download) | 1 字节 | 写入 1 字节数据(如 UINT8、布尔值) |
| 0x40 | 0100 0000 |
客户端 → 服务器 | 上传请求(Upload Request) | --- | 请求读取某对象字典条目(无数据) |
| 0x43 | 0100 0011 |
服务器 → 客户端 | 上传响应(Upload Response) | 4 字节 | 返回 4 字节数据 |
| 0x47 | 0100 0111 |
服务器 → 客户端 | 上传响应 | 3 字节 | 返回 3 字节数据 |
| 0x4B | 0100 1011 |
服务器 → 客户端 | 上传响应 | 2 字节 | 返回 2 字节数据 |
| 0x4F | 0100 1111 |
服务器 → 客户端 | 上传响应 | 1 字节 | 返回 1 字节数据 |
| 0x80 | 1000 0000 |
服务器 → 客户端 | 中止传输(Abort) | 4 字节 | 传输失败,后4字节为错误码(如 0x06010000) |
6. 举个例子
🎯 场景设定
- 目标操作 :主机读取从节点(NodeID = 3)的 "制造商设备名称" (对象字典索引
0x1008,子索引0x00) - 通信方式:SDO 上传(Upload)------ 快速传输(≤4 字节)
- 物理层:CAN 总线,标准帧(11-bit ID)
🔁 交互过程:SDO 上传(读取设备名称)
注:
0x1008通常是字符串,但若长度 ≤4 字节(如 "DRV1"),可用快速上传;否则需分段。此处假设值为"MOT"(3 字节),用快速传输。
第 1 步:主机 → 从节点(SDO 上传请求)
| 项目 | 值 |
|---|---|
| COB-ID | 0x600 + NodeID = 0x600 + 3 = 0x603 |
| CAN 数据帧(8 字节) | [40, 08, 10, 00, 00, 00, 00, 00] |
🔍 报文解析:
| 字节 | 值(Hex) | 含义 |
|---|---|---|
| 0 | 40 |
命令字节 = 0x40 → 上传请求(Upload Request) |
| 1--2 | 08 10 |
索引 = 0x1008(小端序:低字节在前) |
| 3 | 00 |
子索引 = 0x00 |
| 4--7 | 00 00 00 00 |
无数据(上传请求不带数据) |
✅ 协议语义:
"NodeID=3,请将对象字典中 0x1008:00 的值发给我。"
第 2 步:从节点 → 主机(SDO 上传响应)
| 项目 | 值 |
|---|---|
| COB-ID | 0x580 + NodeID = 0x580 + 3 = 0x583 |
| CAN 数据帧(8 字节) | [47, 08, 10, 00, 4D, 4F, 54, 00] |
🔍 报文解析:
| 字节 | 值(Hex) | 含义 |
|---|---|---|
| 0 | 47 |
命令字节 = 0x47 → 上传响应,3 字节数据 |
| 1--2 | 08 10 |
索引 = 0x1008 |
| 3 | 00 |
子索引 = 0x00 |
| 4--6 | 4D 4F 54 |
ASCII: 'M' 'O' 'T' → 设备名称 = "MOT" |
| 7 | 00 |
填充字节(无意义) |
✅ 协议语义:
"这是你要的 0x1008:00 的值:'MOT'(3 字节)。"
7. 总结
CANopen 通过 标准化的对象字典、灵活的 PDO/SDO 通信、完善的网络管理,在保持 CAN 总线实时性和可靠性的基础上,提供了工业级的设备互操作性。其