• Libraries
  • Shop
  • Doc
  • Free Modbus
  • Support
  • Login
FieldTalk Modbus Slave C++ Library  Library version 2.10.0
  • Introduction
  • Chapters
  • Modules
  • Classes
    Examples

    Serial Example

    The following example tinyslave.cpp shows how to implement a small Modbus RTU slave:

    // HM platform detection
    #include "hmplatf.h"
    // Platform header
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    // Include FieldTalk package header
    #include "MbusRtuSlaveProtocol.hpp"
    /*****************************************************************************
    * Gobal data
    *****************************************************************************/
    #if defined(__WIN32__)
    const TCHAR *portName = TEXT("COM1");
    #elif defined(__LINUX__)
    const char *portName = "/dev/ttyS0";
    #elif defined(__MACOSX__)
    const char *portName = "/dev/ttys0";
    #elif defined(__FREEBSD__) || defined(__NETBSD__) || defined(__OPENBSD__)
    const char *portName = "/dev/ttyd0";
    #elif defined(__QNX__)
    const char *portName = "/dev/ser1";
    #elif defined(__VXWORKS__)
    const char *portName = "/tyCo/0";
    #elif defined(__SOLARIS__)
    const char *portName = "/dev/ttya";
    #elif defined(__IRIX__)
    const char *portName = "/dev/ttyf1";
    #elif defined(__OSF__)
    const char *portName = "/dev/tty00";
    #else
    const char *portName = "/dev/tty";
    #endif
    /*****************************************************************************
    * Modbus data table
    *****************************************************************************/
    typedef struct
    {
    short actTemp; // Register 1
    short minTemp; // Register 2
    long scanCounter; // Register 3 and 4
    float setPoint; // Register 5 and 6
    short statusReg; // Register 7
    short configType; // Register 8
    } MyDeviceData;
    MyDeviceData deviceData;
    /*****************************************************************************
    * Data provider
    *****************************************************************************/
    class MyDataProvider: public MbusDataTableInterface
    {
    public:
    int readHoldingRegistersTable(int startRef, short regArr[], int refCnt)
    {
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(regArr, &((short *) &deviceData)[startRef],
    refCnt * sizeof(short));
    return 1;
    }
    int writeHoldingRegistersTable(int startRef,
    const short regArr[],
    int refCnt)
    {
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(&((short *) &deviceData)[startRef],
    regArr, refCnt * sizeof(short));
    return 1;
    }
    } dataProvider;
    /*****************************************************************************
    * Modbus protocol declaration
    *****************************************************************************/
    MbusRtuSlaveProtocol mbusServer;
    /*****************************************************************************
    * Function implementation
    *****************************************************************************/
    void startupServer()
    {
    int result;
    result = mbusServer.addDataTable(1, &dataProvider);
    if (result == FTALK_SUCCESS)
    result = mbusServer.startupServer(portName,
    19200L, // Baudrate
    8, // Databits
    1, // Stopbits
    2); // Even parity
    if (result != FTALK_SUCCESS)
    {
    fprintf(stderr, "Error starting server: %s!\n",
    getBusProtocolErrorText(result));
    exit(EXIT_FAILURE);
    }
    }
    void shutdownServer()
    {
    mbusServer.shutdownServer();
    }
    void runServer()
    {
    int result = FTALK_SUCCESS;
    while (result == FTALK_SUCCESS)
    {
    result = mbusServer.serverLoop();
    if (result != FTALK_SUCCESS)
    fprintf(stderr, "%s!\n", getBusProtocolErrorText(result));
    }
    }
    #if defined(_WIN32_WCE)
    int wmain()
    #else
    int main()
    #endif
    {
    atexit(shutdownServer);
    startupServer();
    runServer();
    return EXIT_FAILURE;
    }

    MODBUS/TCP Example

    The following example tcpslave.cpp shows how to implement a small Modbus/TCP slave:

    // Platform header
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    // Include FieldTalk package header
    #include "MbusTcpSlaveProtocol.hpp"
    /*****************************************************************************
    * Modbus data table
    *****************************************************************************/
    typedef struct
    {
    short actTemp; // Register 1
    short minTemp; // Register 2
    long scanCounter; // Register 3 and 4
    float setPoint; // Register 5 and 6
    short statusReg; // Register 7
    short configType; // Register 8
    } MyDeviceData;
    MyDeviceData deviceData;
    /*****************************************************************************
    * Data provider
    *****************************************************************************/
    const char* VENDOR_NAME = "proconX Pty Ltd";
    const char* PRODUCT_CODE = "FT-MBSV";
    const char* VENDOR_URL = "http://www.modbusdriver.com";
    const char* PRODUCT_NAME = "FieldTalk";
    const char* MODEL_NAME = "Modbus Slave C++ Library";
    const char* USER_APPLICATION_NAME = "diagslave";
    class MyDataProvider: public MbusDataTableInterface
    {
    public:
    int readHoldingRegistersTable(int startRef, short regArr[], int refCnt)
    {
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(regArr, &((short *) &deviceData)[startRef],
    refCnt * sizeof(short));
    return 1;
    }
    int writeHoldingRegistersTable(int startRef,
    const short regArr[],
    int refCnt)
    {
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > int(sizeof(deviceData) / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(&((short *) &deviceData)[startRef],
    regArr, refCnt * sizeof(short));
    return 1;
    }
    int readDeviceIdentification(int objId, char bufferArr[], int maxBufSize)
    {
    switch (objId)
    {
    //
    // VendorName
    //
    case 0:
    if (bufferArr)
    {
    #ifdef HAS_STRNCPY
    strncpy(bufferArr, VENDOR_NAME, maxBufSize);
    #else
    strcpy(bufferArr, VENDOR_NAME);
    #endif
    }
    return strlen(VENDOR_NAME);
    //
    // ProductCode
    //
    case 1:
    if (bufferArr)
    {
    #ifdef HAS_STRNCPY
    strncpy(bufferArr, PRODUCT_CODE, maxBufSize);
    #else
    strcpy(bufferArr, PRODUCT_CODE);
    #endif
    }
    return strlen(PRODUCT_CODE);
    //
    // MajorMinorRevision
    //
    case 2:
    if (bufferArr)
    {
    #ifdef HAS_STRNCPY
    strncpy(bufferArr, MbusSlaveServer::getPackageVersion(), maxBufSize);
    #else
    strcpy(bufferArr, MbusSlaveServer::getPackageVersion());
    #endif
    }
    return strlen(MbusSlaveServer::getPackageVersion());
    }
    return 0; // Return 0 for object not found
    }
    } dataProvider;
    /*****************************************************************************
    * Modbus protocol declaration
    *****************************************************************************/
    MbusTcpSlaveProtocol mbusServer;
    /*****************************************************************************
    * Function implementation
    *****************************************************************************/
    void masterPollEvent(const char* masterIpAddrSz)
    {
    }
    int xmasterPollEvent(const char* masterIpAddrSz)
    {
    printf("kicking out %s!\n", masterIpAddrSz);
    masterPollEvent(masterIpAddrSz);
    return 0;
    }
    void startupServer()
    {
    int result;
    mbusServer.setTimeout(3000); // 3 sec activity time-out
    mbusServer.setConnectionTimeOut(10000); // 10 s connection time-out
    // mbusServer.installMasterPollNotifyCallBack(xmasterPollEvent);
    result = mbusServer.addDataTable(1, &dataProvider); // Unit ID is 1
    if (result == FTALK_SUCCESS)
    result = mbusServer.startupServer();
    if (result != FTALK_SUCCESS)
    {
    fprintf(stderr, "Error starting server: %s!\n",
    getBusProtocolErrorText(result));
    exit(EXIT_FAILURE);
    }
    }
    void shutdownServer()
    {
    mbusServer.shutdownServer();
    }
    void runServer()
    {
    int result = FTALK_SUCCESS;
    while (result == FTALK_SUCCESS)
    {
    result = mbusServer.serverLoop();
    if (result != FTALK_SUCCESS)
    fprintf(stderr, "%s!\n", getBusProtocolErrorText(result));
    }
    }
    #if defined(_WIN32_WCE)
    int wmain()
    #else
    int main()
    #endif
    {
    atexit(shutdownServer);
    startupServer();
    runServer();
    return EXIT_FAILURE;
    }

    Shared Memory Data Provider example

    The following example shows how to implement a Data Provider which serves it's data from shared memory:

    class ShmemMbusDataTable: public MbusDataTableInterface
    {
    public:
    ShmemMbusDataTable(int table0Size, int table1Size, int table3Size, int table4Size)
    {
    int i;
    int fd;
    for (i = 0; i < 5; i++)
    {
    //
    // Determine table sizes
    //
    switch (i)
    {
    case 0:
    if (table0Size <= 0)
    break; // No table will be created for this type
    dataTableArr[i].size = table0Size * sizeof(char);
    break;
    case 1:
    if (table1Size <= 0)
    break; // No table will be created for this type
    dataTableArr[i].size = table1Size * sizeof(char);
    break;
    case 2:
    dataTableArr[i].size = sizeof(SlaveStatusInfo);
    break;
    case 3:
    if (table3Size <= 0)
    break; // No table will be created for this type
    dataTableArr[i].size = table3Size * sizeof(short);
    break;
    case 4:
    if (table4Size <= 0)
    break; // No table will be created for this type
    dataTableArr[i].size = table4Size * sizeof(short);
    break;
    }
    //
    // Open shared memory tables
    //
    shm_unlink(dataTableArr[i].name);
    if (dataTableArr[i].size == 0)
    continue;
    fd = shm_open(dataTableArr[i].name, O_CREAT | O_RDWR | O_EXCL, S_IRWXU);
    if (fd < 0)
    {
    perror("Shared memory open failed");
    abort();
    }
    //
    // Size it
    //
    if (ftruncate(fd, dataTableArr[i].size) < 0)
    {
    perror("Shared memory ftruncate failed");
    abort();
    }
    //
    // Map shared memory into address space
    //
    dataTableArr[i].ptr = (short *) mmap(0, dataTableArr[i].size,
    PROT_READ | PROT_WRITE,
    MAP_SHARED, fd, 0L);
    if (dataTableArr[i].ptr == NULL)
    {
    perror("Shared memory mmap failed");
    abort();
    }
    close (fd); // No we can close the file descriptor
    memset(dataTableArr[i].ptr, 0, dataTableArr[i].size);
    }
    //
    // Handle special cases where we map table 3 to point to table 4 and
    // table 1 to point to table 0
    //
    if (table3Size == -1) // Map table 3 to table 4
    {
    dataTableArr[3].size = dataTableArr[4].size;
    dataTableArr[3].ptr = dataTableArr[4].ptr;
    }
    if (table1Size == -1) // Map table 1 to table 0
    {
    dataTableArr[1].size = dataTableArr[0].size;
    dataTableArr[1].ptr = dataTableArr[0].ptr;
    }
    // Setup pointer to status table
    slaveStatusInfoPtr = (SlaveStatusInfo *) dataTableArr[2].ptr;
    }
    ~ShmemMbusDataTable()
    {
    int i;
    for (i = 0; i < 5; i++)
    {
    if (dataTableArr[i].ptr != NULL)
    {
    munmap(dataTableArr[i].ptr, dataTableArr[i].size);
    shm_unlink(dataTableArr[i].name);
    }
    }
    }
    void timeOutHandler()
    {
    slaveStatusInfoPtr->timeoutCnt++;
    }
    int readInputDiscretesTable(int startRef,
    char bitArr[],
    int refCnt)
    {
    printf("\nreadInputDiscretesTable: %d, %d\n", startRef, refCnt);
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > (int) (dataTableArr[1].size / sizeof(char)))
    return 0;
    //
    // Copy data
    //
    memcpy(bitArr, &((char *) dataTableArr[1].ptr)[startRef], refCnt * sizeof(char));
    slaveStatusInfoPtr->readDiscretesCnt++;
    return 1;
    }
    int readCoilsTable(int startRef,
    char bitArr[],
    int refCnt)
    {
    printf("\nreadCoilsTable: %d, %d\n", startRef, refCnt);
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > (int) (dataTableArr[0].size / sizeof(char)))
    return 0;
    //
    // Copy data
    //
    memcpy(bitArr, &((char *) dataTableArr[0].ptr)[startRef], refCnt * sizeof(char));
    slaveStatusInfoPtr->readDiscretesCnt++;
    return 1;
    }
    int writeCoilsTable(int startRef,
    const char bitArr[],
    int refCnt)
    {
    printf("\nriteCoilsTable: %d, %d\n", startRef, refCnt);
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > (int) (dataTableArr[0].size / sizeof(char)))
    return 0;
    //
    // Copy data
    //
    memcpy(&((char *) dataTableArr[0].ptr)[startRef], bitArr, refCnt * sizeof(char));
    slaveStatusInfoPtr->writeDiscretesCnt++;
    return 1;
    }
    int readInputRegistersTable(int startRef,
    short regArr[],
    int refCnt)
    {
    printf("\nreadInputRegistersTable: %d, %d\n", startRef, refCnt);
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > (int) (dataTableArr[3].size / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(regArr, &((short *) dataTableArr[3].ptr)[startRef], refCnt * sizeof(short));
    slaveStatusInfoPtr->readRegistersCnt++;
    return 1;
    }
    int readHoldingRegistersTable(int startRef,
    short regArr[],
    int refCnt)
    {
    printf("\nreadHoldingRegistersTable: %d, %d\n", startRef, refCnt);
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > (int) (dataTableArr[4].size / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(regArr, &((short *) dataTableArr[4].ptr)[startRef], refCnt * sizeof(short));
    slaveStatusInfoPtr->readRegistersCnt++;
    return 1;
    }
    int writeHoldingRegistersTable(int startRef,
    const short regArr[],
    int refCnt)
    {
    printf("\nwriteHoldingRegistersTable: %d, %d\n", startRef, refCnt);
    // Adjust Modbus reference counting
    startRef--;
    //
    // Validate range
    //
    if (startRef + refCnt > (int) (dataTableArr[4].size / sizeof(short)))
    return 0;
    //
    // Copy data
    //
    memcpy(&((short *) dataTableArr[4].ptr)[startRef], regArr, refCnt * sizeof(short));
    slaveStatusInfoPtr->writeRegistersCnt++;
    return 1;
    }
    private:
    SlaveStatusInfo *slaveStatusInfoPtr;
    };

    • FieldTalk Modbus Slave C++ Library Library version 2.10.0
    Speak to the Experts
    Modbus Organization Member logo

    We are member of the Modbus Organization, Inc.

    Buy with Confidence
    30-day money back guarantee All our FieldTalk web sales are backed by a 30-day Money Back Guarantee.
    We Accept
    Bank VISA MasterCard PayPal
    Customer Info
    • Info & Contact
    • Customer Login
    • Terms of Service
    • Terms of Sale
    • Privacy Policy
    © 2005-2025 proconX Pty Ltd. All rights reserved. proconX and FieldTalk are trademarks of proconX Pty Ltd.
    All other trademarks and registered trademarks appearing on www.modbusdriver.com are the property of their respective owners.