在使用TwinCAT測試EtherCAT EOE功能時,我們會發(fā)現(xiàn)正常是無法使用Wireshark去進行網(wǎng)絡(luò)抓包抓取EtherCAT報文的,今天這篇文章就帶大家來上手EtherCAT抓包方式。
準(zhǔn)備環(huán)境
硬件環(huán)境:
EtherKit開發(fā)板
網(wǎng)線一根
軟件環(huán)境
TwinCAT3
RT-Thread studio
wireshark
EtherCAT EOE工程下載
首先 RT-Thread studio 安裝 EtherKit SDK 包,然后新建一個示例工程:etherkit_ethercat_eoe,編譯并下載程序;

將電腦一端網(wǎng)線連接至 EtherKit 的 ETH0,同時修改以太網(wǎng)適配器IP保持與從站IP在同一網(wǎng)段下:

觀察開發(fā)板串口狀態(tài),此時可以看到 eoe app 已經(jīng)正常運行了:

TwinCAT3 模擬EtherCAT主站啟動
在啟動 TwinCAT3過程中還需要配置ESI文件及安裝Twin CAT驅(qū)動,可參考EtherKit用戶手冊,此處不再詳述;
接下來我們主站掃描從站設(shè)備,并激活該從站設(shè)備:

激活從站設(shè)備后可以看到 EtherKit 開發(fā)板板載以太網(wǎng)指示燈正常工作,同時默認(rèn)從站DC模式為 SM-Synchron :

