1. PDO 是什么:实时通道 vs 邮箱通道
EtherCAT 从站和主站之间有两种数据通道,分工完全不同:
| 通道 | 承载 | 周期 | 内容 | 例子 |
|---|---|---|---|---|
| 过程数据(PDO) | 帧里的逻辑寻址区(LRW) | 每个通信周期(如 1ms/125μs) | 实时控制量:目标位置、控制字、实际位置、状态字 | CSP 模式每个周期下发 607Ah 目标位置 |
| 服务数据(SDO/邮箱) | 帧里的邮箱区(SM0/SM1) | 按需(非周期) | 配置/诊断:改对象字典、读状态、下载参数 | 启动时读 6098h 回原点方式 |
一句话:PDO 是"每周期必达的实时快递",邮箱是"偶尔寄的信"。 控制环路的正确性取决于 PDO 的确定性——这也是 EtherCAT 用硬件(ESC)处理 PDO 而把邮箱留给软件(从站栈)的原因。
2. 一趟完整的 PDO 旅程:帧 → FMMU → SM → PDI → 对象字典
以一个伺服从站的输出过程数据(主站 → 从站,目标位置)为例:
| 环节 | 在哪儿发生 | 干什么 |
|---|---|---|
| 主站打包 | 主站协议栈 | 把 0x607A 目标位置写进过程数据缓冲,放入 LRW 数据报的逻辑地址区 |
| FMMU 映射 | 从站 ESC 内 | 逻辑地址 → 从站本地内存映射(初始化时配好) |
| SM 缓冲 | 从站 ESC 内 | 数据写入 SM2 输出缓存,置"新数据"事件 |
| PDI 交接 | ESC → MCU | SPI/并行接口把数据交给 MCU(中断或轮询) |
| 对象字典落地 | MCU 从站栈 | 按 PDO 映射把位流拆回 0x607A 等对象值,应用层 FOC 消费 |
输入方向(从站 → 主站:实际位置 0x6064)对称:应用写对象字典 → 按映射打包进 SM3 输入缓存 → FMMU → 帧返回主站,WKC 工作计数器 +2。注意 PDO 全程硬件级流转,不经过 MCU 协议解析——MCU 只做"对象字典 ⇄ 位流"的搬运,这正是 EtherCAT 能跑 125μs 周期的关键。
3. TxPDO / RxPDO 方向约定与伺服典型 PDO
RxPDO = 从站接收(主站 → 从站,输出过程数据);TxPDO = 从站发送(从站 → 主站,输入过程数据)。最容易搞反——记住"R=Receive,站在从站角度看"。主站侧常叫"输出/输入 SM",含义相反,对配置文档时先确认视角。
| 方向 | 对象 | 名称 | 典型位长 |
|---|---|---|---|
| RxPDO (主站→从站) | 0x6040 | 控制字(使能/使能运行/停机) | 16 bit |
| 0x6060 | 操作模式(CSP/CST/CSV) | 8 bit | |
| 0x607A | 目标位置 | 32 bit | |
| 0x60FF | 目标速度 | 32 bit | |
| TxPDO (从站→主站) | 0x6041 | 状态字(就绪/使能/故障) | 16 bit |
| 0x6064 | 实际位置 | 32 bit | |
| 0x606C | 实际速度 | 32 bit | |
| 0x6077 | 实际转矩 | 16 bit |
4. PDO 映射:对象字典条目如何编码成位流
一个 PDO 是一串"要一起传的对象",映射表定义了哪些对象、从哪个子索引、占多少位。EtherCAT CoE 里每个 PDO 对应一个映射对象(0x1A00 起 TxPDO / 0x1600 起 RxPDO),结构如下:
| 子索引 | 内容 | 示例(0x1A00 TxPDO) |
|---|---|---|
| 0 | 映射条目数量(计数) | 3 |
| 1 | 第 1 个映射条目(32 bit 三元组) | 6041h · 00h · 16 bit → 状态字 |
| 2 | 第 2 个映射条目 | 6064h · 00h · 32 bit → 实际位置 |
| 3 | 第 3 个映射条目 | 606Ch · 00h · 32 bit → 实际速度 |
bit31..16 = 对象索引(16 bit) | bit15..8 = 子索引(8 bit) | bit7..0 = 位长度(8 bit)
例:0x60640020 = 索引 0x6064、子索引 0、32 bit。读取映射时先读子索引 0 得到条数,再逐条读三元组
把映射条目"排进"过程数据缓冲时,按条目顺序位连续拼接:上面 0x1A00 三个条目共 16+32+32 = 80 bit = 10 字节,主站和从站都按这个布局读写同一块缓冲——映射表就是两端共用的"快递单"。
5. CoE 对象字典里的 PDO 组织:0x1600 / 0x1A00 / 0x1C00 / 0x1C10 / 0x1C11
PDO 不是散装的,CoE 用一套固定索引把它们组织起来:
| 索引区 | 含义 |
|---|---|
| 0x1600 ~ 0x17FF | RxPDO 参数(每个接收 PDO 一个:映射条目 + 方向/触发信息) |
| 0x1A00 ~ 0x1BFF | TxPDO 参数(每个发送 PDO 一个) |
| 0x1C00 | 同步管理器类型:SM0/1=邮箱、SM2=过程数据输入、SM3=过程数据输出 |
| 0x1C10 | 过程数据输入 SM 的 PDO 分配列表(= 该 SM 使用哪些 0x1Axx) |
| 0x1C11 | 过程数据输出 SM 的 PDO 分配列表(= 该 SM 使用哪些 0x16xx) |
| 0x1C12 / 0x1C13 | 邮箱输入/输出 SM 的 PDO 分配(一般为空) |
主站把 0x1C11 填上 [0x1600, 0x1601, ...],从站才知道"SM3 输出通道由这些 RxPDO 组成",然后按 0x16xx 里的映射去打包/拆包。改 PDO 的标准动作就是先改映射(0x16xx/0x1Axx 子索引),再改分配(0x1C10/0x1C11),最后重启通信状态机(Init → PreOp → SafeOp → OP)。
6. 位对齐、字节序与长度计算
映射打包有两条硬规则:
- 位连续:各条目按顺序紧密排列,不做 8/16 位对齐填充——前提是映射条目本身按规范要求"对齐友好"(EtherCAT 规范建议 8 位边界对齐,强制禁止条目跨超过 32 位的边界组合);
- 小端(little-endian):过程数据缓冲按小端存放多字节对象,与 ARM/x86 内存一致,无需软件翻转。
L = ⌈(Σi bitleni) / 8⌉ 字节
Rx 例:控制字 16 + 目标位置 32 + 目标速度 32 = 80 bit → 10 字节;Tx 例:状态字 16 + 实际位置 32 = 48 bit → 6 字节。主站按 ESI/EEPROM 里的映射算出的长度,必须与从站 SM2/SM3 的缓存长度一致,否则 WKC 不匹配
8 bit 边界对齐的约定还带来一个工程好处:可以直接用 memcpy 搬运,不必做位操作;只有出现"半个字节"的怪映射(如 12 bit 对象)才需要位写入器(见第 9 节代码)。
7. 同步机制:SM 事件 vs DC 分布式时钟
| 机制 | 原理 | 精度 | 适用 |
|---|---|---|---|
| SM 事件(帧同步) | ESC 收到该 SM 的数据帧时产生中断/事件,MCU 收到即处理 | 取决于主站帧抖动(μs 级~几十 μs) | 单从站、对同步要求不苛刻 |
| DC(分布式时钟) | 全网从站对齐到参考时钟,按绝对时间(Sync0)同时启动输出 | ns 级(<1μs 典型) | 多轴联动、伺服轨迹同步——必选 |
DC 模式下 PDO 的消费时点由Sync0 中断决定:主站提前一个周期下发数据,所有从站在同一时刻(相位对齐的 Sync0)取数执行——这就是"多轴同起同停"的物理基础。SM 事件与 DC 可以并存:SM 负责数据到位,DC 负责消费时点。从站是否支持 DC 由 EEPROM F8 段声明(见《EtherCAT EEPROM 作用详解》)。
8. PDO 配置从哪来:EEPROM → ESI → 主站覆盖
从站出厂时的默认 PDO 长什么样,源头有三层:
- EEPROM(F4/F5 段):出厂默认 Tx/Rx PDO 映射,主站上电时先读它建初始过程数据;
- ESI 文件(XML):厂商发布的设备描述里带完整 PDO 定义(含所有可选映射),主站据此提供配置界面;
- 主站运行期覆盖:CoE 写 0x1600/0x1A00 映射 + 0x1C10/0x1C11 分配,从站按新配置收发——EEPROM 里的默认值被覆盖但不必落盘。
三层的关系:EEPROM 定"出厂默认",ESI 定"能力全集",主站定"现场实配"。现场改 PDO 不写 EEPROM(重启恢复默认),要固化才需要主站工具写回。
9. 交互演示:PDO 映射位打包
勾选要放进 RxPDO(主站→伺服)的对象,看它们如何按映射顺序连续打包成字节流:
观察要点:
- 对象按勾选顺序连续拼接,不做填充;总位长 Σbitlen 向上取整字节;
- 32 bit 对象(目标位置)在缓冲里按小端存放(低字节在前),主从两端内存模型一致;
- 加/减对象后总字节数变化,必须同步 0x1C11 分配与 SM3 缓存长度,否则主站会报过程数据长度不匹配。
10. 代码实现(C语言,可编译模块)
从站 MCU 侧把对象字典值打包进过程数据缓冲——用位写入器处理任意位长(含非字节对齐),对齐友好的映射退化成 memcpy 也可:
应用侧:映射表在 PreOp 阶段从 0x1A00/0x1600 对象字典读出(子索引 0 = 条数),存成 pdo_entry 数组;进入 OP 后每周期调 pack/unpack。位写入器对字节对齐映射也正确——只是稍慢,追求极致周期时可换成按字节 memcpy 的快速路径。
11. 工程避坑清单
| 坑 | 现象 | 对策 |
|---|---|---|
| Tx/Rx 方向搞反 | 配置里怎么都对,跑起来数据全错/不更新 | 以从站视角命名:Rx=收、Tx=发;对照 ESI 的 SM 方向再填 0x1C10/0x1C11 |
| 映射与 SM 缓存长度不一致 | 主站报过程数据长度错误 / WKC 异常 | 总位长 ⌈Σbitlen/8⌉ 必须等于 SM2/SM3 配置长度;改映射后同步改 SM |
| 改了映射没重启状态机 | 新映射不生效或部分生效 | PDO 修改后必须 Init → PreOp → SafeOp → OP 完整走一遍(0x1C10/1C11 在 PreOp 下发) |
| 多字节对象字节序混乱 | 位置/速度值错乱但控制正常 | 确认小端存放;跨架构(如大端 DSP)时在 PDI 边界做字节交换 |
| 非 8 位对齐映射 | 打包错位、偶发数据错 | 规范上强制禁止条目组合跨 32 bit 边界;尽量全用 8/16/32 bit 对象 |
| DC 时相位未对齐 | 多轴"同时"但输出时刻有固定偏移 | 用 Sync0 周期与相移寄存器统一;DC 从站先跑"DC 同步窗口"校准 |
| EEPROM 默认 PDO 与 ESI 不一致 | 同一从站不同批次行为不同 | F4/F5 段内容由 SSC 从 ESI 生成,量产 bin 与 ESI 版本绑定校验 |
一句话收尾:PDO 是 EtherCAT 实时性的心脏——映射决定"传什么",分配决定"谁传",同步决定"什么时候用",三者对齐,从站才真正"实时"。