| ioPAC RTU Controllers C/C++ Sample Code Programming Guide

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

Data Structures | Macros | Typedefs | Functions | Variables
modbus_rtu_slave.c File Reference

Modbus RTU Slave Sample Application More...

`#include <libmoxa_rtu.h>`

## Data Structures
struct | _MODBUS_MAP

## Macros
#define | MODBUS_SERIAL_PARITY 'N'
#define | MODBUS_DEVICE_ID 1
#define | MODBUS_SIZE 3000
#define | DIM(x) (sizeof(x)/sizeof(x[0]))

## Typedefs
typedef struct _MODBUS_MAP | MODBUS_MAP
typedef struct _MODBUS_MAP * | pMODBUS_MAP

## Functions
void | stopHandler (int signum)
int | main (int argc, char *argv[])

## Variables
volatile sig_atomic_t | keepRunning
MODBUS_MAP | ModbusMap []

## Detailed Description

Modbus RTU Slave Sample Application

Copyright
  Moxa Inc.

Date
  04-02-2015

Author
  TJ Tai

Version
  V1.0
  Modbus RTU Slave Sample Application

    Introduction:
    The Modbus Slave creates two Modbus addresses, one for DIs (input register) and one for DOs (holding register).
    Then, PC Modbus Master polls for DI values and sets the DO statuses equal to the DI values.
    Example:
    1. Using default: ./modbus_rtu_slave
    Default:
    Environment Setting on ioPAC8600
    RTU Slot = 1
    DI  Slot = 2
    DO  Slot = 3
    Help:

    root@Moxa:/tmp#./modbus_rtu_slave -h
    Modbus RTU Slave sample program.

    Usage: ./modbus_rtu_slave [OPTIONS]

    Get DI value and set DO value

    Options:
            -r       Slot of RTU(Serial) module [1-9]. Default slot = 1
            -i       Slot of DI module [1-9]. Default slot = 2
            -s       Slot of DO module [1-9]. Default slot = 3

Library:
ModbusRTUSlave APIs

## Macro Definition Documentation

#define MODBUS_SERIAL_PARITY 'N'

