liblightmodbus 3.0
A lightweight, header-only, hardware-agnostic Modbus RTU/TCP library
Loading...
Searching...
No Matches
Master device

In order to use slave side functions, make sure to define LIGHTMODBUS_MASTER macro and enable necessary functions (e.g. LIGHTMODBUS_F03M) before including the library. Please also see Building and integrating liblightmodbus for more information.

Master initialization

Master device state is represented by ModbusMaster structure. It must be initialized with modbusMasterInit() before it is used:

ModbusMaster master;
&master,
myDataCallback, // Callback for handling incoming data
myExceptionCallback, // Exception callback (optional)
modbusDefaultAllocator, // Memory allocator used to allocate request
modbusMasterDefaultFunctions, // Set of supported functions
modbusMasterDefaultFunctionCount // Number of supported functions
);
// Check for errors
assert(modbusIsOk(err) && "modbusMasterInit() failed");
static uint8_t modbusIsOk(ModbusErrorInfo err)
Checks if ModbusErrorInfo contains an error.
Definition base.h:442
ModbusError modbusDefaultAllocator(ModbusBuffer *buffer, uint16_t size, void *context)
The default memory allocator based on realloc()
Definition base.impl.h:21
ModbusMasterFunctionHandler modbusMasterDefaultFunctions[]
Default array of supported functions. Length is stored in modbusMasterDefaultFunctionCount.
Definition master.impl.h:18
const uint8_t modbusMasterDefaultFunctionCount
Stores length of modbusMasterDefaultFunctions array.
Definition master.impl.h:63
ModbusErrorInfo modbusMasterInit(ModbusMaster *status, ModbusDataCallback dataCallback, ModbusMasterExceptionCallback exceptionCallback, ModbusAllocator allocator, const ModbusMasterFunctionHandler *functions, uint8_t functionCount)
Initializes a ModbusMaster struct.
Definition master.impl.h:79
Richer error represenation - source and type of error.
Definition base.h:126
Master device status.
Definition master.h:73

Similarly to slave, master has two callbacks - data callback and exception callback. The first is used for processing all register data incoming to master, the latter for handling exceptions reported by the slave. These callbacks are described in more detail in Data callback and Exception callback.

Master also relies on a memory allocator - please refer to Custom allocators for more details.

The 5th argument determines the set of functions supported by the master device. It should be a pointer to an array of ModbusMasterFunctionHandler structures which associate function codes with callbacks. The lifetime of this array must not be shorter than the lifetime of the ModbusMaster structure. The last argument must contain that array's length.

Data callback

The data callback is a function matching ModbusDataCallback, used to provide data read from the slaves to user.

This function is called from modbusParseResponse*() for every received register/coil/input value. The address of the slave, index of the register, its value and function used to acquire it are provided as an argument of type ModbusDataCallbackArgs.

If you're sure that none of the used parsing functions use the data callback, you can pass NULL as the argument to modbusMasterInit(). Importantly, all default parsing functions in the library require the data callback to be provided.

The data callback must return a ModbusError. It should always return MODBUS_OK.

Note
Return values from this callback are ignored. This, however, should not be relied upon and may be subject to change in future versions of the library.

An example of a simple data callback printing out all received data:

/*
Data callback for printing all incoming data
*/
ModbusError dataCallback(const ModbusMaster *master, const ModbusDataCallbackArgs *args)
{
printf(
"Received data:\n"
"\t from: %d\n"
"\t fun: %d\n"
"\t type: %s\n"
"\t id: %d\n"
"\tvalue: %d\n",
args->address,
args->function,
modbusDataTypeStr(args->type), // Requires LIGHTMODBUS_DEBUG
args->index,
args->value
);
// Always return MODBUS_OK
return MODBUS_OK;
}
ModbusError
Represtents different kinds of errors.
Definition base.h:137
@ MODBUS_OK
No error.
Definition base.h:143
const char * modbusDataTypeStr(ModbusDataType type)
Returns a string containing the name of the ModbusDataType enum value.
Definition debug.impl.h:86
Arguments for the data callback.
Definition master.h:40
uint8_t function
Function that reported this value.
Definition master.h:44
uint16_t value
Value of the register.
Definition master.h:43
uint16_t index
Index of the register.
Definition master.h:42
ModbusDataType type
Type of Modbus register.
Definition master.h:41
uint8_t address
Address of the slave.
Definition master.h:45

Exception callback

Master exception callback is a function matching ModbusMasterExceptionCallback called when an exception response frame is parsed by one of the modbusParseResponse*() functions.

When called, the callback is provided with address of the slave that reported the exception, function code of the function that caused it and a Modbus exception code (ModbusExceptionCode). The callback must return a ModbusError value, which should be MODBUS_OK.

Note
Return values from this callback are ignored. This, however, should not be relied upon and may be subject to change in future versions of the library.

An example of a simple exception callback printing out all received exceptions:

