3、SDO基础:SDO协议格式、加速传输与分段传输机制

说到CANopen里的数据交换,大家最先接触的肯定是SDO。我刚开始学CANopen那会儿,总觉得SDO这个名字挺唬人——服务数据对象,听着就抽象。其实说白了,SDO就是用来读写对象字典的通道。你想配置参数、查状态、下载固件,都得靠它。

今天咱们就把SDO的底裤扒干净。从协议格式讲起,再到两种传输模式:加速传输和分段传输。嗯,这两个概念搞明白了,你写代码的时候就知道什么时候该用谁了。

3.1 SDO协议格式——报文里藏了什么秘密?

SDO通信用的是CAN标准帧,11位ID。客户端发请求,服务器回响应。我习惯把SDO报文分成三部分看:

  • CAN-ID:0x600 + 节点号(请求),0x580 + 节点号(响应)
  • 字节0:命令字,也叫CCS(Client Command Specifier)
  • 字节1-3:对象字典索引(2字节)+ 子索引(1字节)
  • 字节4-7:数据区,最多4字节

举个例子你就明白了。假设节点1的驱动器,我想把它的“电机额定电流”改成5000mA。这个参数存在对象字典0x2001,子索引0x01。那么我发的SDO请求报文长这样:

CAN-ID: 0x601
数据: 23 01 20 01 88 13 00 00

拆开看:

  • 0x23:命令字,表示“写数据,加速传输,4字节有效”
  • 0x01 0x20:索引0x2001(注意小端模式,低字节在前)
  • 0x01:子索引
  • 0x88 0x13 0x00 0x00:数据5000,十六进制0x1388,小端排列

服务器收到后,如果成功,会回复:

CAN-ID: 0x581
数据: 60 01 20 01 00 00 00 00

0x60就是“写成功”的响应码。嗯,这里要注意:如果服务器报错,返回的就不是0x60了,而是0x80开头的错误报文,后面跟着错误码。

核心记忆点:SDO请求的CAN-ID = 0x600 + 节点号,响应CAN-ID = 0x580 + 节点号。这个公式我闭着眼睛都能写出来。

3.2 加速传输——小数据就该快刀斩乱麻

加速传输,英文叫Expedited Transfer。名字起得好,就是“加急”的意思。什么时候用?当你要传输的数据不超过4字节时。

你想想看,电机参数、PID系数、限位值,这些哪个不是4字节以内?所以加速传输在实际项目里用得最多。我做过一个伺服项目,90%的SDO通信都是加速传输,又快又省事。

加速传输的命令字格式如下:

位7-5 位4 位3 位2 位1-0
CCS 1(加速标志) 1(数据有效) e(数据大小编码) 保留

CCS的值:1=下载(写),2=上传(读)。

e的编码:00=4字节,01=3字节,10=2字节,11=1字节。

举个例子,我要读节点2的“设备类型”(4字节,索引0x1000,子索引0x00):

请求: 40 00 10 00 00 00 00 00
响应: 43 00 10 00 01 00 00 00

请求的0x40表示“上传请求,加速”。响应的0x43表示“上传响应,加速,4字节有效”,数据是0x00000001,表示设备类型是“通用驱动器”。

我的小技巧:写代码时,我习惯把命令字定义成宏。比如#define SDO_DOWNLOAD_EXPEDITED_4 0x23,这样一看就懂,不容易写错。

3.3 分段传输——大数据就得慢慢来

那如果数据超过4字节呢?比如你要下载一个100字节的配置文件,或者上传一段固件程序。这时候加速传输就无能为力了。怎么办?用分段传输(Segmented Transfer)。

分段传输的原理很简单:把大数据切成小块,一块一块发。每块最多7字节(因为CAN报文数据区8字节,去掉1字节命令字,剩7字节可用)。

我曾经在一个项目中,需要给驱动器升级固件。固件大小128KB,用分段传输,一包7字节,算下来要发将近2万包。嗯,那时候我才真正体会到什么叫“耐心是美德”。

分段传输的流程分三步:

  1. 初始化:客户端发一个“分段下载请求”,告诉服务器我要传大数据了。命令字0x21(下载,不分段,但数据长度超过4字节)。
  2. 数据分段:客户端一包一包发数据。每包命令字0x00或0x10(0x10表示最后一包)。数据区最多7字节。
  3. 结束确认:服务器收到最后一包后,回复0x60确认。

看个例子,下载一个10字节的数据到对象字典0x2002:

第一步:初始化
请求: 21 02 20 00 0A 00 00 00
解释: 0x21=下载,索引0x2002,子索引0x00,数据长度10字节

第二步:分段发送
第1包: 00 01 02 03 04 05 06 07
第2包: 10 08 09 00 00 00 00 00
解释: 第1包命令字0x00(中间包),第2包0x10(最后一包)

第三步:服务器确认
响应: 60 02 20 00 00 00 00 00

避坑指南:我曾经在分段传输时犯过一个低级错误——忘记设置toggle位。分段传输的每一包都有一个toggle位(命令字的位4),用来做交替校验。第1包toggle=0,第2包toggle=1,第3包toggle=0……以此类推。如果toggle位不对,服务器会直接丢弃报文。这个坑我踩过一次,调试了一下午才发现。

3.4 加速 vs 分段——到底怎么选?

这个问题我经常被问到。其实选择标准就一条:看数据长度

  • 数据 ≤ 4字节:用加速传输。简单、高效、实时性好。
  • 数据 > 4字节:用分段传输。但要注意,分段传输会占用总线时间,如果系统里有多个节点同时做分段传输,总线负载会飙升。

我个人的经验是:能用加速就别用分段。比如有些工程师习惯把所有参数都打包成结构体,一次下载几十个字节。其实完全可以把每个参数单独用加速传输写,代码更清晰,调试也方便。

当然,有些场景不得不分段。比如下载固件、上传历史故障记录。这时候我建议:分段传输期间,暂停其他高优先级PDO的发送,避免总线冲突。

3.5 知识体系总览

下面这张图是我自己画的SDO传输机制总览,帮你把今天的内容串起来:

SDO传输机制总览 SDO 加速传输 分段传输 特性 • 数据 ≤ 4字节 • 一包搞定,实时性高 • 命令字:0x23(写)/ 0x43(读) 特性 • 数据 > 4字节 • 多包传输,需toggle校验 • 初始化→分段→确认三步走 选择原则:数据长度决定传输方式

这张图把今天的内容都串起来了。左边是加速传输,右边是分段传输。你写代码的时候,先问自己一句:数据有没有超过4字节?答案出来了,选哪个也就清楚了。

好了,SDO的基础就讲到这里。协议格式、加速传输、分段传输,这三个点你搞明白了,CANopen的数据交互就算入门了。下一节咱们聊聊SDO的超时处理和错误码,那才是真正考验工程能力的地方。


公众号:蓝海资料掘金营,微信deep3321