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:
&master,
myDataCallback,
myExceptionCallback,
);
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:
{
printf(
"Received data:\n"
"\t from: %d\n"
"\t fun: %d\n"
"\t type: %s\n"
"\t id: %d\n"
"\tvalue: %d\n",
);
}
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:
uint8_t address,
uint8_t function,
{
printf(
"Received exception %s (function %d) from slave %d\n",
function,
address);
}
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*()
.
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:
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:
&master,
slaveResponseData,
slaveResponseLength);
handleMasterError(err);
handleRequestError(err);
handleResponseError(err);
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