/*
Exception callback for printing out exceptions on master side
*/
ModbusError masterExceptionCallback(
const ModbusMaster *master,
uint8_t address,
uint8_t function,
{
printf(
"Received exception %s (function %d) from slave %d\n",
function,
address);
// Always return MODBUS_OK
return MODBUS_OK;
}
ModbusExceptionCode
Represents a Modbus exception code.
Definition base.h:230
const char * modbusExceptionCodeStr(ModbusExceptionCode code)
Returns a string containing the name of the ModbusExceptionCode enum value.
Definition debug.impl.h:67

Building requests

Master side of the library provides a set of functions for building requests. They are named according to the pattern modbusMasterBuildRequest*(). Where * is code of the function followed by the Modbus request format to be generated (PDU, RTU or TCP).

The functions without PDU, RTU or TCP at the end of their name are generic functions responsible for building the request frame and must only be used in between calls to modbusBeginRequest*() and modbusEndRequest*().

Function code Description Functions
01 Read multiple coils modbusBuildRequest01()
modbusBuildRequest01PDU()
modbusBuildRequest01RTU()
modbusBuildRequest01TCP()
02 Read multiple discrete inputs modbusBuildRequest02()
modbusBuildRequest02PDU()
modbusBuildRequest02RTU()
modbusBuildRequest02TCP()
03 Read multiple holding registers modbusBuildRequest03()
modbusBuildRequest03PDU()
modbusBuildRequest03RTU()
modbusBuildRequest03TCP()
04 Read multiple input registers modbusBuildRequest04()
modbusBuildRequest04PDU()
modbusBuildRequest04RTU()
modbusBuildRequest04TCP()
05 Write a single coil modbusBuildRequest05()
modbusBuildRequest05PDU()
modbusBuildRequest05RTU()
modbusBuildRequest05TCP()
06 Write a single holding register modbusBuildRequest06()
modbusBuildRequest06PDU()
modbusBuildRequest06RTU()
modbusBuildRequest06TCP()
15 Write multiple coils modbusBuildRequest15()
modbusBuildRequest15PDU()
modbusBuildRequest15RTU()
modbusBuildRequest15TCP()
16 Write multiple holding registers modbusBuildRequest16()
modbusBuildRequest16PDU()
modbusBuildRequest16RTU()
modbusBuildRequest16TCP()
22 Mask write register modbusBuildRequest22()
modbusBuildRequest22PDU()
modbusBuildRequest22RTU()
modbusBuildRequest22TCP()

Please see master_func.impl.h for more details.

For instance, a request to read the holding register 17 from slave with address 1 can be built with following code:

// For Modbus RTU
err = modbusBuildRequest03RTU(&master, 1, 17, 1);
assert(modbusIsOk(err) && "modbusBuildRequest03RTU() failed");
static ModbusErrorInfo modbusBuildRequest03RTU(ModbusMaster *status, uint8_t address, uint16_t index, uint16_t count)
Read multiple holding registers - a wrapper for modbusBuildRequest01020304()
Definition master_func.h:239

If the request has been built successfully, it can be accessed via modbusMasterGetRequest(), has length of modbusMasterGetRequestLength() bytes and can be sent to the slave.

Processing responses

After obtaining the response from the slave, it's time to process it. In order to do that, one of the modbusParseResponse*() functions can be used:

// For Modbus RTU
&master,
slaveResponseData,
slaveResponseLength);
// Handle serious errors
handleMasterError(err);
// Handle errors related to the structure of the request frame
// If the request produced by modbusBuildRequest*() caused
// you may have found a bug!
handleRequestError(err);
// Handle errors related to the structure of the response frame
// e.g. invalid CRC, frame too short
handleResponseError(err);
// Optionally free the request frame
static ModbusError modbusGetRequestError(ModbusErrorInfo err)
Returns request error from ModbusErrorInfo.
Definition base.h:462
static ModbusError modbusGetGeneralError(ModbusErrorInfo err)
Returns general error from ModbusErrorInfo.
Definition base.h:452
static ModbusError modbusGetResponseError(ModbusErrorInfo err)
Returns response error from ModbusErrorInfo.
Definition base.h:472
static void modbusMasterFreeRequest(ModbusMaster *status)
Frees memory allocated for master's request frame.
Definition master.h:172
ModbusErrorInfo modbusParseResponseRTU(ModbusMaster *status, const uint8_t *request, uint16_t requestLength, const uint8_t *response, uint16_t responseLength)
Parses a Modbus RTU slave response.
Definition master.impl.h:260
static uint16_t modbusMasterGetRequestLength(const ModbusMaster *status)
Returns the length of the request generated by the master.
Definition master.h:136
static const uint8_t * modbusMasterGetRequest(const ModbusMaster *status)
Returns a pointer to the request generated by the master.
Definition master.h:128

Master cleanup

When you're done using an instance of ModbusMaster, you can destroy it using modbusMasterDestroy().

void modbusMasterDestroy(ModbusMaster *status)
Deinitializes a ModbusMaster struct.
Definition master.impl.h:102