Windows10 利用QT搭建SOEM开发环境

文章目录

  • 一. SOEM库简介
  • 二. 安装WinPcap
  • 三. SOEM(1.4)库安装
    • (1) 编译32位库
    • (2) 编译64位库
  • 四. 运行SOEM示例代码
  • 五. WIN10下利用QT构建SOEM开发环境

一. SOEM库简介

SOEM(Scalable Open EtherCAT Master 或 Simple Open EtherCAT Master)是一个开源的、用于EtherCAT通信协议的软件库。EtherCAT(Ethernet for Control Automation Technology)是一种实时以太网通信协议,广泛应用于自动化和机器人技术中,以其高速和低延迟特性而受到青睐。SOEM库允许开发者在他们的应用程序中实现EtherCAT主站功能,从而控制和驱动EtherCAT从站设备。

以下是SOEM库的一些关键特点和优势:

  • 开源和免费:SOEM是开源的,使用LGPLv2.1授权,可以自由使用、修改和分发。
  • 跨平台支持:SOEM支持多种操作系统,包括Linux、FreeRTOS、VxWorks、QNX等,提供跨平台的灵活性。
  • 实时性能:SOEM直接与硬件交互,确保了低延迟和高数据吞吐量,满足实时性要求。
  • 易于集成:SOEM使用标准的设备驱动模型,简化了在现有系统中添加EtherCAT功能的过程。
  • 文档完善:提供详细的API文档和示例代码,帮助开发者快速上手。
  • 社区支持:作为一个开源项目,SOEM拥有活跃的社区支持,不断有更新和问题解决方案。

SOEM库适用于工业自动化、实验室研究、开源硬件项目和教育用途等多种场景。它为用户应用程序提供了发送和接收EtherCAT帧的方法,支持读写过程数据、保持本地IO数据与全局IO映射同步、检测和管理系统错误等功能。

开发者可以通过研究SOEM的源码来深入理解EtherCAT主站与从站之间的交互方式,这不仅有助于学习EtherCAT协议,还能在此基础上进行定制和优化,以满足特定的应用需求。SOEM项目在GitHub上维护,提供了完整的示例应用和配置文件,方便开发者获取和使用。

二. 安装WinPcap

WinPcap库

  1. 下载并安装WinPcap运行库:官网:http://www.winpcap.org/install/default.htm
    在这里插入图片描述
  2. 运行下载好的exe文件,点击下一步
    在这里插入图片描述
  3. 点击同意
    在这里插入图片描述
  4. 点击安装
    在这里插入图片描述
  5. 点击完成
    在这里插入图片描述

三. SOEM(1.4)库安装

(1) 编译32位库

  1. 官网下载SOEM源文件
    在这里插入图片描述

  2. 运行VS2019的命令行
    在这里插入图片描述

  3. 进入下载好的SOEM源文件
    在这里插入图片描述

  4. 在源文件目录下创建build文件夹,并进入

    mkdir build
    cd build
    

    在这里插入图片描述

  5. 运行以下命令,编译源文件

    cmake .. -G "NMake Makefiles"
    nmake
    

    在这里插入图片描述

  6. 运行以下命令生成调用库

    namke install
    

    在这里插入图片描述

(2) 编译64位库

  1. 官网下载SOEM源文件
    在这里插入图片描述

  2. 运行VS2019的命令行
    在这里插入图片描述

  3. 进入下载好的SOEM源文件
    在这里插入图片描述

  4. 在源文件目录下创建build文件夹,并进入

    mkdir build
    
  5. 运行以下命令,编译源文件

    cmake .. -G "Visual Studio 16 2019" -S . -B build
    

    在这里插入图片描述

  6. 进入build文件夹,用vs2019打开soem.sln项目

    namke install
    

    在这里插入图片描述

  7. 点击生成,点击配置管理器
    在这里插入图片描述

  8. 选择要生成的内容
    在这里插入图片描述

  9. 点击生成解决方案
    在这里插入图片描述

  10. 没有报错则完成,可以在debug文件夹中找到生成的库文件
    在这里插入图片描述
    在这里插入图片描述

四. 运行SOEM示例代码

  1. 编译好的SOEM文件夹中有例程(simple_ng)
    在这里插入图片描述

  2. cmd中运行simple_ng,可以看到电脑带的所有的网卡信息
    在这里插入图片描述

  3. 选择已经接入EtherCAT从站的网口,复制网口信息(\Device\NPF_{51D73200-BC7C-4562-8918-04FA9C959372}),cmd中运行如下代码

    simple_ng \Device\NPF_{51D73200-BC7C-4562-8918-04FA9C959372}
    

    在这里插入图片描述

  4. 通过-map指令,可以查看从站的I/O配置

    slaveinfo \Device\NPF_{A837AD34-3738-42FF-8E0B-F5B0BE69ABD6} -map
    

    在这里插入图片描述

