SOEM2.0编译与Qt调用

文章目录

  • [一. SOEM2.0编译](#一. SOEM2.0编译)
  • [二. Qt调用](#二. Qt调用)

SOEM官方编译教程:https://docs.rt-labs.com/soem/tutorials/building.html

一. SOEM2.0编译

环境:vs2019+CMake3.26.0

  1. 官网下载源代码

    GitHub - OpenEtherCATsociety/SOEM: Simple Open Source EtherCAT Master · GitHub

  2. CMD进入源代码目录

  3. CMD运行以下命令

    1. 设置编译器和安装位置
Bash 复制代码
cmake --preset default -G "Visual Studio 16 2019" -DCMAKE_INSTALL_PREFIX=C:\Users\nflg\Downloads\SOEM\install
复制代码
2. 编译与安装
Bash 复制代码
cmake --build --preset default --target install
  1. 测试示例代码
    1. 使用VS2019打开项目

    2. 选择一个项目,设置为启动项

    3. 运行项目,查看输出窗口

    4. 设置运行参数,重新运行程序,可以看到设备信息



二. Qt调用

  1. cmakeList.txt
Bash 复制代码
cmake_minimum_required(VERSION 3.16)

project(SOEMTest LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# winpcap库目录
set(WINPCAP_DIR "D:\\Program Files\\wpcap\\")
include_directories(${WINPCAP_DIR}\\Include\\)
link_directories(${WINPCAP_DIR}\\Lib\\x64\\)

# SOEM2.0库目录
set(CMAKE_PREFIX_PATH "D:\\Program Files\\soem2\\" ${CMAKE_PREFIX_PATH})
find_package(soem REQUIRED)

add_executable(SOEMTest main.cpp)

target_link_libraries(SOEMTest PUBLIC soem wpcap)

include(GNUInstallDirs)
install(TARGETS SOEMTest
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
复制代码
注意:winpcap直接复制源代码目录下的SOEM\oshw\win32\wpcap即可,这里我将SOEM\oshw\win32\wpcap这个目录移动到了D:\\Program Files\\wpcap,SOEM\install移动到了D:\\Program Files\\soem2
  1. 主代码
C 复制代码
/*
 * This software is dual-licensed under GPLv3 and a commercial
 * license. See the file LICENSE.md distributed with this software for
 * full license information.
 */

#include <stdio.h>
#include <string.h>
#include <inttypes.h>

#include "soem/soem.h"

static uint8 IOmap[4096];
static ec_ODlistt ODlist;
static ec_OElistt OElist;
static boolean printSDO = FALSE;
static boolean printMAP = FALSE;
static char usdo[128];

static ecx_contextt ctx;

#define OTYPE_VAR    0x0007
#define OTYPE_ARRAY  0x0008
#define OTYPE_RECORD 0x0009

#define ATYPE_Rpre   0x01
#define ATYPE_Rsafe  0x02
#define ATYPE_Rop    0x04
#define ATYPE_Wpre   0x08
#define ATYPE_Wsafe  0x10
#define ATYPE_Wop    0x20

char *dtype2string(uint16 dtype, uint16 bitlen)
{
    static char str[32] = {0};

    switch (dtype)
    {
    case ECT_BOOLEAN:
        snprintf(str, sizeof(str), "BOOLEAN");
        break;
    case ECT_INTEGER8:
        snprintf(str, sizeof(str), "INTEGER8");
        break;
    case ECT_INTEGER16:
        snprintf(str, sizeof(str), "INTEGER16");
        break;
    case ECT_INTEGER32:
        snprintf(str, sizeof(str), "INTEGER32");
        break;
    case ECT_INTEGER24:
        snprintf(str, sizeof(str), "INTEGER24");
        break;
    case ECT_INTEGER64:
        snprintf(str, sizeof(str), "INTEGER64");
        break;
    case ECT_UNSIGNED8:
        snprintf(str, sizeof(str), "UNSIGNED8");
        break;
    case ECT_UNSIGNED16:
        snprintf(str, sizeof(str), "UNSIGNED16");
        break;
    case ECT_UNSIGNED32:
        snprintf(str, sizeof(str), "UNSIGNED32");
        break;
    case ECT_UNSIGNED24:
        snprintf(str, sizeof(str), "UNSIGNED24");
        break;
    case ECT_UNSIGNED64:
        snprintf(str, sizeof(str), "UNSIGNED64");
        break;
    case ECT_REAL32:
        snprintf(str, sizeof(str), "REAL32");
        break;
    case ECT_REAL64:
        snprintf(str, sizeof(str), "REAL64");
        break;
    case ECT_BIT1:
        snprintf(str, sizeof(str), "BIT1");
        break;
    case ECT_BIT2:
        snprintf(str, sizeof(str), "BIT2");
        break;
    case ECT_BIT3:
        snprintf(str, sizeof(str), "BIT3");
        break;
    case ECT_BIT4:
        snprintf(str, sizeof(str), "BIT4");
        break;
    case ECT_BIT5:
        snprintf(str, sizeof(str), "BIT5");
        break;
    case ECT_BIT6:
        snprintf(str, sizeof(str), "BIT6");
        break;
    case ECT_BIT7:
        snprintf(str, sizeof(str), "BIT7");
        break;
    case ECT_BIT8:
        snprintf(str, sizeof(str), "BIT8");
        break;
    case ECT_VISIBLE_STRING:
        snprintf(str, sizeof(str), "VISIBLE_STR(%d)", bitlen);
        break;
    case ECT_OCTET_STRING:
        snprintf(str, sizeof(str), "OCTET_STR(%d)", bitlen);
        break;
    default:
        snprintf(str, sizeof(str), "dt:0x%4.4X (%d)", dtype, bitlen);
    }
    return str;
}

char *otype2string(uint16 otype)
{
    static char str[32] = {0};

    switch (otype)
    {
    case OTYPE_VAR:
        snprintf(str, sizeof(str), "VAR");
        break;
    case OTYPE_ARRAY:
        snprintf(str, sizeof(str), "ARRAY");
        break;
    case OTYPE_RECORD:
        snprintf(str, sizeof(str), "RECORD");
        break;
    default:
        snprintf(str, sizeof(str), "ot:0x%4.4X", otype);
    }
    return str;
}

char *access2string(uint16 access)
{
    static char str[32] = {0};

    snprintf(str, sizeof(str), "%s%s%s%s%s%s",
             ((access & ATYPE_Rpre) != 0 ? "R" : "_"),
             ((access & ATYPE_Wpre) != 0 ? "W" : "_"),
             ((access & ATYPE_Rsafe) != 0 ? "R" : "_"),
             ((access & ATYPE_Wsafe) != 0 ? "W" : "_"),
             ((access & ATYPE_Rop) != 0 ? "R" : "_"),
             ((access & ATYPE_Wop) != 0 ? "W" : "_"));
    return str;
}

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 *p;
    size_t size;

    memset(&usdo, 0, sizeof(usdo));
    ecx_SDOread(&ctx, slave, index, subidx, FALSE, &l, &usdo, EC_TIMEOUTRXM);
    if (ctx.ecaterror)
    {
        return ecx_elist2string(&ctx);
    }
    else
    {
        static char str[sizeof(usdo) + 3] = {0};
        switch (dtype)
        {
        case ECT_BOOLEAN:
            u8 = (uint8 *)&usdo[0];
            if (*u8)
                snprintf(str, sizeof(str), "TRUE");
            else
                snprintf(str, sizeof(str), "FALSE");
            break;
        case ECT_INTEGER8:
            i8 = (int8 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%2.2x / %d", *i8, *i8);
            break;
        case ECT_INTEGER16:
            i16 = (int16 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%4.4x / %d", *i16, *i16);
            break;
        case ECT_INTEGER32:
        case ECT_INTEGER24:
            i32 = (int32 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%8.8x / %d", *i32, *i32);
            break;
        case ECT_INTEGER64:
            i64 = (int64 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%16.16" PRIx64 " / %" PRId64, *i64, *i64);
            break;
        case ECT_UNSIGNED8:
            u8 = (uint8 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%2.2x / %u", *u8, *u8);
            break;
        case ECT_UNSIGNED16:
            u16 = (uint16 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%4.4x / %u", *u16, *u16);
            break;
        case ECT_UNSIGNED32:
        case ECT_UNSIGNED24:
            u32 = (uint32 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%8.8x / %u", *u32, *u32);
            break;
        case ECT_UNSIGNED64:
            u64 = (uint64 *)&usdo[0];
            snprintf(str, sizeof(str), "0x%16.16" PRIx64 " / %" PRIu64, *u64, *u64);
            break;
        case ECT_REAL32:
            sr = (float *)&usdo[0];
            snprintf(str, sizeof(str), "%f", *sr);
            break;
        case ECT_REAL64:
            dr = (double *)&usdo[0];
            snprintf(str, sizeof(str), "%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];
            snprintf(str, sizeof(str), "0x%x / %u", *u8, *u8);
            break;
        case ECT_VISIBLE_STRING:
            snprintf(str, sizeof(str), "\"%s\"", usdo);
            break;
        case ECT_OCTET_STRING:
            p = str;
            size = sizeof(str);
            for (i = 0; i < l && i < (int)sizeof(usdo); i++)
            {
                int n = snprintf(p, size, "0x%2.2x ", usdo[i]);
                if (n > (int)size)
                    break;
                p += n;
                size -= n;
            }
            break;
        default:
            snprintf(str, sizeof(str), "Unknown type");
        }
        str[sizeof(str) - 1] = 0;
        return str;
    }
}

/** 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 = ecx_SDOread(&ctx, 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 = ecx_SDOread(&ctx, slave, PDOassign, (uint8)idxloop, FALSE, &rdl, &rdat, EC_TIMEOUTRXM);
            /* result is index of PDO */
            idx = etohs(rdat);
            if (idx > 0)
            {
                rdl = sizeof(subcnt);
                subcnt = 0;
                /* read number of subindexes of PDO */
                wkc = ecx_SDOread(&ctx, 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 = ecx_SDOread(&ctx, 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 = ecx_readOEsingle(&ctx, 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], bitlen), 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 = ecx_SDOread(&ctx, 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 = ecx_SDOread(&ctx, 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)(ctx.slavelist[slave].outputs - IOmap), 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)(ctx.slavelist[slave].inputs - IOmap), 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;
    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 = ctx.slavelist[slave].eep_pdi;

    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 = ecx_siifind(&ctx, slave, ECT_SII_PDO + t);
    if (PDO->Startpos > 0)
    {
        a = PDO->Startpos;
        w = ecx_siigetbyte(&ctx, slave, a++);
        w += (ecx_siigetbyte(&ctx, slave, a++) << 8);
        PDO->Length = w;
        c = 1;
        /* traverse through all PDOs */
        do
        {
            PDO->nPDO++;
            PDO->Index[PDO->nPDO] = ecx_siigetbyte(&ctx, slave, a++);
            PDO->Index[PDO->nPDO] += (ecx_siigetbyte(&ctx, slave, a++) << 8);
            PDO->BitSize[PDO->nPDO] = 0;
            c++;
            /* number of entries in PDO */
            e = ecx_siigetbyte(&ctx, slave, a++);
            PDO->SyncM[PDO->nPDO] = ecx_siigetbyte(&ctx, slave, a++);
            a++;
            obj_name = ecx_siigetbyte(&ctx, 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)
                    ecx_siistring(&ctx, 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 = ecx_siigetbyte(&ctx, slave, a++);
                    obj_idx += (ecx_siigetbyte(&ctx, slave, a++) << 8);
                    obj_subidx = ecx_siigetbyte(&ctx, slave, a++);
                    obj_name = ecx_siigetbyte(&ctx, slave, a++);
                    obj_datatype = ecx_siigetbyte(&ctx, slave, a++);
                    bitlen = ecx_siigetbyte(&ctx, slave, a++);
                    abs_offset = mapoffset + (bitoffset / 8);
                    abs_bit = bitoffset % 8;

                    PDO->BitSize[PDO->nPDO] += bitlen;
                    a += 2;

                    /* skip entry if filler (0x0000:0x00) */
                    if (obj_idx || obj_subidx)
                    {
                        str_name[0] = 0;
                        if (obj_name)
                            ecx_siistring(&ctx, 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, bitlen), str_name);
                    }
                    bitoffset += bitlen;
                    totalsize += bitlen;
                }
                PDO->SMbitsize[PDO->SyncM[PDO->nPDO]] += 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) ecx_eeprom2pdi(&ctx, 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)(ctx.slavelist[slave].outputs - IOmap), outputs_bo);
    outputs_bo += Tsize;
    /* read the assign TXPDOs */
    Tsize = si_siiPDO(slave, 0, (int)(ctx.slavelist[slave].inputs - 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 (ecx_readODlist(&ctx, cnt, &ODlist))
    {
        printf(" CoE Object Description found, %d entries.\n", ODlist.Entries);
        for (i = 0; i < ODlist.Entries; i++)
        {
            uint16_t max_sub;
            char name[128] = {0};

            ecx_readODdescription(&ctx, i, &ODlist);
            while (ctx.ecaterror)
                printf(" - %s\n", ecx_elist2string(&ctx));
            snprintf(name, sizeof(name) - 1, "\"%s\"", ODlist.Name[i]);
            if (ODlist.ObjectCode[i] == OTYPE_VAR)
            {
                printf("0x%04x      %-40s      [%s]\n", ODlist.Index[i], name,
                       otype2string(ODlist.ObjectCode[i]));
            }
            else
            {
                printf("0x%04x      %-40s      [%s  maxsub(0x%02x / %d)]\n",
                       ODlist.Index[i], name, otype2string(ODlist.ObjectCode[i]),
                       ODlist.MaxSub[i], ODlist.MaxSub[i]);
            }
            memset(&OElist, 0, sizeof(OElist));
            ecx_readOE(&ctx, i, &ODlist, &OElist);
            while (ctx.ecaterror)
                printf("- %s\n", ecx_elist2string(&ctx));

            if (ODlist.ObjectCode[i] != OTYPE_VAR)
            {
                int l = sizeof(max_sub);
                ecx_SDOread(&ctx, cnt, ODlist.Index[i], 0, FALSE, &l, &max_sub, EC_TIMEOUTRXM);
            }
            else
            {
                max_sub = ODlist.MaxSub[i];
            }

            for (j = 0; j < max_sub + 1; j++)
            {
                if ((OElist.DataType[j] > 0) && (OElist.BitLength[j] > 0))
                {
                    snprintf(name, sizeof(name) - 1, "\"%s\"", OElist.Name[j]);
                    printf("    0x%02x      %-40s      [%-16s %6s]      ", j, name,
                           dtype2string(OElist.DataType[j], OElist.BitLength[j]),
                           access2string(OElist.ObjAccess[j]));
                    if ((OElist.ObjAccess[j] & 0x0007))
                    {
                        printf("%s", SDO2string(cnt, ODlist.Index[i], j, OElist.DataType[j]));
                    }
                    printf("\n");
                }
            }
        }
    }
    else
    {
        while (ctx.ecaterror)
            printf("%s", ecx_elist2string(&ctx));
    }
}

void slaveinfo(char *ifname)
{
    int cnt, i, j, nSM;
    uint16 ssigen;
    int expectedWKC;

    printf("Starting slaveinfo\n");

    /* initialise SOEM, bind socket to ifname */
    if (ecx_init(&ctx, ifname))
    {
        printf("ecx_init on %s succeeded.\n", ifname);

        /* find and auto-config slaves */
        if (ecx_config_init(&ctx) > 0)
        {
            ec_groupt *group = &ctx.grouplist[0];

            ecx_config_map_group(&ctx, IOmap, 0);

            ecx_configdc(&ctx);
            while (ctx.ecaterror)
                printf("%s", ecx_elist2string(&ctx));
            printf("%d slaves found and configured.\n", ctx.slavecount);
            expectedWKC = (group->outputsWKC * 2) + group->inputsWKC;
            printf("Calculated workcounter %d\n", expectedWKC);
            /* wait for all slaves to reach SAFE_OP state */
            ecx_statecheck(&ctx, 0, EC_STATE_SAFE_OP, EC_TIMEOUTSTATE * 3);
            if (ctx.slavelist[0].state != EC_STATE_SAFE_OP)
            {
                printf("Not all slaves reached safe operational state.\n");
                ecx_readstate(&ctx);
                for (i = 1; i <= ctx.slavecount; i++)
                {
                    if (ctx.slavelist[i].state != EC_STATE_SAFE_OP)
                    {
                        printf("Slave %d State=%2x StatusCode=%4x : %s\n",
                               i, ctx.slavelist[i].state, ctx.slavelist[i].ALstatuscode, ec_ALstatuscode2string(ctx.slavelist[i].ALstatuscode));
                    }
                }
            }

            ecx_readstate(&ctx);
            for (cnt = 1; cnt <= ctx.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, ctx.slavelist[cnt].name, ctx.slavelist[cnt].Obits, ctx.slavelist[cnt].Ibits,
                       ctx.slavelist[cnt].state, ctx.slavelist[cnt].pdelay, ctx.slavelist[cnt].hasdc);
                if (ctx.slavelist[cnt].hasdc) printf(" DCParentport:%d\n", ctx.slavelist[cnt].parentport);
                printf(" Activeports:%d.%d.%d.%d\n", (ctx.slavelist[cnt].activeports & 0x01) > 0,
                       (ctx.slavelist[cnt].activeports & 0x02) > 0,
                       (ctx.slavelist[cnt].activeports & 0x04) > 0,
                       (ctx.slavelist[cnt].activeports & 0x08) > 0);
                printf(" Configured address: %4.4x\n", ctx.slavelist[cnt].configadr);
                printf(" Man: %8.8x ID: %8.8x Rev: %8.8x\n", (int)ctx.slavelist[cnt].eep_man, (int)ctx.slavelist[cnt].eep_id, (int)ctx.slavelist[cnt].eep_rev);
                for (nSM = 0; nSM < EC_MAXSM; nSM++)
                {
                    if (ctx.slavelist[cnt].SM[nSM].StartAddr > 0)
                        printf(" SM%1d A:%4.4x L:%4d F:%8.8x Type:%d\n", nSM, etohs(ctx.slavelist[cnt].SM[nSM].StartAddr), etohs(ctx.slavelist[cnt].SM[nSM].SMlength),
                               etohl(ctx.slavelist[cnt].SM[nSM].SMflags), ctx.slavelist[cnt].SMtype[nSM]);
                }
                for (j = 0; j < ctx.slavelist[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,
                           etohl(ctx.slavelist[cnt].FMMU[j].LogStart), etohs(ctx.slavelist[cnt].FMMU[j].LogLength), ctx.slavelist[cnt].FMMU[j].LogStartbit,
                           ctx.slavelist[cnt].FMMU[j].LogEndbit, etohs(ctx.slavelist[cnt].FMMU[j].PhysStart), ctx.slavelist[cnt].FMMU[j].PhysStartBit,
                           ctx.slavelist[cnt].FMMU[j].FMMUtype, ctx.slavelist[cnt].FMMU[j].FMMUactive);
                }
                printf(" FMMUfunc 0:%d 1:%d 2:%d 3:%d\n",
                       ctx.slavelist[cnt].FMMU0func, ctx.slavelist[cnt].FMMU1func, ctx.slavelist[cnt].FMMU2func, ctx.slavelist[cnt].FMMU3func);
                printf(" MBX length wr: %d rd: %d MBX protocols : %2.2x\n", ctx.slavelist[cnt].mbx_l, ctx.slavelist[cnt].mbx_rl, ctx.slavelist[cnt].mbx_proto);
                ssigen = ecx_siifind(&ctx, cnt, ECT_SII_GENERAL);
                /* SII general section */
                if (ssigen)
                {
                    ctx.slavelist[cnt].CoEdetails = ecx_siigetbyte(&ctx, cnt, ssigen + 0x07);
                    ctx.slavelist[cnt].FoEdetails = ecx_siigetbyte(&ctx, cnt, ssigen + 0x08);
                    ctx.slavelist[cnt].EoEdetails = ecx_siigetbyte(&ctx, cnt, ssigen + 0x09);
                    ctx.slavelist[cnt].SoEdetails = ecx_siigetbyte(&ctx, cnt, ssigen + 0x0a);
                    if ((ecx_siigetbyte(&ctx, cnt, ssigen + 0x0d) & 0x02) > 0)
                    {
                        ctx.slavelist[cnt].blockLRW = 1;
                        ctx.slavelist[0].blockLRW++;
                    }
                    ctx.slavelist[cnt].Ebuscurrent = ecx_siigetbyte(&ctx, cnt, ssigen + 0x0e);
                    ctx.slavelist[cnt].Ebuscurrent += ecx_siigetbyte(&ctx, cnt, ssigen + 0x0f) << 8;
                    ctx.slavelist[0].Ebuscurrent += ctx.slavelist[cnt].Ebuscurrent;
                }
                printf(" CoE details: %2.2x FoE details: %2.2x EoE details: %2.2x SoE details: %2.2x\n",
                       ctx.slavelist[cnt].CoEdetails, ctx.slavelist[cnt].FoEdetails, ctx.slavelist[cnt].EoEdetails, ctx.slavelist[cnt].SoEdetails);
                printf(" Ebus current: %d[mA]\n only LRD/LWR:%d\n",
                       ctx.slavelist[cnt].Ebuscurrent, ctx.slavelist[cnt].blockLRW);
                if ((ctx.slavelist[cnt].mbx_proto & ECT_MBXPROT_COE) && printSDO)
                    si_sdo(cnt);
                if (printMAP)
                {
                    if (ctx.slavelist[cnt].mbx_proto & ECT_MBXPROT_COE)
                        si_map_sdo(cnt);
                    else
                        si_map_sii(cnt);
                }
            }
        }
        else
        {
            printf("No slaves found!\n");
        }
        printf("End slaveinfo, close socket\n");
        /* stop SOEM, close socket */
        ecx_close(&ctx);
    }
    else
    {
        printf("No socket connection on %s\nExcecute as root\n", ifname);
    }
}

char ifbuf[1024];

int main(int argc, char *argv[])
{
    ec_adaptert *adapter = NULL;
    ec_adaptert *head = NULL;
    printf("SOEM (Simple Open EtherCAT Master)\nSlaveinfo\n");

    if (argc > 1)
    {
        if ((argc > 2) && (strncmp(argv[2], "-sdo", sizeof("-sdo")) == 0)) printSDO = TRUE;
        if ((argc > 2) && (strncmp(argv[2], "-map", sizeof("-map")) == 0)) printMAP = TRUE;
        /* start slaveinfo */
        strncpy(ifbuf, argv[1], sizeof(ifbuf) - 1);
        ifbuf[sizeof(ifbuf) - 1] = '\0';
        slaveinfo(ifbuf);
    }
    else
    {
        printf("Usage: slaveinfo ifname [options]\nifname = eth0 for example\nOptions :\n -sdo : print SDO info\n -map : print mapping\n");

        printf("\nAvailable adapters:\n");
        head = adapter = ec_find_adapters();
        while (adapter != NULL)
        {
            printf("    - %s  (%s)\n", adapter->name, adapter->desc);
            adapter = adapter->next;
        }
        ec_free_adapters(head);
    }

    printf("End program\n");
    return (0);
}
相关推荐
用户805533698031 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner1 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz6 天前
QML Hello World 入门示例
qt
xcyxiner9 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner10 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner10 天前
DicomViewer (添加模型类)3
qt
xcyxiner11 天前
DicomViewer (目录调整) 2
qt
xcyxiner11 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能13 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G13 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt