3. SDO协议基础:客户端/服务器模型、CCS与SCS编码规则、SDO请求与应答帧格式
SDO,全称是Service Data Object。说白了,它就是CANopen协议里用来访问对象字典的“万能钥匙”。你想读参数、写配置、做诊断,都得靠它。我刚开始接触CANopen时,总觉得SDO很复杂,后来发现只要搞懂了它的通信模型和帧结构,其实就那么回事。
3.1 客户端/服务器模型
SDO采用典型的客户端/服务器模型。这个模型怎么理解呢?我打个比方:
- 客户端:主动发起请求的一方。通常是CANopen主站,比如你的PC或者PLC。
- 服务器:被动响应请求的一方。就是我们的STM32从站设备。
客户端发一个请求帧,服务器回一个应答帧。一来一回,完成一次SDO传输。嗯,这里要注意:SDO通信是确认型服务,也就是说,客户端发了请求,必须等到服务器的应答,才能进行下一次操作。
关键点:SDO的客户端/服务器模型是一对一的。每个SDO通道只能服务一个对象。如果你想同时访问多个对象,要么开多个SDO通道,要么用块传输模式(后面章节会讲)。
我在项目中遇到过一个问题:主站连续发了两个SDO请求,没有等应答。结果从站直接懵了,总线报错。后来我养成了一个习惯——发一个请求,等一个应答,再发下一个。这个顺序千万别乱。
3.2 CCS与SCS编码规则
SDO帧里有个关键字段,叫命令码。客户端发的叫CCS(Client Command Specifier),服务器回的叫SCS(Server Command Specifier)。它们俩的编码规则,决定了这次SDO操作的类型。
我整理了一张表,把常用的CCS/SCS编码列出来:
| 命令码(bit 7-5) | 缩写 | 含义 | 方向 |
|---|---|---|---|
| 001 | Download | 写请求(客户端→服务器) | CCS |
| 010 | Upload | 读请求(客户端→服务器) | CCS |
| 011 | Abort | 中止传输 | CCS/SCS |
| 100 | Download应答 | 写应答(服务器→客户端) | SCS |
| 101 | Upload应答 | 读应答(服务器→客户端) | SCS |
你看,CCS和SCS的编码是对称的。客户端发Download(001),服务器就回Download应答(100)。客户端发Upload(010),服务器就回Upload应答(101)。
我的经验:调试SDO时,我习惯先看CAN报文的前3个bit。如果CCS=001,说明主站要写数据;如果CCS=010,说明主站要读数据。这个判断比看整个帧快得多。
3.3 SDO请求与应答帧格式
SDO的CAN数据帧固定为8字节。这8个字节怎么分配?我画个图你就明白了。
你看,8个字节分成了4个部分:
- 字节0:命令码。包含CCS/SCS(高3位)和传输指示(低4位)。
- 字节1-2:对象字典的索引。比如0x1017就是心跳生产者时间。
- 字节3:子索引。用于访问数组或记录类型对象。
- 字节4-7:数据。最多4字节,不够的补0。
注意:SDO的索引和子索引是小端模式(Little-Endian)。比如索引0x1017,在CAN报文里是0x17, 0x10。我刚开始写代码时,因为大小端搞反,折腾了一整天。你写代码时一定要确认好字节序。
3.4 举个例子:读一个对象
假设我们要读对象字典0x1017(心跳生产者时间)的子索引0x00。整个过程是这样的:
客户端发请求:
CAN ID: 0x600 + 节点ID(假设节点ID=1,则CAN ID=0x601)
数据: 0x40 0x17 0x10 0x00 0x00 0x00 0x00 0x00
这里0x40 = 010 0 0000,CCS=010表示Upload请求。
服务器回应答:
CAN ID: 0x580 + 节点ID(节点ID=1,则CAN ID=0x581)
数据: 0x43 0x17 0x10 0x00 0x64 0x00 0x00 0x00
这里0x43 = 100 0 0011,SCS=100表示Upload应答。数据0x64=100,说明心跳时间设置为100ms。
避坑指南:我曾经在调试时发现,服务器返回的应答帧里,数据长度可能小于4字节。比如读一个8位参数,数据只有1个字节有效。这时候别把后面3个0当成有效数据。我一般会先检查命令码里的传输指示位,确认实际数据长度。
3.5 再举个例子:写一个对象
现在我们要写对象0x1017的子索引0x00,把心跳时间改成200ms(0xC8)。
客户端发请求:
CAN ID: 0x600 + 节点ID(节点ID=1,CAN ID=0x601)
数据: 0x23 0x17 0x10 0x00 0xC8 0x00 0x00 0x00
0x23 = 001 0 0011,CCS=001表示Download请求。数据0xC8=200。
服务器回应答:
CAN ID: 0x580 + 节点ID(节点ID=1,CAN ID=0x581)
数据: 0x60 0x17 0x10 0x00 0x00 0x00 0x00 0x00
0x60 = 110 0 0000,SCS=110表示Download应答。注意,应答帧的数据段通常为0,表示写入成功。
总结一下:SDO通信就是客户端发命令,服务器回状态。命令码决定了操作类型,索引和子索引定位对象字典,数据段承载参数。搞懂这8个字节,你就掌握了SDO的核心。