TwinCAT3配置DC-Synchron
首先我們需要開啟 wireshark 抓包支持,右鍵點擊 Device,在 Adapter 中勾選 Promiscuous Mode(use with Wireshark only)來開啟混雜模式;
接著我們需要先切換DC模式,由默認(rèn)的 SM-Synchron 模式切換為 DC-Synchron;
接著我們點擊上方導(dǎo)航欄 TwinCAT->Restart TwinCAT(config Mode);
提示 Restart TwinCAT system in config Mode,點擊確定;
shell再次提示 Load IO設(shè)備,點擊確定;
然后點擊激活;
接著我們再切換回 SM-Synchron,并打開wireshark,選擇對應(yīng)的網(wǎng)卡設(shè)備,此時就可以看到ECAT報文了;
EtherCAT數(shù)據(jù)幀結(jié)構(gòu)
EtherCAT數(shù)據(jù)直接使用以太網(wǎng)數(shù)據(jù)幀進行傳輸,幀類型為0x88A4。一個EtherCAT數(shù)據(jù)包括2個字節(jié)的數(shù)據(jù)頭和44~1498字節(jié)的數(shù)據(jù),其中數(shù)據(jù)區(qū)由一個或多個EtherCAT子報文組成,每個子報文對應(yīng)獨立的設(shè)備或從站存儲區(qū)域;
EtherCAT幀結(jié)構(gòu)定義
EtherCAT幀結(jié)構(gòu)定義
每個EtherCAT子報文包括子報文頭、數(shù)據(jù)域和相應(yīng)的工作計數(shù)器(WKC,Working Counter);WKC記錄了子報文被從站操作的次數(shù),主站為每個通信服務(wù)子報文設(shè)置預(yù)期的WKC,發(fā)送子報文中的工作計數(shù)器初值為0,子報文被從站正確處理后,工作計數(shù)器將增加一個增量,主站比較返回子報文中的WKC和預(yù)期WKC來判斷子報文是否被正確處理;WKC由ESC在處理數(shù)據(jù)幀的同時進行處理,不同的通信服務(wù)對WKC的增加方式不同;
EtherCAT子報文結(jié)構(gòu)定義
EtherCAT報文分析
1.請求報文
首先我們設(shè)置過濾規(guī)則:
ecat.cmd==BRD && ecat.ado==0x130
我們隨機抓取一條BRD報文,主站向從站發(fā)送的偏移地址為 0x130 的報文,表示讀取從站特定寄存器(如設(shè)備標(biāo)識符、狀態(tài)字等)的值。此類報文在系統(tǒng)初始化或狀態(tài)監(jiān)測中常被使用。
2.應(yīng)答報文
從站啟動過程:主站依次向偏移地址 0x120 發(fā)送 1、2、4、8 命令,控制從站依次進入初始化(INIT)、預(yù)操作(PRE-OP)、安全模式(SAFE-OP)和操作模式(OP):
ecat.ado==0x120 && (ecat.adp==0x03e9 ||ecat.adp==0xffff)
其中 ecat.adp == 0xffff 表示廣播方式,主站向所有從站發(fā)送命令;而 ecat.adp==0x03e9(例如)表示特定從站地址(可根據(jù)實際地址修改)發(fā)送控制命令。
3.控制命令與EOE報文過濾
我們使用如下過濾規(guī)則來抓取EtherCAT控制命令與以太網(wǎng)封裝(EOE, Ethernet over EtherCAT)相關(guān)的報文:
(ecat.ado==0x120 || ecat_mailbox.eoe) && (ecat.adp==0x03e9 || ecat.adp==0xffff)
解析說明
ecat.ado==0x120:表示抓取訪問地址偏移 0x120 的寄存器命令,此為 從站狀態(tài)控制寄存器,主站通過它向從站發(fā)送模式切換指令(如INIT、PRE-OP、SAFE-OP、OP);
ecat_mailbox.eoe:表示抓取所有 EOE協(xié)議封裝的以太網(wǎng)數(shù)據(jù),EOE允許通過EtherCAT傳輸標(biāo)準(zhǔn)以太網(wǎng)幀(如TCP/IP、UDP);
ecat.adp==0x03e9:指定從站地址為 0x03e9(十進制1001),用于單個從站點對點通信;
ecat.adp==0xffff:表示廣播命令,主站向所有從站同時發(fā)起操作。
應(yīng)用場景
此過濾規(guī)則可用于同時監(jiān)控:
主站對某個從站(或全部從站)的工作模式控制行為;
通過EOE傳輸?shù)臄?shù)據(jù)幀(常見于使用TCP/IP通信的EtherCAT從站,如帶IP接口的遠程IO模塊或工業(yè)攝像頭);
下面是使用Wireshark實際抓包情況:
4. EtherCAT EOE抓包TCP報文
首先我們修改工程目錄下的 src/hal_entry.c 文件,將該文件全部替換為如下代碼:
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-03-11 Wangyuqiang first version*/#include#include"hal_data.h"#include#include#include#include#include#include#defineBUFSZ (1024)staticconstcharsend_data[] ="This is TCP Server from RT-Thread.";voidhal_entry(void){ rt_kprintf("\nHello RT-Thread!\n"); rt_kprintf("==================================================\n"); rt_kprintf("This example project is an ethercat eoe routine!\n"); rt_kprintf("==================================================\n");}staticvoidtcpserv(void*parameter){ char*recv_data;/* 用于接收的指針,后面會做一次動態(tài)分配以請求可用內(nèi)存 */ socklen_tsin_size; intsock, connected, bytes_received; structsockaddr_inserver_addr, client_addr; rt_bool_tstop = RT_FALSE;/* 停止標(biāo)志 */ intret; recv_data =rt_malloc(BUFSZ +1);/* 分配接收用的數(shù)據(jù)緩沖 */ if(recv_data == RT_NULL) { rt_kprintf("No memory\n"); return; } /* 一個socket在使用前,需要預(yù)先創(chuàng)建出來,指定SOCK_STREAM為TCP的socket */ if((sock =socket(AF_INET, SOCK_STREAM,0)) ==-1) { /* 創(chuàng)建失敗的錯誤處理 */ rt_kprintf("Socket error\n"); /* 釋放已分配的接收緩沖 */ rt_free(recv_data); return; } /* 初始化服務(wù)端地址 */ server_addr.sin_family = AF_INET; server_addr.sin_port =htons(5000);/* 服務(wù)端工作的端口 */ server_addr.sin_addr.s_addr = INADDR_ANY; rt_memset(&(server_addr.sin_zero),0,sizeof(server_addr.sin_zero)); /* 綁定socket到服務(wù)端地址 */ if(bind(sock, (structsockaddr *)&server_addr,sizeof(structsockaddr)) ==-1) { /* 綁定失敗 */ rt_kprintf("Unable to bind\n"); /* 釋放已分配的接收緩沖 */ rt_free(recv_data); return; } /* 在socket上進行監(jiān)聽 */ if(listen(sock,5) ==-1) { rt_kprintf("Listen error\n"); /* release recv buffer */ rt_free(recv_data); return; } rt_kprintf("\nTCPServer Waiting for client on port 5000...\n"); while(stop != RT_TRUE) { sin_size =sizeof(structsockaddr_in); /* 接受一個客戶端連接socket的請求,這個函數(shù)調(diào)用是阻塞式的 */ connected =accept(sock, (structsockaddr *)&client_addr, &sin_size); /* 返回的是連接成功的socket */ if(connected 0)? ? ? ? {? ? ? ? ? ? rt_kprintf("accept connection failed! errno = %d\n", errno);? ? ? ? ? ? continue;? ? ? ? }? ? ? ? /* 接受返回的client_addr指向了客戶端的地址信息 */? ? ? ? rt_kprintf("I got a connection from (%s , %d)\n",? ? ? ? ? ? ? ? ? ?inet_ntoa(client_addr.sin_addr),?ntohs(client_addr.sin_port));? ? ? ? /* 客戶端連接的處理 */? ? ? ? while?(1)? ? ? ? {? ? ? ? ? ? /* 發(fā)送數(shù)據(jù)到connected socket */? ? ? ? ? ? ret =?send(connected, send_data,?strlen(send_data),?0);? ? ? ? ? ? if?(ret 0)? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 發(fā)送失敗,關(guān)閉這個連接 */? ? ? ? ? ? ? ? closesocket(connected);? ? ? ? ? ? ? ? rt_kprintf("\nsend error,close the socket.\r\n");? ? ? ? ? ? ? ? break;? ? ? ? ? ? }? ? ? ? ? ? else?if?(ret ==?0)? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 打印send函數(shù)返回值為0的警告信息 */? ? ? ? ? ? ? ? rt_kprintf("\n Send warning,send function return 0.\r\n");? ? ? ? ? ? }? ? ? ? ? ? /* 從connected socket中接收數(shù)據(jù),接收buffer是1024大小,但并不一定能夠收到1024大小的數(shù)據(jù) */? ? ? ? ? ? bytes_received =?recv(connected, recv_data, BUFSZ,?0);? ? ? ? ? ? if?(bytes_received 0)? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 接收失敗,關(guān)閉這個connected socket */? ? ? ? ? ? ? ? closesocket(connected);? ? ? ? ? ? ? ? break;? ? ? ? ? ? }? ? ? ? ? ? else?if?(bytes_received ==?0)? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 打印recv函數(shù)返回值為0的警告信息 */? ? ? ? ? ? ? ? rt_kprintf("\nReceived warning,recv function return 0.\r\n");? ? ? ? ? ? ? ? closesocket(connected);? ? ? ? ? ? ? ? break;? ? ? ? ? ? }? ? ? ? ? ? /* 有接收到數(shù)據(jù),把末端清零 */? ? ? ? ? ? recv_data[bytes_received] =?'\0';? ? ? ? ? ? if?(strcmp(recv_data,?"q") ==?0?||?strcmp(recv_data,?"Q") ==?0)? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 如果是首字母是q或Q,關(guān)閉這個連接 */? ? ? ? ? ? ? ? closesocket(connected);? ? ? ? ? ? ? ? break;? ? ? ? ? ? }? ? ? ? ? ? else?if?(strcmp(recv_data,?"exit") ==?0)? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 如果接收的是exit,則關(guān)閉整個服務(wù)端 */? ? ? ? ? ? ? ? closesocket(connected);? ? ? ? ? ? ? ? stop = RT_TRUE;? ? ? ? ? ? ? ? break;? ? ? ? ? ? }? ? ? ? ? ? else? ? ? ? ? ? {? ? ? ? ? ? ? ? /* 在控制終端顯示收到的數(shù)據(jù) */? ? ? ? ? ? ? ? rt_kprintf("RECEIVED DATA = %s \n", recv_data);? ? ? ? ? ? }? ? ? ? }? ? }? ? /* 退出服務(wù) */? ? closesocket(sock);? ? /* 釋放接收緩沖 */? ? rt_free(recv_data);? ? return?;}static?int?tcpserv_app(void){? ? rt_thread_t?tcps =?rt_thread_create("tcpserv", tcpserv, RT_NULL,?2048,?18,?10);? ? if(tcps != RT_NULL)? ? {? ? ? ? rt_thread_startup(tcps);? ? }? ? return?0;}
編譯下載后重新燒錄程序并啟動,在從站成功連接到主站后,執(zhí)行 tcpserv_app 指令來啟動一個 TCP Server:

