EtherCAT数据帧抓包解析(RxPDO配置过程详解)
EtherCAT数据帧抓包解析(RxPDO配置过程详解)
目录
使用顺序寻址命令设置从站地址(从站地址也叫Ado,Slave Address) 6
阅读前需要掌握EtherCAT基础知识,这里记录的是一个RxPDO配置的完整历程。
博客园上传文件的时候docx文件颜色不见了,我传个pdf,点这里下载
EthereCAT报文数据帧结构
这是主站运行后发的第一帧。
为了方便看,我标个色:
填充段:数据段后到FSC段(da 26 ad df)白色的是填充字段,要填充到最短44字节,为什么限制了最短字节,可以看这篇文章:在传统以太网中为什么要有最小帧长度和最大帧长度的限制 - 道客巴巴 (doc88.com);
目的地址:ff ff ff ff ff ff6个f说明主从站采用直连模式,如果是开放模式,即EtherCAT网段连接到一个标志的以太网交换机上,那这个地址为第一个从站的ISO/IEC 8802.3的MAC地址。
源地址:00 00 00 00 00 主站的MAC地址。
帧类型:88a4 固定为0x88A4,如果使用UDP/IP协议有传输EtherCAT数据,需开放UDP端口0x88A4,如下图所示:
EtherCAT数据长度:0d所有子报文长度总和,该数据长度为11位,发过来是完整的两字节小端模式,正确排序是0x100d,把0x100d写成二进制:
0001 0000 0000 1011;
把无关的位用*代替:
0001 **** **** ****高四位,是类型;
**** 1*** **** ****高第五位是保留位;
**** *000 0000 1011剩余的低11位是数据长度。
类型:1表示与从站通讯,其余保留。
命令:08 寻址方式及读写方式,EtherCAT所有命令如下表所示:
寻址方式 |
读写模式 |
命令名称和编号 |
解释 |
WKC |
空指令 |
---- |
NOP(0) No Operation |
没有操作 |
0 |
顺序寻址 |
读数据 |
APRD(1) Auto Increment Read |
主站使用顺序寻址从从站读取一定长度数据,从站对地址加1 |
1 |
写数据 |
APWR(2) Auto Increment Write |
主站使用顺序寻址向从站写入一定长度的数据,从站对地址加1 |
1 |
|
读写 |
APRW(3) Auto Increment Read Write |
主站使用顺序寻址与从站交换数据,从站对地址加1 |
3 |
|
设置寻址 |
读数据 |
FPRD(4) Configured Address Read |
主站使用设置寻址从从站读取一定长度的数据 |
1 |
写数据 |
FPWR(5) Configured Address Write |
主站使用设置寻址向从站写入一定长度的数据 |
1 |
|
读写 |
FPRW(6) Configured Address Read Write |
主站使用设置寻址与从站交换数据 |
3 |
|
广播寻址 |
读数据 |
BRD(7) Broadcast Read |
主站从所有从站的物理地址读取数据并做逻辑或操作,每个从站对地址加1 |
与寻址到从站个数相关 |
写数据 |
BWR(8) Broadcast Write |
主站广播写入所有从站,每个从站对地址加1 |
||
读写 |
BRW(9) Broadcast Read Write |
主站与所有从站交换数据,对读取的数据做逻辑或操作,每个从站对地址加1,一般不使用该命令 |
||
逻辑寻址 |
读数据 |
LRD(10) Logical Memory Read |
读取的逻辑地址和从站设置FMMU一致时,读取一定长度的数据 |
|
写数据 |
LWR(11) Logical Memory Write |
写入的逻辑地址和从站设置FMMU一致时,写入一定长度的数据 |
||
读写 |
LRW(12) Logical Memory Read Write |
逻辑地址和从站设置FMMU一致时从站交换数据 |
||
顺序寻址 |
读,多重写 |
ARMW(13) Auto Increment Read Multiple Write |
由从站读取数据,并写入以后所有从站相同的地址 |
|
设置寻址 |
FRMW(14) Configured Read Multiple Write |
这条数据的08表示使用广播寻址对所有从站写入数据。
索引:80 BWR命令下每发出1条子报文,索引会加1,范围在0x80~0xff,注意这个准确的应该叫帧编码,不要跟字典的索引混淆。不同命令对于帧编码的使用是不同。
地址区: 00 00 01 01 除逻辑寻址命令外,地址区会拆分成Slave Addr 和 Offset Addr,也就是Slave Addr:0x0000,Offset Addr:0x0101,注意一下,这是小端模式,要怎么读你懂的;如果是逻辑寻址,地址区就只有一个32位的 Log Addr:0x 01010000。
长度:0100 报文数据区长度,小端模式,正确排序是0x0001,将它扩写成二进制:
0000 0000 0000 0001;
把无关的位用*代替:
0*** **** **** ****最高位,就是帧结构里的M,为0表示只有一帧,为1表示后续还有后续报文;
*000 0*** **** ****高2、3、4位是保留位,但实际情况下,使用wireshark解析,高第二位的定义是.0.. .... .... .... = Round trip: Frame is not circulating;
**** *000 0000 0001剩余的低11位是数据长度。
状态位:0000中断到来标志。
数据:00 报文结构,用户定义。
WKC:00 WKC了子报文被从站操作的次数,主站为每个通信服务子报文设置预期的WKC。发送子报文中的工作计数器初值为0,子报文被从站正确处理后,工作计数器的值将增加一个增量,主站比较返回子报文中的WKC和预期WKC来判断子报文是否被正确处理。WKC由ESC在处理数据帧的同时进行处理,不同的通信服务对WKC的增加方式不同。
FCS:da26addf帧校验序列。
使用顺序寻址命令设置从站地址(从站地址也叫Ado,Slave Address)
此报文有两帧,第一帧给地址为0进行复位:
第二帧的0x3e9为使用设置寻址命令时所写入的地址:
偏移地址offset Addr0x0010是ESC芯片里的一个物理地址,对应的寄存器描述如下:
地址 |
位 |
名称 |
描述 |
复位值 |
0x0010~0x0011 |
0~15 |
设置站点地址 |
设置寻址所用地址(FPRD\FPWR和FPRW命令) |
0 |
设置完成,使用设置寻址,从站地址(Slave Addr)为0x03e9就可以与目标从站通讯:
SM相关寄存器信息:
偏移地址 |
位 |
名称 |
描述 |
复位值 |
+0x0 : 0x1 |
0~16 |
数据物理地址起始位 |
SM处理的第一个字节在ESC地址空间的起始位置 |
0 |
+0x2 : 0x3 |
0~16 |
SM数据长度 |
分配给SM通道的数据长度,必须大于1,否则SM将不被激活;设置为1时只使能看门狗 |
0 |
+0x4 |
0~7 |
SM控制寄存器 |
||
0~1 |
运行模式 |
00:3个缓存区模式 01:保留 10:单个缓存区模式 11:保留 |
00 |
|
2~3 |
方向 |
00:读,ECAT读访问,PDI写访问 01:写,ECAT写访问,PDI读访问 10:保留 11:保留 |
00 |
|
4 |
ECAT帧中断请求触发 |
0:不使能 1:使能 |
0 |
|
5 |
PDI中断请求触发 |
0:不使能 1:使能 |
0 |
|
6 |
看门狗触发 |
0:不使能 1:使能 |
||
7 |
保留 |
|||
+0x5 |
0~7 |
SM状态寄存器 |
||
0 |
写中断 |
1:写操作完成后触发中断 0:读第一个字节后清除 |
0 |
|
1 |
读中断 |
1:写操作完成后触发中断 0:读第一个字节后清除 |
0 |
|
2 |
保留 |
|||
3 |
单缓存状态 |
单缓存区模式:缓存区状态 0:缓存区空闲 1:缓存区满 |
0 |
|
4~5 |
多缓存状态 |
多缓存区模式:最后写入的缓存区 00:缓存区1 01:缓存区2 10:缓存区3 11:没有写入缓存区 |
11 |
|
6~7 |
保留 |
|||
+0x6 |
0~7 |
ECAT帧控制SM激活 |
||
0 |
SM使能 |
0:不使能,不使用SM控制对内存的访问 1:使能,SM激活,控制设置其中的内存访问 |
0 |
|
1 |
重复请求 |
请求重复邮箱数据传输,主要与ECAT帧读邮箱一起使用 |
0 |
|
2~5 |
保留 |
|||
6 |
ECAT帧访问事件锁存 |
0:无操作 1:EtherCAT主站读写一个缓存区后产生锁存事件 |
0 |
|
7 |
PDI访问事件锁存 |
0:无操作 1:PDI读写一个缓存区或PDI访问缓存区起始地址时产生锁存事件 |
0 |
|
+0x7 |
0~7 |
PDI控制SM |
||
0 |
使SM无效 |
读和写的含义不同 读 0:正常操作,SM激活 1:SM无效,并锁定对内存区的访问 写 0:激活SM 1:请求SM无效,直到当前正在处理的数据帧结束 |
0 |
|
1 |
重复请求应答 |
与重复请求位相同时,表示PDI对前面设置的重复请求的应答 |
0 |
|
2~7 |
保留 |
0 |
这是配置SM2的数据帧,让SM2管理的从站物理地址为0x1800:
从站上会生成三个缓冲区,当0x1800有数据变动时,缓冲区同步数据,这样主站发起读的命令时可以快速将0x1800数据从缓冲区读走。当主站有数据需要写入0x1800的时候,先写入在缓冲区,从站有空再把数据搬过去0x1800,通过这样的机制来完成快速交互的目的,也保证了数据的安全与一致。
下面是配置SM3的数据帧,管理的地址为1C00:
配置SM0的数据帧,管理的地址为1000,用来SDO写邮箱:
配置SM0的数据帧,管理的地址为1400,用来SDO读邮箱:
EtherCAT子报文可以使用逻辑寻址方式访问ESC内部存储空间,ESC使用FMMU通道实现逻辑地址映射。每个FMMU通道使用16个字节配置寄存器,从0x0600开始。下表是FMMU通道配置寄存器的含义:
偏移地址 |
位 |
名称 |
描述 |
复位值 |
+0x0~0x3 |
0~31 |
数据逻辑其实地址 |
在EtherCAT地址空间内的逻辑起始地址 |
0 |
+0x4~0x5 |
x0~15 |
数据长度(字节数) |
从第一个逻辑FMMU字节到最后一个FMMU字节的偏移量增加1字节,例如,如果使用2个字节,取值为2 |
0 |
+0x6 |
0~2 |
数据逻辑起始位 |
应该映射的逻辑起始位,从最低有效位(=0)到最高有效位(=7)计数 |
0 |
3~7 |
保留 |
|||
+0x7 |
0~2 |
数据逻辑终止位 |
应该映射的最后一位,从最低有效位(=0)到最高有效位(=7)计数 |
0 |
3~7 |
保留 |
|||
+0x8~0x9 |
0~15 |
从站物理内存起始位置 |
物理起始地址,影射到逻辑起始地址 |
0 |
+0xA |
0~2 |
物理内存起始位置 |
物理起始位,影射到逻辑起始位 |
0 |
3~7 |
保留 |
|||
+0xB |
0 |
读操作控制 |
0:无读访问映射 1:使用读访问映射 |
0 |
1 |
写操作控制 |
0:无写访问映射 1:使用写访问映射 |
0 |
|
2~7 |
保留 |
|||
+0xC |
0 |
激活 |
0:不激活FMMU 1:激活FMMU,用以检查根据映射配置所有映射逻辑地址块 |
0 |
1~7 |
保留 |
|||
+0xD~+0xF |
0~23 |
保留 |
0 |
查看捕获到的配置FMMU相关报文,第一帧是将十六个通道的FMMU全部置为0:
设置物理地址0x1800的FMMU映射为0x12000:
设置物理地址0x1C00的FMMU映射为0x11000:
设置缓冲区状态0x80D的FMMU映射0x40000:
对应ZLGEtherCATStudio(周立功EtherCAT主站)上位机设置:
上图中画红色方框的是生成信息的总览。
通过上方的操作,主站就可以通过逻辑寻址快速访问某一ESC上0x1800、0x1c00、0x080D的数据,这样做的好处,比如我使用设置寻址范文1号从站的0x1800的数据时,需要先找到1号从站,然后告诉1号从站说把0x1800的数据拷给我,从站确认没东西在写或者读那块地址,再把那段地址的数据读出来填充到主站发过来的数据帧上(这里挺浪费时间跟容易数据混乱的,FMMU解决不了问题,所以又创造出了SM这个东西)。
你可能会想,那就发条报文设置寻址读呗,配置FMMU不也得寻个址,脱了裤子放屁,如果只是读一个从站的数据,你这么想也是没问题的,但我要你拿100个从站的数据怎么办,你是不是得发100条子报文,这么做增加了网络负载,也增加了主站程序发送报文时填充数据的时间开销。重点来了,有了FMMU后,主站上的一段内存地址就跟从站的每个FMMU匹配上了,光打字可能不清楚,我画个图:
地址:0x10000 数据:1A |
地址0x10010 数据:2B |
地址0x10020 数据:3C |
地址0x10030 数据:4D |
地址0x10040 数据:5E |
地址0x10050 数据:2F |
… |
||
从站1 FMMU |
地址:0x10000 数据:1A |
地址:0x10010 数据:FF |
地址:0x10020 数据:FF |
地址:0x10030 数据:FF |
地址:0x10040 数据:FF |
地址:0x10050 数据:FF |
… |
|
从站2 FMMU |
地址:0x10000 数据:FF |
地址:0x10010 数据:2B |
地址:0x10020 数据:FF |
地址:0x10030 数据:FF |
地址:0x10040 数据:FF |
地址:0x10050 数据:2F |
… |
|
从站3 FMMU |
地址:0x10000 数据:FF |
地址:0x10010 数据:FF |
地址:0x10020 数据:3C |
地址:0x10030 数据:FF |
地址:0x10040 数据:FF |
地址:0x10050 数据:FF |
… |
|
从站4 FMMU |
地址:0x10000 数据:FF |
地址:0x10010 数据:FF |
地址:0x10020 数据:FF |
地址:0x10030 数据:4D |
地址:0x10040 数据:FF |
地址:0x10050 数据:FF |
… |
|
从站5 FMMU |
地址:0x10000 数据:FF |
地址:0x10010 数据:FF |
地址:0x10020 数据:FF |
地址:0x10030 数据:FF |
地址:0x10040 数据:5E |
地址:0x10050 数据:FF |
… |
|
… |
… |
… |
… |
… |
… |
… |
… |
|
无背景为未配置FMMU通道,主站不会同步数据 |
有背景为配置了FMMU通道为读,主站同步数据 |
主站发送命令为LRD(逻辑寻址读)数据帧:逻辑地址0x10000,长度0x30,数据帧到达从站1,此时从站1匹配到主站要访问的0x10000,从站1的FMMU0x10000已经配置了映射到某某物理地址,就把数据搬到主站数据帧的对应位置上去,匹配到0x10010的地址时,从站发现FMMU没有配置,不做任何操作。主站数据帧发出到从站2的时候,从站2匹配0x10000地址时,发现FMMU没有配置该逻辑地址,跳过不处理,匹配到0x10010时,FMMU配置了,把数据搬上车,后续从站处理方法同理。
主站发送命令为LWR(逻辑寻址写)数据帧:假设添加背景色的地址,已经配置了FMMU该地址为写,此时数据处理的方式跟LRD大致相同,不同的是,从站会将主站发出的数据帧上的数据同步到本地。
主站发送命令为LRW(逻辑寻址读写)数据帧:假设添加背景色的地址,已经配置了FMMU该地址为读写访问,此时数据处理的方式跟LRD大致相同,不同的是,从站会将主站发出的数据帧上的数据同步到本地,将本地的数据填充到主站数据帧上。
经过FMMU映射,主站已经可以通过逻辑寻址0x12000、0x11000、0x40000快速访问从站物理地址0x1800、0x1C00、0x80D。
0x1800跟0x1C00是从站厂商决定的存放过程数据的地址,厂商通过程序将各个数据放到对应的地址上。
0x80D是SM1的数据更新标志位,主站到从站邮箱通讯用SM0,从站到主站邮箱通讯用SM1,所有数据交换都由主站发起的,如果从站有数据发送给主站,必须先将数据写入发送邮箱缓冲区,然后由主站来读取,于是主站可以通过将0x80D.3映射到逻辑地址0x40000,使用逻辑寻址周期性的读这一标志位。
现在,主站从站已经有协商好的过程数据(PDO)的逻辑存放地址了,下一步是主站跟从站统一PDO的数据结构,详细的说,主站想要从站在FMMU的0x12000逻辑地址上,放以下这几种数据:
对应从站物理地址0x1800,要在这个地址空间上放的是以上的数据结构(0x1800是从站厂商决定的,从站上跑的程序要将这些数据按规定的RxPDO结构排好放到0x1800上)。
主站和从站如何协商数据结构:
PDO是有分组的,每个从站PDO组数跟硬件相关,不同PDO组里的PDO子项不同,有的PDO分组可以修改,有的不能修改,这里先介绍PXPDO,主站决定使用哪组PDO后,将索引这组PDO的索引号(比如0x1601)写入邮箱的0x1c12,然后将PDO的各个子项索引(比如0x6060)写入邮箱的0x1601。
数据都需要经过SM0(物理地址0x1000邮箱数据地址,0x1000以上的地址,各个厂商有所不同),主站发送邮箱数据到SM0,从站根据数据结构解析数据(结构如下所示),按邮箱索引配置各个通讯参数。
为帮助理解,可以看下图描述:
主站将邮箱数据指令发送到从站的0x1000,从站程序解析指令,将‘0x1601索引号’写入索引0x1c12,将‘各PDO子项索引号’写入索引0x1601。
从站进入OP状态后,将根据设定,按照索引0x1601的子索引号访问对应的空间数据,并将数据复制到SM2管理的物理地址上,如0x1800。
邮箱
Phy:
0x1000
索引Index:0x1601(RxPDO2映射参数)
填入数据:0x60400010
0x60600008
…
索引Index:0x1c12(RXPDO索引管理)
填入数据:0x1601
从站
RxPDO分组有以下几种:
下面是主站给SM0发送邮箱数据,设定将‘0x1601索引号’填入邮箱的0x1C12索引中:
设定0x1C12 RXPDO分配索引数为1:
将PDO子项索引参数写入0x1601:
索引 |
子索引 |
|
1601h |
00h |
RPDO映射应用对象数目 |
01h |
第1个映射应用对象 |
|
02h |
第2个映射应用对象 |
|
… |
… |
|
40h |
第40个映射应用对象 |
Data项0x6040是索引号,后面跟着的00、10分别是子索引、长度。
EtherCAT每个通讯周期都会发送以下几个子报文:
一共四条,第一条子报文逻辑寻址读0x11000,是TxPDO读取,数据位全部为零,经过从站后,从站的FMMU单元会将0x11000上的数据填入到Data中;
第二条子报文逻辑寻址写0x12000,是RxPDO写入,数据位全部为零是因为我的程序给了零,后面的抓的数据帧被我删掉了,虽然都是0但都是参数,从站的FMMU会将这段数据读取后放到自己的0x12000上,不信你自己去试试;
第三条子报文是逻辑寻址读0x40000,读取邮箱状态位,它对应的是0x80D地址(SM1状态寄存器),从站的FMMU单元会把自己0x40000的数据填充到Data中,如果主站检测到回来的这条子报文第3位为1,它会一个设置寻址读0x1000的邮箱数据帧就甩到这个从站脸上,总结一下,就是这个0x40000的作用是从站用来告诉主站说,从站有数据要出来了,它憋不住了;
第四条子报文是DC同步,读去第一个从站的DC数据,写入到后续的从站中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架