2. CAN与CANopen基础回顾

好,咱们进入第二章。说实话,CANopen 协议栈移植这件事,很多人一上来就啃源码,结果越看越懵。为什么?因为你不理解它背后的那几个核心概念。这章我就带你把这几个概念彻底捋清楚。

CANopen 的核心概念,说白了就五个:对象字典(OD)、通信对象(COB-ID)、网络管理(NMT)、过程数据对象(PDO)、服务数据对象(SDO)。你把这五个东西搞明白了,整个协议栈的骨架就搭起来了。

一句话总结:对象字典是设备的“记忆体”,COB-ID 是通信的“门牌号”,NMT 管设备“死活”,PDO 传“快数据”,SDO 传“大文件”。

CANopen 核心概念关系图 对象字典 (OD) COB-ID NMT PDO SDO OD 是核心,COB-ID 是地址,NMT/PDO/SDO 是三种通信方式

2.1 对象字典(Object Dictionary, OD)

对象字典是什么?我习惯把它理解成设备的“记忆体”。每个 CANopen 设备都有一个 OD,里面按索引(Index)和子索引(Subindex)存放了设备的所有参数。

举个例子,你想想看,一个伺服驱动器,它需要知道自己的额定电流、最大转速、通信波特率、故障状态……这些东西都存在哪?就存在 OD 里。

索引范围 用途 我见过的坑
0x1000 - 0x1FFF 通信对象(COB-ID、同步、心跳等) 有人把波特率写错,整个网络挂掉
0x2000 - 0x5FFF 制造商特定参数 不同厂家定义不同,移植时要仔细看手册
0x6000 - 0x9FFF 标准化设备参数(如 CIA 402 驱动) 这部分最好别乱改,否则不符合标准

我的习惯:移植协议栈时,先把 OD 的 Excel 表格整理好。用脚本自动生成 C 代码,比手写快十倍,还不会出错。

2.2 通信对象(COB-ID)

COB-ID 就是 CAN 报文 ID。但 CANopen 对 ID 做了标准化分配。每个功能都有固定的 ID 范围。

我记得刚做 CANopen 时,总搞不清 0x180 和 0x200 的区别。后来发现,其实只要记住一个公式:COB-ID = 功能码 + 节点 ID。

功能码 通信对象 COB-ID 范围
0001 NMT 管理 0x000
0010 紧急报文 0x080 + 节点ID
0011 PDO1 (发送) 0x180 + 节点ID
0100 PDO1 (接收) 0x200 + 节点ID
1011 SDO (发送) 0x580 + 节点ID
1100 SDO (接收) 0x600 + 节点ID

避坑指南:我曾经在一个项目里,两个设备配了相同的 COB-ID,结果总线直接瘫痪。排查了整整两天才发现。记住:CANopen 网络里,每个 COB-ID 必须唯一。

2.3 网络管理(NMT)

NMT 管的是设备的“死活”和“状态”。CANopen 设备有几种状态:初始化、预操作、操作、停止。

说白了,NMT 就是主站用来控制从站状态的“遥控器”。

  • 初始化:设备上电后自动进入,做完自检就跳走
  • 预操作:可以发 SDO,但不能发 PDO。我常用这个状态来配置参数
  • 操作:正常工作状态,PDO 可以跑了
  • 停止:啥也不干,只响应 NMT 命令

关键点:NMT 报文的目标节点 ID 为 0 时,表示广播给所有节点。我曾经用这个功能一键让整个产线停机——嗯,测试的时候差点被骂。

2.4 过程数据对象(PDO)

PDO 是用来传“快数据”的。比如编码器位置、电机转速、开关状态。一个 PDO 报文最多传 8 字节,实时性很高。

PDO 分两种:

  • TPDO(发送 PDO):设备主动往外发
  • RPDO(接收 PDO):设备从总线上收

触发方式也有讲究:

  1. 事件触发:数据变了就发。我习惯用在编码器上
  2. 同步触发:收到 SYNC 报文才发。适合多轴同步
  3. 远程请求:别人问我才发。用得少

我的经验:PDO 映射表一定要提前规划好。我曾经在一个 32 轴的项目里,PDO 映射配错了,结果位置和速度数据串了。电机直接飞车,吓得我赶紧按了急停。

2.5 服务数据对象(SDO)

SDO 是用来传“大文件”的。比如修改 OD 参数、下载固件。SDO 是确认模式——你发一条,对方回一条,保证可靠。

SDO 的报文格式有点复杂,我直接给你看个例子:

// 读 OD 索引 0x1017(心跳周期)
// 请求:0x40 0x17 0x10 0x00 0x00 0x00 0x00 0x00
// 响应:0x43 0x17 0x10 0x00 0xFA 0x00 0x00 0x00
// 0xFA = 250,表示心跳周期 250ms

你看,SDO 的通信模式是“一问一答”。虽然慢,但可靠。我一般在设备调试阶段用 SDO 改参数,量产阶段用 PDO 跑数据。

特性 PDO SDO
速度 快(无确认) 慢(有确认)
数据量 最多 8 字节 可分段传大块数据
用途 实时控制 参数配置
可靠性 无确认 有确认

注意:SDO 通信时,如果主站和从站同时发请求,会产生冲突。我曾经遇到过 SDO 超时导致设备死锁的情况。解决办法是加超时重试机制,别死等。

好了,这五个核心概念就讲完了。你把这章吃透,后面讲协议栈移植的时候,你就知道代码里那些结构体、宏定义、回调函数到底在干什么了。