1. CAN 总线快速回顾:报文是怎么传的
CAN(Controller Area Network)是差分串行总线,两根线 CANH/CANL,具有抗干扰强、错误检测完善、多主仲裁的特点。一个 CAN 数据帧的组成:
- 帧起始 + 仲裁段(标准帧 11 位 ID):决定优先级,ID 越小优先级越高
- 控制段:DLC(数据长度 0~8 字节)
- 数据段:最多 8 字节
- CRC、ACK、帧结束:错误检测与应答
tframe ≈ (44 + 8·DLC) / 波特率,实际还要加填充位与间隔
500kbps · 8 字节数据 ≈ 108 位 ≈ 216 μs
CAN 只解决了"报文怎么传",但报文里装什么、谁跟谁通信、错误了怎么办——这是 CANopen 要回答的问题。
2. CANopen 的核心思想:一切皆对象字典
CANopen(CiA 301)建立在 CAN 之上,定义了:
- 对象字典(OD, Object Dictionary):每个从站有一张参数表,所有数据都用"索引:子索引"寻址
- 通信对象:读配置走 SDO、传实时数据走 PDO、网络管理走 NMT、故障上报走 EMCY
- 设备行规:CiA 401(I/O)、CiA 402(驱动/伺服)等,让不同厂商设备"同一套字典"互操作
一句话:CANopen = CAN 传输 + 对象字典寻址 + 标准通信服务。
3. 对象字典(OD):从站的大脑
对象字典把每个数据组织成 索引(Index, 16 位):子索引(Subindex, 8 位) 的两级表。索引按区域划分:
| 索引范围 | 区域 | 典型内容 |
|---|---|---|
| 0000h | 保留 | — |
| 1000h–1FFFh | 通信参数区 | 设备类型、错误寄存器、PDO通信参数(1400h/1800h)、PDO映射(1600h/1A00h)、SDO参数、心跳(1017h)、节点ID(1017h附近) |
| 2000h–5FFFh | 厂商特定区 | 厂家自定义参数、内部变量 |
| 6000h–9FFFh | 标准设备行规区 | CiA 402:状态字6041h、控制字6040h、目标位置607Ah、操作模式6060h… |
| A000h–FFFFh | 保留 | — |
每个 OD 条目有固定属性:对象类型(VAR/数组/记录)、数据类型(U8/I8/U16/U32/REAL…)、访问属性(ro/rw/wo/const)、映射属性(能否被 PDO 映射)。
读伺服当前状态:读 6041h 子索引0;写目标位置:写 607Ah 子索引0。掌握了"索引:子索引"两级寻址,就掌握了 CANopen 数据访问的钥匙。
4. 通信对象:各司其职的五类报文
| 通信对象 | 方向 | 用途 | 典型 COB-ID |
|---|---|---|---|
| NMT(网络管理) | 主→从 | 启动/停止/进入预操作/复位节点 | 000h(+命令+节点ID) |
| SYNC(同步) | 主→广播 | 同步所有从站开始采样/执行 | 080h |
| SDO(服务数据) | 双向 | 读写对象字典(配置),可任意访问 | 请求 600h+ID / 响应 580h+ID |
| PDO(过程数据) | 双向 | 实时数据(位置/速度/电流),周期或触发 | TPDO 180h+ID · RPDO 200h+ID |
| EMCY(紧急报文) | 从→主 | 故障/错误上报 | 080h+ID |
| 心跳/节点守护 | 从→主 | 节点在线状态监控 | 700h+ID |
4.1 NMT:网络状态机
每个从站必须处于以下状态之一:初始化 → 预操作(Pre-operational)→ 运行(Operational)↔ 停止(Stopped)。
- 预操作:可走 SDO(配置),不传 PDO
- 运行:SDO + PDO 都可用(正常工作)
- 停止:只响应 NMT 和心跳
NMT 报文 2 字节:命令字节 + 目标节点 ID(0=广播所有节点)。常用命令:01h 启动、02h 停止、80h 进入预操作、81h 复位节点。
4.2 SDO:配置的"挂号信"
SDO 用"请求-应答"可靠传数据,适合配置但不适合实时。单帧写 4 字节以内数据:
请求:600h+ID · [2F/2B/27/23] [索引低] [索引高] [子索引] [数据0..3]
响应:580h+ID · [4F/4B/47/43] 同索引子索引,出错则 [80h]+错误码
超过 4 字节走分段传输(0x10/0x21 等),这里不展开。
4.3 PDO:实时的"快递"
PDO 是数据面通信:把对象字典里几个条目"映射"进一个 CAN 帧(最多 8 字节),触发方式可选周期、事件、同步、远程请求。发送 PDO 叫 TPDO,接收 PDO 叫 RPDO。
PDO 的映射关系由 OD 配置:
- PDO 通信参数:TPDO 在 1800h–1803h(含 COB-ID、传输类型、周期),RPDO 在 1400h–1403h
- PDO 映射参数:TPDO 在 1A00h–1A03h,RPDO 在 1600h–1603h;每个映射条目是 32 位:
索引(16) | 子索引(8) | 位长(8)
映射总位数不能超过 64 位(8 字节)。改映射时通常要先把 PDO 通信参数里的"有效"标志(1F00h 节点保护 / 对应 bit)置 0,改完再置 1 才生效——很多现场"改了映射没反应"就是这个原因。
5. 交互式演示:PDO 映射与数据打包
勾选左侧对象字典条目(总长不超过 8 字节),右侧实时生成 PDO 映射表(0x1A00 各子索引)和打包后的一个 CAN 帧 8 字节数据——这就是 TPDO 在从站里干的事。
观察要点:每个映射条目都是 32 位的 索引|子索引|位长;勾选的数据按顺序紧凑拼进 8 字节;总位数不能超过 64 位,否则提示溢出。
6. 代码实现(C语言)
6.1 对象字典条目结构
6.2 SDO 单帧读/写分发
6.3 TPDO 打包
7. 工程要点与常见误区
要点 1:COB-ID 冲突排查
多从站共用一个 CAN 网络,PDO/SDO/心跳 ID 都按节点 ID 偏移。节点 ID 重复或与主站配置不符是"通信不上"的第一原因,先用总线分析仪抓 ID 分布。
要点 2:PDO 触发方式按场景选
位置/速度环同步控制用同步触发(SYNC 对齐);普通状态上报用周期/事件触发。同步 PDO 配合 CiA 402 才有确定性。
要点 3:总线负载率要预算
所有周期 PDO + 心跳 + 周期 SDO 加起来别超过总线容量的 30%~50%(留裕量给 EMCY 突发)。1Mbps 下一个 8 字节 PDO 约 216μs,10 个从站各 1ms 周期就会到 20% 以上。
误区 1:SDO 当 PDO 用
SDO 是请求-应答、有协议开销,不适合周期实时传。实时数据必须走 PDO。
误区 2:改 PDO 映射不重入操作
映射要在从站进入预操作时改,改完确认,不能边运行边乱改。
误区 3:以为 CANopen 只传 8 字节
单帧是 8 字节,但 SDO 分段、PDO 多帧/多对象组合、同步联动可以覆盖任意规模和复杂控制需求。
8. 小结
- CAN 解决"报文怎么传",CANopen 解决"报文装什么、怎么协作"
- 对象字典用 索引:子索引 两级寻址,通信区 1xxxh / 厂商区 2xxx-5xxxh / 行规区 6xxx-9xxxh
- 五类通信对象各司其职:NMT 管状态、SDO 管配置、PDO 管实时、EMCY 管故障、心跳管在线
- PDO 映射 = 把 OD 条目按
索引|子索引|位长打包进 8 字节帧,总长 ≤64 位 - 从站实现的核心就是"一张 OD 表 + SDO 分发 + PDO 打包"三件事
下一篇进入运动控制视角——CiA 402 伺服行规:状态机怎么迁、控制字/状态字怎么用、七种工作模式怎么选。