3. 通信对象与SDO:SDO的通信机制与实战配置
大家好,我是老张。今天咱们聊聊SDO——服务数据对象。说实话,在CANopen的各类通信对象里,SDO是我用得最多的一个。为什么?因为你要配置从站参数、读写设备数据,基本都靠它。我刚开始接触CANopen那会儿,被SDO的请求响应格式搞得晕头转向,后来踩了几个坑才算真正搞明白。
3.1 SDO的通信机制
SDO说白了就是「一问一答」的模式。主站发一个请求,从站回一个响应。这种机制保证了数据传输的可靠性——你想想看,如果发出去没回应,你根本不知道设备收到没有。
我个人习惯把SDO理解成「CANopen世界的Modbus RTU」。它基于客户端/服务器模型:
- 客户端:通常是主站(比如PLC、工控机),发起请求
- 服务器:是从站设备(比如驱动器、I/O模块),处理请求并回复
每个从站设备默认有两组SDO通道:
| SDO通道 | 发送COB-ID | 接收COB-ID | 用途 |
|---|---|---|---|
| SDO 1 | 0x600 + 节点ID | 0x580 + 节点ID | 默认参数配置 |
| SDO 2 | 0x640 + 节点ID | 0x5C0 + 节点ID | 扩展配置 |
举个例子,节点ID为3的从站,主站发请求用0x603,从站回复用0x583。这个对应关系我建议你记牢了,调试的时候经常要用到。
3.2 SDO的请求与响应格式
SDO报文一共8个字节。我刚开始看协议文档的时候,觉得这格式挺复杂。后来自己画了个图,一下就清楚了。
命令字这块,我常用的就几个:
- 0x22:写请求(下载)——我要往从站写数据
- 0x40:读请求(上传)——我要从从站读数据
- 0x60:写响应——从站告诉我写成功了
- 0x41:读响应——从站把数据发回来了
- 0x80:异常响应——出错了,里面带错误码
3.3 SDO的快速传输与分段传输
这里有个重要的概念——快速传输和分段传输。说白了就是:
- 快速传输:数据≤4字节,一个报文搞定
- 分段传输:数据>4字节,拆成多个报文发
我在项目中遇到过这样的情况:配置一个伺服驱动器的电子齿轮比,需要写8个字节的数据。一开始我用快速传输,结果从站没反应。后来才意识到,超过4字节必须用分段传输。
快速传输示例
假设我要把从站节点ID=3的设备,对象字典索引0x2000子索引0x01的值设为0x12345678:
主站请求:22 00 20 01 78 56 34 12
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
命令 索引 子索引 数据(小端)
从站响应:60 00 20 01 00 00 00 00
↑
写成功确认
注意数据是小端格式!我刚开始就栽在这个坑里——0x12345678在报文里是78 56 34 12,不是12 34 56 78。这个顺序搞反了,写进去的数据全是错的。
分段传输示例
如果要写8个字节的数据0x1122334455667788到索引0x2001子索引0x00:
第一段(主站发):21 01 20 00 11 22 33 44
↑
命令字0x21表示分段写,还有数据
第二段(主站发):00 55 66 77 88 00 00 00
↑
命令字0x00表示最后一段
从站响应:60 01 20 00 00 00 00 00
写成功
3.4 使用SDO配置从站参数
好了,理论说完了,咱们来点实战的。我个人习惯用这样的步骤来配置从站:
- 先读后写:配置前先读一下当前值,确认对象字典地址对不对
- 写前备份:把原始值记下来,万一配错了还能恢复
- 写后回读:写完再读一遍,确认写入成功
举个例子,配置一个变频器的加速时间(假设对象字典为0x2002子索引0x01,数据类型为32位无符号整数):
// 第一步:读取当前值
主站请求:40 02 20 01 00 00 00 00
从站响应:41 02 20 01 0A 00 00 00 // 当前值为10(单位ms)
// 第二步:写入新值(设为500ms)
主站请求:22 02 20 01 F4 01 00 00 // 500 = 0x01F4
从站响应:60 02 20 01 00 00 00 00 // 写入成功
// 第三步:回读确认
主站请求:40 02 20 01 00 00 00 00
从站响应:41 02 20 01 F4 01 00 00 // 确认已改为500
另外,有些从站设备在写入某些参数后需要重新上电才能生效。比如修改节点ID、波特率这些。我一般会在写入后加一个延时,然后发送复位命令(NMT的0x81)。
嗯,SDO这块内容就这些。说白了就是记住三点:报文格式、快速/分段的选择、写后回读的习惯。掌握了这些,配置从站参数基本不会出大问题。
公众号:蓝海资料掘金营,微信deep3321