五. WIN10下利用QT构建SOEM开发环境

  1. 在QT中创建一个新c++项目,CMakeList.txt文件如下

    cmake_minimum_required(VERSION 3.5)
    
    project(SOEMTest LANGUAGES CXX)
    
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    
    set(SOEM_DIR "C:\\Users\\10001540\\Downloads\\SOEM-master")
    include_directories(${SOEM_DIR}\\install\\include\\soem\\ ${SOEM_DIR}\\oshw\\win32\\wpcap\\Include\\)
    link_directories(C:\\Users\\10001540\\Downloads\\SOEM-master\\build\\Debug\\ ${SOEM_DIR}\\oshw\\win32\\wpcap\\Lib\\x64\\)
    
    add_executable(SOEMTest main.cpp)
    
    target_link_libraries(SOEMTest PUBLIC soem.lib Packet.lib wpcap.lib Ws2_32.lib Winmm.lib)
    
    install(TARGETS SOEMTest
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
    
    message(STATUS "The system is: ${CMAKE_SYSTEM_NAME}")
    
  2. main函数中,代码如下:

    #include <iostream>
    #include "ethercat.h"
    
    using namespace std;
    
    char IOmap[4096];
    ec_ODlistt ODlist;
    ec_OElistt OElist;
    boolean printSDO = FALSE;
    boolean printMAP = FALSE;
    char usdo[128];
    char hstr[1024];
    
    char* dtype2string(uint16 dtype)
    {
        switch(dtype)
        {
            case ECT_BOOLEAN:
                sprintf(hstr, "BOOLEAN");
                break;
            case ECT_INTEGER8:
                sprintf(hstr, "INTEGER8");
                break;
            case ECT_INTEGER16:
                sprintf(hstr, "INTEGER16");
                break;
            case ECT_INTEGER32:
                sprintf(hstr, "INTEGER32");
                break;
            case ECT_INTEGER24:
                sprintf(hstr, "INTEGER24");
                break;
            case ECT_INTEGER64:
                sprintf(hstr, "INTEGER64");
                break;
            case ECT_UNSIGNED8:
                sprintf(hstr, "UNSIGNED8");
                break;
            case ECT_UNSIGNED16:
                sprintf(hstr, "UNSIGNED16");
                break;
            case ECT_UNSIGNED32:
                sprintf(hstr, "UNSIGNED32");
                break;
            case ECT_UNSIGNED24:
                sprintf(hstr, "UNSIGNED24");
                break;
            case ECT_UNSIGNED64:
                sprintf(hstr, "UNSIGNED64");
                break;
            case ECT_REAL32:
                sprintf(hstr, "REAL32");
                break;
            case ECT_REAL64:
                sprintf(hstr, "REAL64");
                break;
            case ECT_BIT1:
                sprintf(hstr, "BIT1");
                break;
            case ECT_BIT2:
                sprintf(hstr, "BIT2");
                break;
            case ECT_BIT3:
                sprintf(hstr, "BIT3");
                break;
            case ECT_BIT4:
                sprintf(hstr, "BIT4");
                break;
            case ECT_BIT5:
                sprintf(hstr, "BIT5");
                break;
            case ECT_BIT6:
                sprintf(hstr, "BIT6");
                break;
            case ECT_BIT7:
                sprintf(hstr, "BIT7");
                break;
            case ECT_BIT8:
                sprintf(hstr, "BIT8");
                break;
            case ECT_VISIBLE_STRING:
                sprintf(hstr, "VISIBLE_STRING");
                break;
            case ECT_OCTET_STRING:
                sprintf(hstr, "OCTET_STRING");
                break;
            default:
                sprintf(hstr, "Type 0x%4.4X", dtype);
        }
        return hstr;
    }
    
    char* SDO2string(uint16 slave, uint16 index, uint8 subidx, uint16 dtype)
    {
       int l = sizeof(usdo) - 1, i;
       uint8 *u8;
       int8 *i8;
       uint16 *u16;
       int16 *i16;
       uint32 *u32;
       int32 *i32;
       uint64 *u64;
       int64 *i64;
       float *sr;
       double *dr;
       char es[32];
    
       memset(&usdo, 0, 128);
       ec_SDOread(slave, index, subidx, FALSE, &l, &usdo, EC_TIMEOUTRXM);
       if (EcatError)
       {
          return ec_elist2string();
       }
       else
       {
          switch(dtype)
          {
             case ECT_BOOLEAN:
                u8 = (uint8*) &usdo[0];
                if (*u8) sprintf(hstr, "TRUE");
                 else sprintf(hstr, "FALSE");
                break;
             case ECT_INTEGER8:
                i8 = (int8*) &usdo[0];
                sprintf(hstr, "0x%2.2x %d", *i8, *i8);
                break;
             case ECT_INTEGER16:
                i16 = (int16*) &usdo[0];
                sprintf(hstr, "0x%4.4x %d", *i16, *i16);
                break;
             case ECT_INTEGER32:
             case ECT_INTEGER24:
                i32 = (int32*) &usdo[0];
                sprintf(hstr, "0x%8.8x %d", *i32, *i32);
                break;
             case ECT_INTEGER64:
                i64 = (int64*) &usdo[0];
                //sprintf(hstr, "0x%16.16"PRIx64" %"PRId64, *i64, *i64);
                break;
             case ECT_UNSIGNED8:
                u8 = (uint8*) &usdo[0];
                sprintf(hstr, "0x%2.2x %u", *u8, *u8);
                break;
             case ECT_UNSIGNED16:
                u16 = (uint16*) &usdo[0];
                sprintf(hstr, "0x%4.4x %u", *u16, *u16);
                break;
             case ECT_UNSIGNED32:
             case ECT_UNSIGNED24:
                u32 = (uint32*) &usdo[0];
                sprintf(hstr, "0x%8.8x %u", *u32, *u32);
                break;
             case ECT_UNSIGNED64:
                u64 = (uint64*) &usdo[0];
                //sprintf(hstr, "0x%16.16"PRIx64" %"PRIu64, *u64, *u64);
                break;
             case ECT_REAL32:
                sr = (float*) &usdo[0];
                sprintf(hstr, "%f", *sr);
                break;
             case ECT_REAL64:
                dr = (double*) &usdo[0];
                sprintf(hstr, "%f", *dr);
                break;
             case ECT_BIT1:
             case ECT_BIT2:
             case ECT_BIT3:
             case ECT_BIT4:
             case ECT_BIT5:
             case ECT_BIT6:
             case ECT_BIT7:
             case ECT_BIT8:
                u8 = (uint8*) &usdo[0];
                sprintf(hstr, "0x%x", *u8);
                break;
             case ECT_VISIBLE_STRING:
                strcpy(hstr, usdo);
                break;
             case ECT_OCTET_STRING:
                hstr[0] = 0x00;
                for (i = 0 ; i < l ; i++)
                {
                   sprintf(es, "0x%2.2x ", usdo[i]);
                   strcat( hstr, es);
                }
                break;
             default:
                sprintf(hstr, "Unknown type");
          }
          return hstr;
       }
    }
    
    /** Read PDO assign structure */
    int si_PDOassign(uint16 slave, uint16 PDOassign, int mapoffset, int bitoffset)
    {
        uint16 idxloop, nidx, subidxloop, rdat, idx, subidx;
        uint8 subcnt;
        int wkc, bsize = 0, rdl;
        int32 rdat2;
        uint8 bitlen, obj_subidx;
        uint16 obj_idx;
        int abs_offset, abs_bit;
    
        rdl = sizeof(rdat); rdat = 0;
        /* read PDO assign subindex 0 ( = number of PDO's) */
        wkc = ec_SDOread(slave, PDOassign, 0x00, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
        rdat = etohs(rdat);
        /* positive result from slave ? */
        if ((wkc > 0) && (rdat > 0))
        {
            /* number of available sub indexes */
            nidx = rdat;
            bsize = 0;
            /* read all PDO's */
            for (idxloop = 1; idxloop <= nidx; idxloop++)
            {
                rdl = sizeof(rdat); rdat = 0;
                /* read PDO assign */
                wkc = ec_SDOread(slave, PDOassign, (uint8)idxloop, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
                /* result is index of PDO */
                idx = etohl(rdat);
                if (idx > 0)
                {
                    rdl = sizeof(subcnt); subcnt = 0;
                    /* read number of subindexes of PDO */
                    wkc = ec_SDOread(slave,idx, 0x00, FALSE, &rdl, &subcnt, EC_TIMEOUTRXM);
                    subidx = subcnt;
                    /* for each subindex */
                    for (subidxloop = 1; subidxloop <= subidx; subidxloop++)
                    {
                        rdl = sizeof(rdat2); rdat2 = 0;
                        /* read SDO that is mapped in PDO */
                        wkc = ec_SDOread(slave, idx, (uint8)subidxloop, FALSE, &rdl, &rdat2, EC_TIMEOUTRXM);
                        rdat2 = etohl(rdat2);
                        /* extract bitlength of SDO */
                        bitlen = LO_BYTE(rdat2);
                        bsize += bitlen;
                        obj_idx = (uint16)(rdat2 >> 16);
                        obj_subidx = (uint8)((rdat2 >> 8) & 0x000000ff);
                        abs_offset = mapoffset + (bitoffset / 8);
                        abs_bit = bitoffset % 8;
                        ODlist.Slave = slave;
                        ODlist.Index[0] = obj_idx;
                        OElist.Entries = 0;
                        wkc = 0;
                        /* read object entry from dictionary if not a filler (0x0000:0x00) */
                        if(obj_idx || obj_subidx)
                            wkc = ec_readOEsingle(0, obj_subidx, &ODlist, &OElist);
                        printf("  [0x%4.4X.%1d] 0x%4.4X:0x%2.2X 0x%2.2X", abs_offset, abs_bit, obj_idx, obj_subidx, bitlen);
                        if((wkc > 0) && OElist.Entries)
                        {
                            printf(" %-12s %s\n", dtype2string(OElist.DataType[obj_subidx]), OElist.Name[obj_subidx]);
                        }
                        else
                            printf("\n");
                        bitoffset += bitlen;
                    };
                };
            };
        };
        /* return total found bitlength (PDO) */
        return bsize;
    }
    
    int si_map_sdo(int slave)
    {
        int wkc, rdl;
        int retVal = 0;
        uint8 nSM, iSM, tSM;
        int Tsize, outputs_bo, inputs_bo;
        uint8 SMt_bug_add;
    
        printf("PDO mapping according to CoE :\n");
        SMt_bug_add = 0;
        outputs_bo = 0;
        inputs_bo = 0;
        rdl = sizeof(nSM); nSM = 0;
        /* read SyncManager Communication Type object count */
        wkc = ec_SDOread(slave, ECT_SDO_SMCOMMTYPE, 0x00, FALSE, &rdl, &nSM, EC_TIMEOUTRXM);
        /* positive result from slave ? */
        if ((wkc > 0) && (nSM > 2))
        {
            /* make nSM equal to number of defined SM */
            nSM--;
            /* limit to maximum number of SM defined, if true the slave can't be configured */
            if (nSM > EC_MAXSM)
                nSM = EC_MAXSM;
            /* iterate for every SM type defined */
            for (iSM = 2 ; iSM <= nSM ; iSM++)
            {
                rdl = sizeof(tSM); tSM = 0;
                /* read SyncManager Communication Type */
                wkc = ec_SDOread(slave, ECT_SDO_SMCOMMTYPE, iSM + 1, FALSE, &rdl, &tSM, EC_TIMEOUTRXM);
                if (wkc > 0)
                {
                    if((iSM == 2) && (tSM == 2)) // SM2 has type 2 == mailbox out, this is a bug in the slave!
                    {
                        SMt_bug_add = 1; // try to correct, this works if the types are 0 1 2 3 and should be 1 2 3 4
                        printf("Activated SM type workaround, possible incorrect mapping.\n");
                    }
                    if(tSM)
                        tSM += SMt_bug_add; // only add if SMt > 0
    
                    if (tSM == 3) // outputs
                    {
                        /* read the assign RXPDO */
                        printf("  SM%1d outputs\n     addr b   index: sub bitl data_type    name\n", iSM);
                        Tsize = si_PDOassign(slave, ECT_SDO_PDOASSIGN + iSM, (int)(ec_slave[slave].outputs - (uint8 *)&IOmap[0]), outputs_bo );
                        outputs_bo += Tsize;
                    }
                    if (tSM == 4) // inputs
                    {
                        /* read the assign TXPDO */
                        printf("  SM%1d inputs\n     addr b   index: sub bitl data_type    name\n", iSM);
                        Tsize = si_PDOassign(slave, ECT_SDO_PDOASSIGN + iSM, (int)(ec_slave[slave].inputs - (uint8 *)&IOmap[0]), inputs_bo );
                        inputs_bo += Tsize;
                    }
                }
            }
        }
    
        /* found some I/O bits ? */
        if ((outputs_bo > 0) || (inputs_bo > 0))
            retVal = 1;
        return retVal;
    }
    
    int si_siiPDO(uint16 slave, uint8 t, int mapoffset, int bitoffset)
    {
        uint16 a , w, c, e, er, Size;
        uint8 eectl;
        uint16 obj_idx;
        uint8 obj_subidx;
        uint8 obj_name;
        uint8 obj_datatype;
        uint8 bitlen;
        int totalsize;
        ec_eepromPDOt eepPDO;
        ec_eepromPDOt *PDO;
        int abs_offset, abs_bit;
        char str_name[EC_MAXNAME + 1];
    
        eectl = ec_slave[slave].eep_pdi;
        Size = 0;
        totalsize = 0;
        PDO = &eepPDO;
        PDO->nPDO = 0;
        PDO->Length = 0;
        PDO->Index[1] = 0;
        for (c = 0 ; c < EC_MAXSM ; c++) PDO->SMbitsize[c] = 0;
        if (t > 1)
            t = 1;
        PDO->Startpos = ec_siifind(slave, ECT_SII_PDO + t);
        if (PDO->Startpos > 0)
        {
            a = PDO->Startpos;
            w = ec_siigetbyte(slave, a++);
            w += (ec_siigetbyte(slave, a++) << 8);
            PDO->Length = w;
            c = 1;
            /* traverse through all PDOs */
            do
            {
                PDO->nPDO++;
                PDO->Index[PDO->nPDO] = ec_siigetbyte(slave, a++);
                PDO->Index[PDO->nPDO] += (ec_siigetbyte(slave, a++) << 8);
                PDO->BitSize[PDO->nPDO] = 0;
                c++;
                /* number of entries in PDO */
                e = ec_siigetbyte(slave, a++);
                PDO->SyncM[PDO->nPDO] = ec_siigetbyte(slave, a++);
                a++;
                obj_name = ec_siigetbyte(slave, a++);
                a += 2;
                c += 2;
                if (PDO->SyncM[PDO->nPDO] < EC_MAXSM) /* active and in range SM? */
                {
                    str_name[0] = 0;
                    if(obj_name)
                      ec_siistring(str_name, slave, obj_name);
                    if (t)
                      printf("  SM%1d RXPDO 0x%4.4X %s\n", PDO->SyncM[PDO->nPDO], PDO->Index[PDO->nPDO], str_name);
                    else
                      printf("  SM%1d TXPDO 0x%4.4X %s\n", PDO->SyncM[PDO->nPDO], PDO->Index[PDO->nPDO], str_name);
                    printf("     addr b   index: sub bitl data_type    name\n");
                    /* read all entries defined in PDO */
                    for (er = 1; er <= e; er++)
                    {
                        c += 4;
                        obj_idx = ec_siigetbyte(slave, a++);
                        obj_idx += (ec_siigetbyte(slave, a++) << 8);
                        obj_subidx = ec_siigetbyte(slave, a++);
                        obj_name = ec_siigetbyte(slave, a++);
                        obj_datatype = ec_siigetbyte(slave, a++);
                        bitlen = ec_siigetbyte(slave, a++);
                        abs_offset = mapoffset + (bitoffset / 8);
                        abs_bit = bitoffset % 8;
    
                        PDO->BitSize[PDO->nPDO] += bitlen;
                        a += 2;
    
                        str_name[0] = 0;
                        if(obj_name)
                          ec_siistring(str_name, slave, obj_name);
    
                        printf("  [0x%4.4X.%1d] 0x%4.4X:0x%2.2X 0x%2.2X", abs_offset, abs_bit, obj_idx, obj_subidx, bitlen);
                        printf(" %-12s %s\n", dtype2string(obj_datatype), str_name);
                        bitoffset += bitlen;
                        totalsize += bitlen;
                    }
                    PDO->SMbitsize[ PDO->SyncM[PDO->nPDO] ] += PDO->BitSize[PDO->nPDO];
                    Size += PDO->BitSize[PDO->nPDO];
                    c++;
                }
                else /* PDO deactivated because SM is 0xff or > EC_MAXSM */
                {
                    c += 4 * e;
                    a += 8 * e;
                    c++;
                }
                if (PDO->nPDO >= (EC_MAXEEPDO - 1)) c = PDO->Length; /* limit number of PDO entries in buffer */
            }
            while (c < PDO->Length);
        }
        if (eectl) ec_eeprom2pdi(slave); /* if eeprom control was previously pdi then restore */
        return totalsize;
    }
    
    int si_map_sii(int slave)
    {
        int retVal = 0;
        int Tsize, outputs_bo, inputs_bo;
    
        printf("PDO mapping according to SII :\n");
    
        outputs_bo = 0;
        inputs_bo = 0;
        /* read the assign RXPDOs */
        Tsize = si_siiPDO(slave, 1, (int)(ec_slave[slave].outputs - (uint8*)&IOmap), outputs_bo );
        outputs_bo += Tsize;
        /* read the assign TXPDOs */
        Tsize = si_siiPDO(slave, 0, (int)(ec_slave[slave].inputs - (uint8*)&IOmap), inputs_bo );
        inputs_bo += Tsize;
        /* found some I/O bits ? */
        if ((outputs_bo > 0) || (inputs_bo > 0))
            retVal = 1;
        return retVal;
    }
    
    void si_sdo(int cnt)
    {
        int i, j;
    
        ODlist.Entries = 0;
        memset(&ODlist, 0, sizeof(ODlist));
        if( ec_readODlist(cnt, &ODlist))
        {
            printf(" CoE Object Description found, %d entries.\n",ODlist.Entries);
            for( i = 0 ; i < ODlist.Entries ; i++)
            {
                ec_readODdescription(i, &ODlist);
                while(EcatError) printf("%s", ec_elist2string());
                printf(" Index: %4.4x Datatype: %4.4x Objectcode: %2.2x Name: %s\n",
                    ODlist.Index[i], ODlist.DataType[i], ODlist.ObjectCode[i], ODlist.Name[i]);
                memset(&OElist, 0, sizeof(OElist));
                ec_readOE(i, &ODlist, &OElist);
                while(EcatError) printf("%s", ec_elist2string());
                for( j = 0 ; j < ODlist.MaxSub[i]+1 ; j++)
                {
                    if ((OElist.DataType[j] > 0) && (OElist.BitLength[j] > 0))
                    {
                        printf("  Sub: %2.2x Datatype: %4.4x Bitlength: %4.4x Obj.access: %4.4x Name: %s\n",
                            j, OElist.DataType[j], OElist.BitLength[j], OElist.ObjAccess[j], OElist.Name[j]);
                        if ((OElist.ObjAccess[j] & 0x0007))
                        {
                            printf("          Value :%s\n", SDO2string(cnt, ODlist.Index[i], j, OElist.DataType[j]));
                        }
                    }
                }
            }
        }
        else
        {
            while(EcatError) printf("%s", ec_elist2string());
        }
    }
    
    void slaveinfo(char *ifname)
    {
        int cnt, i, j, nSM;
        uint16 ssigen;
        int expectedWKC;
        ecx_contextt* contex;
    
        printf("Starting slaveinfo\n");
    
        if(ec_init(ifname)) // 初始化SOEM库,绑定soket到网口
        {
            printf("ec_init on %s succeeded.\n",ifname);
            if(ec_config(FALSE, &IOmap) > 0) // 枚举所有从站的信息,并配置从站,保存到IOmap中
            {
                ec_configdc();
                while(EcatError)
                {
                    cout<< ec_elist2string() << endl;
                }
                printf("%d slaves found and configured.\n",ec_slavecount);
                expectedWKC = (ec_group[0].outputsWKC * 2) + ec_group[0].inputsWKC;
                printf("Calculated workcounter %d\n", expectedWKC);
                ec_statecheck(0, EC_STATE_SAFE_OP,  EC_TIMEOUTSTATE * 3);
                if (ec_slave[0].state != EC_STATE_SAFE_OP )
                {
                    printf("Not all slaves reached safe operational state.\n");
                    ec_readstate();
                    for(i = 1; i<=ec_slavecount ; i++)
                    {
                       if(ec_slave[i].state != EC_STATE_SAFE_OP)
                       {
                           printf("Slave %d State=%2x StatusCode=%4x : %s\n",
                                                i, ec_slave[i].state, ec_slave[i].ALstatuscode, ec_ALstatuscode2string(ec_slave[i].ALstatuscode));
                       }
                    }
                }
    
                ec_readstate();
                for( cnt = 1 ; cnt <= ec_slavecount ; cnt++)
                {
                   printf("\nSlave:%d\n Name:%s\n Output size: %dbits\n Input size: %dbits\n State: %d\n Delay: %d[ns]\n Has DC: %d\n",
                         cnt, ec_slave[cnt].name, ec_slave[cnt].Obits, ec_slave[cnt].Ibits,
                         ec_slave[cnt].state, ec_slave[cnt].pdelay, ec_slave[cnt].hasdc);
                   if (ec_slave[cnt].hasdc) printf(" DCParentport:%d\n", ec_slave[cnt].parentport);
                   printf(" Activeports:%d.%d.%d.%d\n", (ec_slave[cnt].activeports & 0x01) > 0 ,
                                                (ec_slave[cnt].activeports & 0x02) > 0 ,
                                                (ec_slave[cnt].activeports & 0x04) > 0 ,
                                                (ec_slave[cnt].activeports & 0x08) > 0 );
                   printf(" Configured address: %4.4x\n", ec_slave[cnt].configadr);
                   printf(" Man: %8.8x ID: %8.8x Rev: %8.8x\n", (int)ec_slave[cnt].eep_man, (int)ec_slave[cnt].eep_id, (int)ec_slave[cnt].eep_rev);
                   for(nSM = 0 ; nSM < EC_MAXSM ; nSM++)
                   {
                      if(ec_slave[cnt].SM[nSM].StartAddr > 0)
                         printf(" SM%1d A:%4.4x L:%4d F:%8.8x Type:%d\n",nSM, ec_slave[cnt].SM[nSM].StartAddr, ec_slave[cnt].SM[nSM].SMlength,
                                (int)ec_slave[cnt].SM[nSM].SMflags, ec_slave[cnt].SMtype[nSM]);
                   }
                   for(j = 0 ; j < ec_slave[cnt].FMMUunused ; j++)
                   {
                      printf(" FMMU%1d Ls:%8.8x Ll:%4d Lsb:%d Leb:%d Ps:%4.4x Psb:%d Ty:%2.2x Act:%2.2x\n", j,
                              (int)ec_slave[cnt].FMMU[j].LogStart, ec_slave[cnt].FMMU[j].LogLength, ec_slave[cnt].FMMU[j].LogStartbit,
                              ec_slave[cnt].FMMU[j].LogEndbit, ec_slave[cnt].FMMU[j].PhysStart, ec_slave[cnt].FMMU[j].PhysStartBit,
                              ec_slave[cnt].FMMU[j].FMMUtype, ec_slave[cnt].FMMU[j].FMMUactive);
                   }
                   printf(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n",
                            ec_slave[cnt].FMMU0func, ec_slave[cnt].FMMU1func, ec_slave[cnt].FMMU2func, ec_slave[cnt].FMMU3func);
                   printf(" MBX length wr: %d rd: %d MBX protocols : %2.2x\n", ec_slave[cnt].mbx_l, ec_slave[cnt].mbx_rl, ec_slave[cnt].mbx_proto);
                   ssigen = ec_siifind(cnt, ECT_SII_GENERAL);
                   /* SII general section */
                   if (ssigen)
                   {
                      ec_slave[cnt].CoEdetails = ec_siigetbyte(cnt, ssigen + 0x07);
                      ec_slave[cnt].FoEdetails = ec_siigetbyte(cnt, ssigen + 0x08);
                      ec_slave[cnt].EoEdetails = ec_siigetbyte(cnt, ssigen + 0x09);
                      ec_slave[cnt].SoEdetails = ec_siigetbyte(cnt, ssigen + 0x0a);
                      if((ec_siigetbyte(cnt, ssigen + 0x0d) & 0x02) > 0)
                      {
                         ec_slave[cnt].blockLRW = 1;
                         ec_slave[0].blockLRW++;
                      }
                      ec_slave[cnt].Ebuscurrent = ec_siigetbyte(cnt, ssigen + 0x0e);
                      ec_slave[cnt].Ebuscurrent += ec_siigetbyte(cnt, ssigen + 0x0f) << 8;
                      ec_slave[0].Ebuscurrent += ec_slave[cnt].Ebuscurrent;
                   }
                   printf(" CoE details: %2.2x FoE details: %2.2x EoE details: %2.2x SoE details: %2.2x\n",
                           ec_slave[cnt].CoEdetails, ec_slave[cnt].FoEdetails, ec_slave[cnt].EoEdetails, ec_slave[cnt].SoEdetails);
                   printf(" Ebus current: %d[mA]\n only LRD/LWR:%d\n",
                           ec_slave[cnt].Ebuscurrent, ec_slave[cnt].blockLRW);
                   if ((ec_slave[cnt].mbx_proto & ECT_MBXPROT_COE) && printSDO)
                   {
                           si_sdo(cnt);
                   }
    
                   if (ec_slave[cnt].mbx_proto & ECT_MBXPROT_COE)
                       si_map_sdo(cnt);
                   else
                       si_map_sii(cnt);
    
                }
    
            }
        }
        else
        {
        }
    }
    
    int main()
    {
        char* ifbuf = "\\Device\\NPF_{A837AD34-3738-42FF-8E0B-F5B0BE69ABD6}"; // 网口设备号
        printf("SOEM (Simple Open EtherCAT Master)\nSlaveinfo\n");
        slaveinfo(ifbuf);
        return 0;
    }
    

    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/713856.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【OrangePiKunPengPro】 linux下编译、安装Boa服务器

OrangePiKunPengPro | linux下编译、安装Boa服务器 时间&#xff1a;2024年6月7日21:41:01 1.参考 1.boa- CSDN搜索 2.Boa服务器 | Ubuntu下编译、安装Boa_ubuntu安装boa-CSDN博客 3.i.MX6ULL—ElfBoard Elf1板卡 移植boa服务器的方法 (qq.com) 2.实践 2-1下载代码 [fly752fa…

python将数据保存到文件的多种实现方式

&#x1f308;所属专栏&#xff1a;【python】✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的…

EasyRecovery2024数据恢复神器#电脑必备良品

EasyRecovery数据恢复软件&#xff0c;让你的数据重见天日&#xff01; 大家好&#xff01;今天我要给大家种草一个非常实用的软件——EasyRecovery数据恢复软件&#xff01;你是不是也曾经遇到过不小心删除了重要的文件&#xff0c;或者电脑突然崩溃导致数据丢失的尴尬情况呢&…

手机照片免费数据恢复软件EasyRecovery2024免费版下载

大家好&#xff01;今天我要给大家推荐一款非常棒的软件——EasyRecovery。相信大家都知道&#xff0c;电脑中的重要文件一旦丢失&#xff0c;对我们的工作和学习都会产生很大的影响。 而EasyRecovery软件就是专门解决这个问题的利器&#xff01;它能够帮助我们快速、有效地恢…

第三篇—基于黑白样本的webshell检测

本篇为webshell检测的第三篇&#xff0c;主要讲的是基于黑白样本的webshell预测&#xff0c;从样本收集、特征提取、模型训练&#xff0c;最后模型评估这四步&#xff0c;实现一个简单的黑白样本预测模型。   若有误之处&#xff0c;望大佬们指出 Ⅰ 基本实现步骤 样本收集&…

Unity中的伽马(Gamma)空间和线性(Linear)空间

伽马空间定义&#xff1a;通常用于描述图像在存储和显示时的颜色空间。在伽马空间中&#xff0c;图像的保存通常经过伽马转换&#xff0c;使图片看起来更亮。 gamma并不是色彩空间&#xff0c;它其实只是如何对色彩进行采样的一种方式 为什么需要Gamma&#xff1a; 在游戏业…

53. QT插件开发--插件(动态库so)的调用与加载

1. 说明 在使用QT进行插件库的开发之后,还需要将这个插件库程序生成的so动态链接库加载到主程序框架中进行使用,才能达到主程序的模块化开发的效果。在前一篇文章插件创建中介绍了如何在QT中开发插件库,并提供外部接口调用。本篇博客的主要作用是模拟在主程序框架中加载动态…

诊断丢帧:发送端连续帧发送过快,导致接收端丢帧

项目场景: 在项目开发过程中,对于报文的接收/发送,一般来说,通信量大,选择Polling(轮询)处理模式;通信量小,选择Interrupt(中断)处理模式。具体选择没有优劣之分。结合项目的实际情况,选择适合项目的方式就好。小编将分享一个Polling模式下出现的丢帧现象。 1576…

Docker镜像技术剖析

目录 1、概述1.1 什么是镜像&#xff1f;1.2 联合文件系统UnionFS1.3 bootfs和rootfs1.4 镜像结构1.5 镜像的主要技术特点1.5.1 镜像分层技术1.5.2 写时复制(copy-on-write)策略1.5.3 内容寻址存储(content-addressable storage)机制1.5.4 联合挂载(union mount)技术 2.机制原理…

C# WPF入门学习主线篇(十五)—— DockPanel布局容器

C# WPF入门学习主线篇&#xff08;十五&#xff09;—— DockPanel布局容器 欢迎来到C# WPF入门学习系列的第十五篇。在前几篇文章中&#xff0c;我们探讨了 Canvas、StackPanel 和 WrapPanel 布局容器及其使用方法。本篇博客将介绍另一种强大且常用的布局容器——DockPanel。…

打造成功的人力RPO项目:赢得市场赚取利润

人力资源外包(RPO)项目是当今企业在招聘和人才管理方面越来越倾向的选择。想要通过人力RPO项目赚钱&#xff0c;以下是一些关键的策略和步骤&#xff0c;帮助您进入这个市场并取得成功。 1. 建立专业的人力RPO服务 首先&#xff0c;要想在人力RPO项目中赚钱&#xff0c;必须建立…

HCIA11 网络安全之本地 AAA 配置实验

AAA 提供 Authentication&#xff08;认证&#xff09;、Authorization&#xff08;授权&#xff09;和 Accounting&#xff08;计费&#xff09;三种安全功能。 • 认证&#xff1a;验证用户是否可以获得网络访问权。 • 授权&#xff1a;授权用户可以使用哪些服务。 •…

AOP切面加自定义注解,实现日志记录

AOP切面加自定义注解&#xff0c;实现日志记录 一、AOP二、准备工作三、添加AOP&#xff0c;把日志保存到数据库 一、AOP 在软件业&#xff0c;AOP为Aspect Oriented Programming的缩写&#xff0c;意为&#xff1a;面向切面编程&#xff0c;通过预编译方式和运行期动态代理实…

debug调试高级功能 断点、布局 及Android Studio常用快捷按键使用详情

文章目录 debug断点篇&#xff1a;打临时断点&#xff08;只用一次&#xff09;&#xff1a;alt断点条件断点&#xff1a;在断点上&#xff0c;点击右键&#xff0c;在Condition那里&#xff0c;设置我们需要的值&#xff0c;循环就会自动停到我们设置的那个值那里依赖断点&…

Markdown如何分页操作

Markdown导出分页操作 在平时的文档导出过程中Markdown过程中会出现因为不能分页导致的排版问题。 排版问题在将Markdown文档导出为PDF或其他格式时尤为明显。当文档内容超过一页时&#xff0c;无法自动调整页面布局&#xff0c;导致内容不连续&#xff0c;甚至导致图片或表格…

pve8群晖rr方式安装(编译失败检查网络或磁盘空间error 23:200问题解决)

PVE 篇二&#xff1a;2024年PVE8最新安装使用指南|安装黑群晖&#xff5c;img格式镜像安装_NAS存储_什么值得买 (smzdm.com) 黑群晖 篇五&#xff1a;2023黑群晖最新安装方式|RR新手也可轻松上手_NAS存储_什么值得买 (smzdm.com) 编译引导提示&#xff1a;检查网络或磁盘空间er…

qt dll编写和调用

dll编写 新建项目 头文件 #ifndef LIB1_H #define LIB1_H#include "lib1_global.h"class LIB1_EXPORT Lib1 { public:Lib1(); };//要导出的函数&#xff0c;使用extern "C"&#xff0c;否则名称改变将找不到函数extern "C" LIB1_EXPORT int ad…

程序员的核心职业素养:专业、沟通与持续学习

✨作者主页&#xff1a; Mr.Zwq✔️个人简介&#xff1a;一个正在努力学技术的Python领域创作者&#xff0c;擅长爬虫&#xff0c;逆向&#xff0c;全栈方向&#xff0c;专注基础和实战分享&#xff0c;欢迎咨询&#xff01; 您的点赞、关注、收藏、评论&#xff0c;是对我最大…

单片机第五季-第八课:STM32CubeMx和FreeRTOS

1&#xff0c;FreeRTOS背景介绍 RTOS简介&#xff1a; 实时操作系统&#xff0c;本用于追求实时性的嵌入式系统&#xff0c;典型&#xff1a;ucos/uclinux/vxworks&#xff1b; 特点&#xff1a;中断响应快、一般可嵌套中断、使用实地址、多任务&#xff1b; &#xff08;实…

中国历年人均发电量统计报告

数据来源于国家统计局&#xff0c;为1978年到2020年我国每年的人均发电量数据。 2020年&#xff0c;我国人均发电量为5512.76千瓦时&#xff0c;比上年增长3.4%。 数据统计单位为&#xff1a;千瓦时 我国人均发电量有多少&#xff1f; 2020年&#xff0c;我国人均发电量为5512…