同時我們打開 TCP 測試軟件,配置 TCP 客戶端,配置信息如下:
目標(biāo)IP:192.168.10.100(從站IP)
目標(biāo)端口:5000

同時打開 Wireshark ,查看 EtherCAT EOE網(wǎng)絡(luò)下的 TCP報文能夠被成功捕獲:

附錄1 EtherCAT通信服務(wù)命令
EtherCAT 子報文所有的服務(wù)都是以主站操作描述的。數(shù)據(jù)鏈路層去規(guī)定了從站內(nèi)部物理存儲、讀寫和交換(讀取并馬上寫入)數(shù)據(jù)的服務(wù)。讀寫操作和尋址方式共同決定了子報文的通信服務(wù)類型, 由子報文頭中的命令字節(jié)表示:

主站接收到返回數(shù)據(jù)幀后,檢查子報文中的WKC,如果不等于預(yù)期值,則表示此子報文沒有被正確處理。子報文的WKC預(yù)期值與通信服務(wù)類型和尋址地址相關(guān)。子報文經(jīng)過某一個從站時,如果是單獨地讀或?qū)懖僮鳎?WKC 加1 。如果是讀寫操作, 讀成功時WKC加1,寫成功時WKC 加2 ,讀寫全部完成時WKC加3,子報文由多個從站處理時, WKC是各個從站處理結(jié)果的累加。
附錄2 EtherCAT狀態(tài)碼
-
網(wǎng)絡(luò)
+關(guān)注
關(guān)注
14文章
7801瀏覽量
90675 -
開發(fā)板
+關(guān)注
關(guān)注
25文章
5634瀏覽量
103784 -
ethercat
+關(guān)注
關(guān)注
19文章
1084瀏覽量
39860
發(fā)布評論請先 登錄
如何使用TwinCAT3內(nèi)部的函數(shù)來獲取系統(tǒng)時間?
如何去使用TwinCAT3中SCOPE功能?
一種倍福TwinCAT3中讀取臺達伺服扭矩
倍福TwinCAT(貝福Beckhoff)基礎(chǔ)教程 TwinCAT安裝配置
使用TwinCAT3實現(xiàn)高級測量數(shù)據(jù)處理
TwinCAT3的入門教程詳細(xì)說明
TwinCAT 3運動控制教程Version 1.0
RX72M單芯片EtherCAT伺服方案(下)操作說明與規(guī)范
如何基于TwinCAT3實現(xiàn)伺服電機控制

評論