3、EtherCAT从站协议栈解析

各位同学,今天我们来聊聊EtherCAT从站协议栈。说实话,这个主题我讲了不下十次,但每次都有新感悟。EtherCAT从站协议栈,说白了就是让一个普通设备能听懂EtherCAT主站说话的那套规则。你想想看,一个伺服驱动器、一个IO模块,它们怎么知道主站发来的数据是位置指令还是速度指令?靠的就是这套协议栈。

3.1 EtherCAT数据帧结构

先看数据帧。EtherCAT的数据帧结构,我习惯把它想象成一列火车。火车头是以太网帧头,后面挂着一节节车厢,每节车厢就是一个EtherCAT子报文。

标准以太网帧长1518字节,EtherCAT数据帧就塞在里面。它的以太网帧类型是0x88A4,这个值我记了十年——因为当年调试时抓包看到这个值,才知道数据已经正确到达了从站。

EtherCAT数据帧结构(关键字段)

  • 以太网帧头:目的MAC、源MAC、帧类型(0x88A4)
  • EtherCAT头:11位长度 + 1位保留 + 4位类型
  • 子报文1:命令 + 索引 + 地址区 + 长度 + R + M + 状态位 + 数据区 + WKC
  • 子报文2:同上结构
  • ...
  • 子报文N:同上结构
  • FCS:帧校验序列

每个子报文里有个WKC(工作计数器),这东西太重要了。我在项目中遇到过,从站没响应,一看WKC没增加,就知道问题出在从站处理上。WKC就像快递签收单,主站发出去,从站处理完必须把WKC加1,否则主站就知道出问题了。

子报文的数据区最大1486字节。为什么是这个数?因为以太网帧最大1518,减去各种头尾开销,剩下的就是数据区。嗯,这里要注意,实际项目中很少塞满,一般就几十个字节,够用就行。

3.2 从站控制器(ESC)寄存器映射

ESC寄存器映射,我建议你把它当成一张地图。每个从站芯片内部都有固定的寄存器地址,主站通过读写这些寄存器来控制从站行为。

ESC寄存器分为几个区域:

地址范围区域名称说明
0x0000 - 0x0FFF寄存器区状态控制、中断、AL事件等
0x1000 - 0x10FFFMMU区现场总线内存管理单元配置
0x1100 - 0x11FFSyncManager区同步管理器通道配置
0x1200 - 0x12FFPDO配置区过程数据对象映射表
0x2000 - 0xFFFF应用层区用户自定义数据

我个人习惯把0x0200到0x020F这16个字节背下来,它们是AL状态机控制寄存器。每次调试从站状态切换,我第一件事就是读这个区域,看看当前状态对不对。

小技巧:调试时用Wireshark抓包,过滤条件写"ethercat",然后看子报文里的地址区。如果地址是0x0200,那肯定是在操作AL状态机。这个技巧帮我省了不少排查时间。

3.3 状态机(Init、Pre-Op、Safe-Op、Op)

EtherCAT从站状态机,我把它比作一个人的成长阶段。Init是婴儿期,Pre-Op是学步期,Safe-Op是少年期,Op是成年期。每个阶段能做的事情不一样。

状态切换路径是这样的:

  • Init → Pre-Op:初始化完成,可以配置邮箱通信
  • Pre-Op → Safe-Op:邮箱通信建立,开始同步PDO映射
  • Safe-Op → Op:PDO映射完成,开始正常数据交换
  • 任何状态 → Init:出错或复位

我曾经踩过一个坑:从站从Pre-Op切到Safe-Op时,主站发了切换命令,但从站没反应。查了半天,发现是SyncManager通道没配置好。说白了,状态切换不是你想切就能切,每个步骤都有前置条件。

避坑指南:状态切换时,一定要检查AL状态寄存器的错误码。如果切换失败,错误码会告诉你原因。我曾经因为没检查这个,浪费了整整两天时间。

状态机里有个AL事件寄存器(0x0220),主站写这个寄存器来请求状态切换。从站处理完后,把状态更新到AL状态寄存器(0x0130)。这两个寄存器配合使用,就像打电话和接电话的关系。

3.4 过程数据对象(PDO)映射

PDO映射,说白了就是告诉从站:主站发来的数据,哪个字节对应哪个参数。比如一个伺服驱动器,主站发来8个字节,前4个是位置指令,后4个是速度指令。这个对应关系就是PDO映射。

PDO映射分为两种:

  • RxPDO:主站发给从站的数据(接收方向)
  • TxPDO:从站发给主站的数据(发送方向)

每个PDO映射条目包含三个信息:索引、子索引、位长度。比如0x6040:00:16,表示对象0x6040的子索引0,长度16位。这个对象在CiA402标准里是控制字,用来控制伺服电机的启停。

我建议你在设计从站时,把PDO映射表放在EEPROM里。这样主站可以通过SDO在线修改映射关系,不用每次改固件。我在一个项目中就是这么做的,客户要换电机型号,我远程改了PDO映射就搞定了,省了出差成本。

PDO映射示例(伺服驱动器)

RxPDO 1 (0x1600):
  0x6040:00:16  // 控制字,16位
  0x607A:00:32  // 目标位置,32位
  0x60FF:00:32  // 目标速度,32位

TxPDO 1 (0x1A00):
  0x6041:00:16  // 状态字,16位
  0x6064:00:32  // 实际位置,32位
  0x606C:00:32  // 实际速度,32位

PDO映射的位长度必须对齐。比如你映射了一个16位的对象,那它在数据区里就占2个字节。如果下一个对象是32位的,那它从第3个字节开始,占4个字节。嗯,这里要注意,不要出现位不对齐的情况,否则数据会错位。

我见过一个案例,有人把16位对象映射成32位,结果后面所有数据都偏移了2个字节。排查了三天才发现是映射长度写错了。所以,PDO映射表一定要仔细核对,最好用工具自动生成。

最后说一句,EtherCAT从站协议栈看起来复杂,但只要你理解了数据帧结构、ESC寄存器、状态机和PDO映射这四块,剩下的就是细节问题了。我在项目中反复验证过,这四块是核心中的核心。

EtherCAT从站协议栈核心知识体系 EtherCAT从站协议栈 数据帧结构 ESC寄存器映射 状态机 PDO映射 以太网帧头 + 子报文 + FCS WKC工作计数器 0x0000-0x0FFF 寄存器区 0x0200 AL状态机控制 Init → Pre-Op → Safe-Op → Op AL事件 + AL状态寄存器 RxPDO + TxPDO 索引:子索引:位长度 核心:数据帧 + 寄存器 + 状态机 + PDO 四者缺一不可,共同构成EtherCAT从站协议栈

个人经验:我建议初学者先从状态机入手,把Init到Op的切换流程跑通。状态机通了,数据帧和PDO映射自然就理解了。别一上来就啃寄存器手册,容易劝退。


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