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 - 0x10FF | FMMU区 | 现场总线内存管理单元配置 |
| 0x1100 - 0x11FF | SyncManager区 | 同步管理器通道配置 |
| 0x1200 - 0x12FF | PDO配置区 | 过程数据对象映射表 |
| 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映射这四块,剩下的就是细节问题了。我在项目中反复验证过,这四块是核心中的核心。
个人经验:我建议初学者先从状态机入手,把Init到Op的切换流程跑通。状态机通了,数据帧和PDO映射自然就理解了。别一上来就啃寄存器手册,容易劝退。
公众号:蓝海资料掘金营,微信deep3321