/*******************************************************************************
* Copyright Moxa Inc.
*
* Modbus RTU Slave Sample Application
*
* Date Author Comment
* 04-02-2015 TJ Tai Created.
******************************************************************************/
#include <libmoxa_rtu.h>
#define MODBUS_SERIAL_PARITY 'N'
#define MODBUS_DEVICE_ID 1
#define MODBUS_SIZE 3000
#define DIM(x) (sizeof(x)/sizeof(x[0]))
volatile sig_atomic_t keepRunning;
//static int keepRunning = 1;
void stopHandler(int signum)
{
keepRunning = 1;
}
typedef struct _MODBUS_MAP
{
UINT8 slave_group;
UINT16 slave_addr;
int (*pfnModRead)(UINT8 *pData, UINT16 nth, void *pUserData);
int (*pfnModWrite)(UINT8 *pData, UINT16 nth, void *pUserData);
UINT32 reg;
} MODBUS_MAP, *pMODBUS_MAP;
static int getReg(UINT8 *pData, UINT16 nth, void *pUserData);
static int setReg(UINT8 *pData, UINT16 nth, void *pUserData);
MODBUS_MAP ModbusMap[] =
{
//{ MODBUS_INPUT_REGISTER, 0x0001, getReg, NULL, 0xFFFF },
//{ MODBUS_HOLDING_REGISTER, 0x0002, getReg, setReg, 0xFFFF },
{ MODBUS_INPUT_REGISTER, 0x0800, getReg, NULL, 0xFFFF },
{ MODBUS_HOLDING_REGISTER, 0x0810, getReg, setReg, 0xFFFF },
};
static int getReg(UINT8 *pData, UINT16 nth, void *pUserData)
{
UINT16 data = 0;
char *ptr = (char *)&data;
pMODBUS_MAP info = (pMODBUS_MAP)pUserData;
data = info->reg;
pData[nth * 2] = ptr[1];
pData[nth * 2 + 1] = ptr[0];
return RETURN_OK;
}
static int setReg(UINT8 *pData, UINT16 nth, void *pUserData)
{
UINT16 value = MAKE_WORD(pData[nth * 2], pData[nth * 2 + 1]);
pMODBUS_MAP info = (pMODBUS_MAP)pUserData;
info->reg = value;
return RETURN_OK;
}
int main(int argc, char *argv[])
{
UINT32 handle_num;
int rc = 0;
int i;
UINT32 rtuSlot = 1;
UINT32 diSlot = 2;
UINT32 doSlot = 3, slotMin = 1, slotMax = 0;
int diChannelAmount = 16;
int doChannelAmount = 16;
UINT32 *pDIValue;
UINT32 *pDOValue;
UINT32 lastDOValue;
MX_RTU_Total_Slots_Get(&slotMax);
while(-1 != (rc = getopt(argc, argv, "hr:i:s:")))
{
switch(rc)
{
case 'r':
rtuSlot = atoi(optarg);
if (rtuSlot < slotMin || rtuSlot > slotMax) {
printf("Error parameter: slot: %d\n", rtuSlot);
return -1;
}
case 'i':
diSlot = atoi(optarg);
if(diSlot < slotMin || diSlot > slotMax)
{
printf("Error parameter: slot: %d\n", diSlot);
return -1;
}
break;
case 's':
doSlot = atoi(optarg);
if(doSlot < slotMin || doSlot > slotMax)
{
printf("Error parameter: slot: %d\n", doSlot);
return -1;
}
break;
case '?':
case 'h':
default:
printf("Modbus RTU Slave sample program.\n\n");
printf("Usage: ./modbus_rtu_slave [OPTIONS]\n\n");
printf("Get DI value and set DO value\n\n");
printf("Options:\n");
printf("\t%-8s Slot of RTU module [%d-%d]. Default slot = %d\n",
"-r", slotMin, slotMax, rtuSlot);
printf("\t%-8s Slot of DI module [%d-%d]. Default slot = %d\n",
"-i", slotMin, slotMax, diSlot);
printf("\t%-8s Slot of DO module [%d-%d]. Default slot = %d\n",
"-s", slotMin, slotMax, doSlot);
printf("\n");
return 0;
}
}
printf("%-10s: %d\n", "RTU slot", rtuSlot);
printf("%-10s: %d\n", "DI slot", diSlot);
printf("%-10s: %d\n", "DO slot", doSlot);
TTY_PARAM param;
memset(&param, 0, sizeof(param));
param.baudrate = BAUD_RATE_115200;
param.databits = SERIAL_DATA_BITS_8;
param.flowCtrl = HW_FLOW_CONTROL;
param.mode = RS232_MODE;
param.parity = SERIAL_PARITY_NONE;
param.stopbit = SERIAL_STOP_BIT_1;
rc = MX_RTU_Modbus_Rtu_Slave_Init();
if (rc != MODBUS_SLAVE_ERR_OK) {
printf("MX_RTU_Modbus_Rtu_Slave_Init error, rc = %d\r\n", rc);
return -1;
}
rc = MX_RTU_Modbus_Rtu_Slave_Register(rtuSlot, PORT1, MODBUS_DEVICE_ID, MODBUS_SIZE, &param, &handle_num);
if (rc != MODBUS_SLAVE_ERR_OK) {
printf("Rtu Slave Register Fail, rtuSlot = %d, port = %d, handle = %d, rc = %d\n", rtuSlot, PORT1, handle_num, rc);
return -1;
}
//Init modbus entries
for(i = 0; i < DIM(ModbusMap); i++)
{
rc = MX_RTU_Modbus_Rtu_Slave_Add_Entry(handle_num, ModbusMap[i].slave_group,
ModbusMap[i].slave_addr, &ModbusMap[i], ModbusMap[i].pfnModRead,
ModbusMap[i].pfnModWrite);
if(rc != MODBUS_SLAVE_ERR_OK)
{
printf("MX_RTU_Modbus_Rtu_Slave_Add_Entry(), return code = %d.\n", rc);
return -1;
}
}
rc = MX_RTU_Modbus_Rtu_Slave_Start(handle_num);
if (rc != MODBUS_SLAVE_ERR_OK) {
printf("MX_RTU_Modbus_Rtu_Slave_Start handle %d error, rc = %d\r\n", handle_num, rc);
return -1;
}
pDIValue = &(ModbusMap[0].reg);
pDOValue = &(ModbusMap[1].reg);
lastDOValue = *pDOValue;
// Config DO module
rc = MX_RTU_Module_DO_Value_Set(doSlot, *pDOValue);
if(rc != MODULE_RW_ERR_OK)
printf("MX_RTU_Module_DO_Value_Set(%d, 0x%04X), return code = %d.\n",
doSlot, *pDOValue, rc);
printf("\nModbus Server is running... UnitID: %d\n\n", MODBUS_DEVICE_ID);
signal(SIGINT, stopHandler);
// Start to polling DI and set DO
while(!keepRunning)
{
rc = MX_RTU_Module_DI_Value_Get(diSlot, pDIValue, NULL);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_Module_DI_Value_Get(%d), return code = %d.\n", diSlot, rc);
break;
}
if(*pDOValue != lastDOValue)
{
lastDOValue = *pDOValue;
rc = MX_RTU_Module_DO_Value_Set(doSlot, *pDOValue);
if(rc != MODULE_RW_ERR_OK)
{
printf("MX_RTU_Module_DO_Value_Set(%d, 0x%04X), return code = %d.\n",
doSlot, *pDOValue, rc);
break;
}
}
usleep(200000);
}
printf("Stop Server\n");
rc = MX_RTU_Modbus_Rtu_Slave_Stop(handle_num);
if (rc != MODBUS_SLAVE_ERR_OK) {
printf("MX_RTU_Modbus_Rtu_Slave_Stop handle %d error, rc = %d\r\n", handle_num, rc);
return -1;
}
//rc = MX_RTU_Modbus_Rtu_Slave_Unregister(handle_num, rtuSlot, PORT1);
rc = MX_RTU_Modbus_Rtu_Slave_Unregister(handle_num);
if (rc != MODBUS_SLAVE_ERR_OK) {
printf("Modbus Rtu Slave Unregister handle %d error, rc = %d\r\n", handle_num, rc);
return -1;
}
rc = MX_RTU_Modbus_Rtu_Slave_Uninit();
if (rc != MODBUS_SLAVE_ERR_OK) {
printf("MX_RTU_Modbus_Rtu_Slave_UnInit error, rc = %d\r\n", rc);
return -1;
}
return 0;
}

#define MODBUS_DEVICE_ID 1

#define MODBUS_SIZE 3000

#define DIM | ( |  | x | ) | (sizeof(x)/sizeof(x[0]))

## Typedef Documentation

typedef struct _MODBUS_MAP MODBUS_MAP

typedef struct _MODBUS_MAP * pMODBUS_MAP

## Function Documentation

void stopHandler | ( | int | signum | ) |

int main | ( | int | argc,
|  | char * | argv[]
| ) |  |

## Variable Documentation

volatile sig_atomic_t keepRunning

MODBUS_MAP ModbusMap[]

Initial value:
=
{
{ MODBUS_INPUT_REGISTER, 0x0800, getReg, NULL, 0xFFFF },
{ MODBUS_HOLDING_REGISTER, 0x0810, getReg, setReg, 0xFFFF },
}
MODBUS_HOLDING_REGISTER
#define MODBUS_HOLDING_REGISTER
Definition: libmoxa_rtu.h:4086
MODBUS_INPUT_REGISTER
#define MODBUS_INPUT_REGISTER
Definition: libmoxa_rtu.h:4087