API reference
This section provides a full reference of all the functions, macros and types that MicroTBX-Modbus offers.
Macros
Version
Macro | Description |
---|---|
TBX_MB_VERSION_MAIN |
Main version number of MicroTBX-Modbus. |
TBX_MB_VERSION_MINOR |
Minor version number of MicroTBX-Modbus. |
TBX_MB_VERSION_PATCH |
Patch number of MicroTBX-Modbus. |
Common
Function codes.
Macro | Description |
---|---|
TBX_MB_FC01_READ_COILS |
Modbus function code 01 - Read Coils. |
TBX_MB_FC02_READ_DISCRETE_INPUTS |
Modbus function code 02 - Read Discrete Inputs. |
TBX_MB_FC03_READ_HOLDING_REGISTERS |
Modbus function code 03 - Read Holding Registers. |
TBX_MB_FC04_READ_INPUT_REGISTERS |
Modbus function code 04 - Read Input Registers. |
TBX_MB_FC05_WRITE_SINGLE_COIL |
Modbus function code 05 - Write Single Coil. |
TBX_MB_FC06_WRITE_SINGLE_REGISTER |
Modbus function code 06 - Write Single Register. |
TBX_MB_FC08_DIAGNOSTICS |
Modbus function code 08 - Diagnostics. |
TBX_MB_FC15_WRITE_MULTIPLE_COILS |
Modbus function code 15 - Write Multiple Coils. |
TBX_MB_FC16_WRITE_MULTIPLE_REGISTERS |
Modbus function code 16 - Write Multiple Registers. |
Exception codes.
Macro | Description |
---|---|
TBX_MB_EC01_ILLEGAL_FUNCTION |
Modbus exception code 01 - Illegal function. |
TBX_MB_EC02_ILLEGAL_DATA_ADDRESS |
Modbus exception code 02 - Illegal data address. |
TBX_MB_EC03_ILLEGAL_DATA_VALUE |
Modbus exception code 03 - Illegal data value. |
TBX_MB_EC04_SERVER_DEVICE_FAILURE |
Modbus exception code 04 - Server device failure. |
Diagnostics sub function codes.
Macro | Description |
---|---|
TBX_MB_DIAG_SC_QUERY_DATA |
Diagnostics sub-function code - Return Query Data. |
TBX_MB_DIAG_SC_CLEAR_COUNTERS |
Diagnostics sub-function code - Clear Counters. |
TBX_MB_DIAG_SC_BUS_MESSAGE_COUNT |
Diagnostics sub-function code - Return Bus Message Count. |
TBX_MB_DIAG_SC_BUS_COMM_ERROR_COUNT |
Diagnostics sub-function code - Return Bus Communication Error Count. |
TBX_MB_DIAG_SC_BUS_EXCEPTION_ERROR_COUNT |
Diagnostics sub-function code - Return Bus Exception Error Count. |
TBX_MB_DIAG_SC_SERVER_MESSAGE_COUNT |
Diagnostics sub-function code - Return Server Message Count. |
TBX_MB_DIAG_SC_SERVER_NO_RESPONSE_COUNT |
Diagnostics sub-function code - Return Server No Response Count. |
Miscellaneous.
Macro | Description |
---|---|
TBX_MB_FC_EXCEPTION_MASK |
Bit mask to OR to the function code to flag it as an exception response. |
Transport layer
Node address.
Macro | Description |
---|---|
TBX_MB_TP_NODE_ADDR_BROADCAST |
Node address value for broadcast purposes. |
TBX_MB_TP_NODE_ADDR_MIN |
Minimum value of a valid node address. |
TBX_MB_TP_NODE_ADDR_MAX |
Maximum value of a valid node address. |
Protocol data unit (PDU).
Macro | Description |
---|---|
TBX_MB_TP_PDU_CODE_LEN_MAX |
Maximum size of the "Function code" at the start of a PDU. |
TBX_MB_TP_PDU_DATA_LEN_MAX |
Maximum number of data bytes inside a PDU. This excludes the function code. |
TBX_MB_TP_PDU_MAX_LEN |
Maximum length of a PDU. |
Types
Server
tTbxMbServer
typedef void * tTbxMbServer
Handle to a Modbus server channel object, in the format of an opaque pointer.
tTbxMbServerResult
typedef enum
{
TBX_MB_SERVER_OK = 0U,
TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR,
TBX_MB_SERVER_ERR_DEVICE_FAILURE
} tTbxMbServerResult
numerated type with all supported return values for the callbacks.
tTbxMbServerReadInput
typedef tTbxMbServerResult (* tTbxMbServerReadInput)(tTbxMbServer channel,
uint16_t addr,
uint8_t * value)
Modbus server callback function for reading a discrete input.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
addr |
Element address (0 ..65535 ). |
value |
Pointer to write the value of the input to. Use TBX_ON if the input is on, TBX_OFF otherwise. |
Return value |
---|
TBX_MB_SERVER_OK if successful, TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR if the specific data elementaddress is not supported by this server, TBX_MB_SERVER_ERR_DEVICE_FAILURE otherwise. |
tTbxMbServerReadCoil
typedef tTbxMbServerResult (* tTbxMbServerReadCoil)(tTbxMbServer channel,
uint16_t addr,
uint8_t * value)
Modbus server callback function for reading a coil.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
addr |
Element address (0 ..65535 ). |
value |
Pointer to write the value of the coil to. Use TBX_ON if the coils is on, TBX_OFF otherwise. |
Return value |
---|
TBX_MB_SERVER_OK if successful, TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR if the specific data elementaddress is not supported by this server, TBX_MB_SERVER_ERR_DEVICE_FAILURE otherwise. |
tTbxMbServerWriteCoil
typedef tTbxMbServerResult (* tTbxMbServerWriteCoil)(tTbxMbServer channel,
uint16_t addr,
uint8_t value)
Modbus server callback function for writing a coil.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
addr |
Element address (0 ..65535 ). |
value |
Coil value. Use TBX_ON to activate the coil, TBX_OFF otherwise. |
Return value |
---|
TBX_MB_SERVER_OK if successful, TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR if the specific data elementaddress is not supported by this server, TBX_MB_SERVER_ERR_DEVICE_FAILURE otherwise. |
tTbxMbServerReadInputReg
typedef tTbxMbServerResult (* tTbxMbServerReadInputReg)(tTbxMbServer channel,
uint16_t addr,
uint16_t * value)
Modbus server callback function for reading an input register.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
addr |
Element address (0 ..65535 ). |
value |
Pointer to write the value of the input register to. |
Return value |
---|
TBX_MB_SERVER_OK if successful, TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR if the specific data elementaddress is not supported by this server, TBX_MB_SERVER_ERR_DEVICE_FAILURE otherwise. |
tTbxMbServerReadHoldingReg
typedef tTbxMbServerResult (* tTbxMbServerReadHoldingReg)(tTbxMbServer channel,
uint16_t addr,
uint16_t * value)
Modbus server callback function for reading a holding register.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
addr |
Element address (0 ..65535 ). |
value |
Pointer to write the value of the holding register to. |
Return value |
---|
TBX_MB_SERVER_OK if successful, TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR if the specific data elementaddress is not supported by this server, TBX_MB_SERVER_ERR_DEVICE_FAILURE otherwise. |
tTbxMbServerWriteHoldingReg
typedef tTbxMbServerResult (* tTbxMbServerWriteHoldingReg)(tTbxMbServer channel,
uint16_t addr,
uint16_t value)
Modbus server callback function for writing a holding register.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
addr |
Element address (0 ..65535 ). |
value |
Value of the holding register. |
Return value |
---|
TBX_MB_SERVER_OK if successful, TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR if the specific data elementaddress is not supported by this server, TBX_MB_SERVER_ERR_DEVICE_FAILURE otherwise. |
tTbxMbServerCustomFunction
typedef uint8_t (* tTbxMbServerCustomFunction)(tTbxMbServer channel,
uint8_t const * rxPdu,
uint8_t * txPdu,
uint8_t * len)
Modbus server callback function for implementing custom function code handling. Thanks to this functionality, the user can support Modbus function codes that are either currently not supported or user defined extensions.
The rxPdu
and txPdu
parameters are pointers to the byte array of the PDU. The first byte (i.e. rxPdu[0]
) contains the function code, followed by its data bytes. Upon calling the callback, the len
parameter contains the length of rxPdu
. When preparing the response, you can write the length of the txPdu
response to len
as well.
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object that triggered the callback. |
rxPdu |
Pointer to a byte array for reading the received PDU. |
txPdu |
Pointer to a byte array for writing the response PDU. |
len |
Pointer to the PDU length, including the function code. |
Return value |
---|
TBX_TRUE if the callback function handled the received function code and prepared a response PDU.TBX_FALSE otherwise. |
Client
tTbxMbClient
typedef void * tTbxMbClient
Handle to a Modbus client channel object, in the format of an opaque pointer.
Transport layer
tTbxMbTp
typedef void * tTbxMbTp
Handle to a Modbus transport layer object, in the format of an opaque pointer.
UART
tTbxMbUartPort
typedef enum
{
TBX_MB_UART_PORT1 = 0U,
TBX_MB_UART_PORT2,
TBX_MB_UART_PORT3,
TBX_MB_UART_PORT4,
TBX_MB_UART_PORT5,
TBX_MB_UART_PORT6,
TBX_MB_UART_PORT7,
TBX_MB_UART_PORT8,
TBX_MB_UART_NUM_PORT
} tTbxMbUartPort
Enumerated type with all supported UART ports.
tTbxMbUartBaudrate
typedef enum
{
TBX_MB_UART_1200BPS = 0U,
TBX_MB_UART_2400BPS,
TBX_MB_UART_4800BPS,
TBX_MB_UART_9600BPS,
TBX_MB_UART_19200BPS,
TBX_MB_UART_38400BPS,
TBX_MB_UART_57600BPS,
TBX_MB_UART_115200BPS,
TBX_MB_UART_NUM_BAUDRATE
} tTbxMbUartBaudrate
Enumerated type with all supported UART baudrates.
tTbxMbUartDatabits
typedef enum
{
TBX_MB_UART_7_DATABITS = 0U,
TBX_MB_UART_8_DATABITS,
TBX_MB_UART_NUM_DATABITS
} tTbxMbUartDatabits
Enumerated type with all supported UART data bits modes.
tTbxMbUartStopbits
typedef enum
{
TBX_MB_UART_1_STOPBITS = 0U,
TBX_MB_UART_2_STOPBITS,
TBX_MB_UART_NUM_STOPBITS
} tTbxMbUartStopbits
Enumerated type with all supported parity modes.
tTbxMbUartParity
typedef enum
{
TBX_MB_ODD_PARITY = 0U,
TBX_MB_EVEN_PARITY,
TBX_MB_NO_PARITY,
TBX_MB_UART_NUM_PARITY
} tTbxMbUartParity
Enumerated type with all supported parity modes.
Functions
Server
TbxMbServerCreate
tTbxMbServer TbxMbServerCreate(tTbxMbTp transport)
Creates a Modbus server channel object and assigns the specified Modbus transport layer to the channel for packet transmission and reception.
This example creates a Modbus RTU server channel object for a node with address 10
:
/* Construct a Modbus RTU transport layer object. */
tTbxMbTp modbusTp = TbxMbRtuCreate(10U, TBX_MB_UART_PORT1, TBX_MB_UART_19200BPS,
TBX_MB_UART_1_STOPBITS, TBX_MB_EVEN_PARITY);
/* Construct a Modbus server object. */
tTbxMbServer modbusServer = TbxMbServerCreate(modbusTp);
Parameter | Description |
---|---|
transport |
Handle to a previously created Modbus transport layer object to assign to the channel. |
Return value |
---|
Handle to the newly created Modbus server channel object if successful, NULL otherwise. |
TbxMbServerFree
void TbxMbServerFree(tTbxMbServer channel)
Releases a Modbus server channel object, previously created with TbxMbServerCreate().
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object to release. |
TbxMbServerSetCallbackReadInput
void TbxMbServerSetCallbackReadInput(tTbxMbServer channel,
tTbxMbServerReadInput callback)
Registers the callback function that this server calls, whenever a client requests the reading of a specific discrete input.
The example connects the state of two digital inputs to the Modbus discrete inputs at addresses 10000
to 10001
:
tTbxMbServerResult AppReadInput(tTbxMbServer channel,
uint16_t addr,
uint8_t * value)
{
tTbxMbServerResult result = TBX_MB_SERVER_OK;
/* Filter on the requested discrete input address. */
switch (addr)
{
case 10000U:
*value = BspDigitalIn(BSP_DIGITAL_IN1);
break;
case 10001U:
*value = BspDigitalIn(BSP_DIGITAL_IN2);
break;
default:
/* Unsupported discrete input address. */
result = TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR;
break;
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for reading the Modbus discrete inputs. */
TbxMbServerSetCallbackReadInput(modbusServer, AppReadInput);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
TbxMbServerSetCallbackReadCoil
void TbxMbServerSetCallbackReadCoil(tTbxMbServer channel,
tTbxMbServerReadCoil callback)
Registers the callback function that this server calls, whenever a client requests the reading of a specific coil.
The example assumes the application stores the state of two coils in an array with name appCoils[]
. Whenever a client requests the reading of the Modbus coils at addresses 0
to 1
, the currently stored values in the appCoils[]
array are returned:
uint8_t appCoils[2] = { TBX_ON, TBX_OFF };
tTbxMbServerResult AppReadCoil(tTbxMbServer channel,
uint16_t addr,
uint8_t * value)
{
tTbxMbServerResult result = TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR;
/* Supported coil address? */
if (addr <= 1U)
{
/* Store the current coil state. */
*value = appCoils[addr];
result = TBX_MB_SERVER_OK;
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for reading the Modbus coils. */
TbxMbServerSetCallbackReadCoil(modbusServer, AppReadCoil);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
TbxMbServerSetCallbackWriteCoil
void TbxMbServerSetCallbackWriteCoil(tTbxMbServer channel,
tTbxMbServerWriteCoil callback)
Registers the callback function that this server calls, whenever a client requests the writing of a specific coil.
The example connects the Modbus coil addresses 0
to 1
to the state of two digital outputs:
tTbxMbServerResult AppWriteCoil(tTbxMbServer channel,
uint16_t addr,
uint8_t value)
{
tTbxMbServerResult result = TBX_MB_SERVER_OK;
/* Filter on the requested coil address. */
switch (addr)
{
case 0U:
BspDigitalOut(BSP_DIGITAL_OUT1, value);
break;
case 1U:
BspDigitalOut(BSP_DIGITAL_OUT2, value);
break;
default:
/* Unsupported coil address. */
result = TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR;
break;
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for writing the Modbus coils. */
TbxMbServerSetCallbackWriteCoil(modbusServer, AppWriteCoil);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
TbxMbServerSetCallbackReadInputReg
void TbxMbServerSetCallbackReadInputReg(tTbxMbServer channel,
tTbxMbServerReadInputReg callback)
Registers the callback function that this server calls, whenever a client requests the reading of a specific input register.
The example connects the state of two analog inputs to the Modbus input registers at addresses 30000
to 30001
:
tTbxMbServerResult AppReadInputReg(tTbxMbServer channel,
uint16_t addr,
uint16_t * value)
{
tTbxMbServerResult result = TBX_MB_SERVER_OK;
/* Filter on the requested input register address. */
switch (addr)
{
case 30000U:
*value = BspAnalogIn(BSP_ANALOG_IN1);
break;
case 30001U:
*value = BspAnalogIn(BSP_ANALOG_IN2);
break;
default:
/* Unsupported input register address. */
result = TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR;
break;
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for reading the Modbus input registers. */
TbxMbServerSetCallbackReadInputReg(modbusServer, AppReadInputReg);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
TbxMbServerSetCallbackReadHoldingReg
void TbxMbServerSetCallbackReadHoldingReg(tTbxMbServer channel,
tTbxMbServerReadHoldingReg callback)
Registers the callback function that this server calls, whenever a client requests the reading of a specific holding register.
The example assumes the application stores the state of two holding registers in an array with name appHoldingRegs[]
. Whenever a client requests the reading of the Modbus holding registers at addresses 40000
to 40001
, the currently stored values in the appHoldingRegs[]
array are returned:
uint16_t appHoldingRegs[2] = { 1234, 5678 };
tTbxMbServerResult AppReadHoldingReg(tTbxMbServer channel,
uint16_t addr,
uint16_t * value)
{
tTbxMbServerResult result = TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR;
/* Supported holding register address? */
if ( (addr >= 40000) && (addr <= 40001U) )
{
/* Store the holding register state. */
*value = appHoldingReg[addr - 40000U];
result = TBX_MB_SERVER_OK;
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for reading the Modbus holding registers. */
TbxMbServerSetCallbackReadHoldingReg(modbusServer, AppReadHoldingReg);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
TbxMbServerSetCallbackWriteHoldingReg
void TbxMbServerSetCallbackWriteHoldingReg(tTbxMbServer channel,
tTbxMbServerWriteHoldingReg callback)
Registers the callback function that this server calls, whenever a client requests the writing of a specific holding register.
The example connects the Modbus holding registers addresses 40000
to 40001
to two 8-bit PWM output signals:
tTbxMbServerResult AppWriteHoldingReg(tTbxMbServer channel,
uint16_t addr,
uint16_t value)
{
tTbxMbServerResult result = TBX_MB_SERVER_OK;
/* Filter on the requested holding register address. */
switch (addr)
{
case 40000U:
/* PWM supports 8-bit duty cycle. */
if (value <= 255U)
{
BspPwmOut(BSP_PWM_OUT1, (uint8_t)value);
}
else
{
result = TBX_MB_SERVER_ERR_DEVICE_FAILURE;
}
break;
case 40001U:
/* PWM supports 8-bit duty cycle. */
if (value <= 255U)
{
BspPwmOut(BSP_PWM_OUT2, (uint8_t)value);
}
else
{
result = TBX_MB_SERVER_ERR_DEVICE_FAILURE;
}
break;
default:
/* Unsupported holding register address. */
result = TBX_MB_SERVER_ERR_ILLEGAL_DATA_ADDR;
break;
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for writing the Modbus holding registers. */
TbxMbServerSetCallbackWriteHoldingReg(modbusServer, AppWriteHoldingReg);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
TbxMbServerSetCallbackCustomFunction
void TbxMbServerSetCallbackCustomFunction (tTbxMbServer channel,
tTbxMbServerCustomFunction callback)
Registers the callback function that this server calls, whenever it received a PDU containing a function code not currently supported. With the aid of this callback function the user can implement support for new function codes.
The example shows how to add support for function code 17 (Report Server ID). It's the counter-part to the example for TbxMbClientCustomFunction(). According to the Modbus protocol, the response to the Report Server ID request is device specific. The device implementation decides the number of bytes for the Server ID and if additional data is added to the response. The following code snippet implements support for Report Server ID, where the actual server ID is 16-bits and the response contains no additional data:
uint8_t AppReportServerIdCallback(tTbxMbServer channel,
uint8_t const * rxPdu,
uint8_t * txPdu,
uint8_t * len)
{
uint8_t result = TBX_FALSE;
/* Function code 17 - Report Server ID? */
if (rxPdu[0] == 17U)
{
/* Check the expected request length. */
if (*len == 1U)
{
/* Prepare the response. */
txPdu[0] = 17U; /* Function code. */
txPdu[1] = 3U; /* Byte count. */
TbxMbCommonStoreUInt16BE(0x1234U, &txPdu[2]); /* server ID. */
txPdu[4] = 0xFFU; /* Run indicator status = ON. */
*len = 5U;
/* Function code handled. */
result = TBX_TRUE;
}
}
/* Give the result back to the caller. */
return result;
}
/* Set the callback for handling custom function codes. */
TbxMbServerSetCallbackCustomFunction(modbusServer, AppReportServerIdCallback);
Parameter | Description |
---|---|
channel |
Handle to the Modbus server channel object. |
callback |
Pointer to the callback function. |
Client
TbxMbClientCreate
tTbxMbClient TbxMbClientCreate(tTbxMbTp transport,
uint16_t responseTimeout,
uint16_t turnaroundDelay)
Creates a Modbus client channel object and assigns the specified Modbus transport layer to the channel for packet transmission and reception.
This example creates a Modbus RTU client channel object. Note the the nodeAddr
parameter of function TbxMbRtuCreate() is not applicable when used on a client and should simply be set to a value of 0
:
/* Construct a Modbus RTU transport layer object. */
tTbxMbTp modbusTp = TbxMbRtuCreate(0U, TBX_MB_UART_PORT1, TBX_MB_UART_19200BPS,
TBX_MB_UART_1_STOPBITS, TBX_MB_EVEN_PARITY);
/* Construct a Modbus client object. */
tTbxMbClient modbusClient = TbxMbClientCreate(modbusTp, 1000U, 100U);
Parameter | Description |
---|---|
transport |
Handle to a previously created Modbus transport layer object to assign to the channel. |
responseTimeout |
Maximum time in milliseconds to wait for a response from the Modbus server, after sending a PDU. |
turnaroundDelay |
Delay time in milliseconds after sending a broadcast PDU to give all recipients sufficient time to process the PDU. |
Return value |
---|
Handle to the newly created Modbus client channel object if successful, NULL otherwise. |
TbxMbClientFree
void TbxMbClientFree(tTbxMbClient channel)
Releases a Modbus client channel object, previously created with TbxMbClientCreate().
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel object to release. |
TbxMbClientReadCoils
uint8_t TbxMbClientReadCoils(tTbxMbClient channel,
uint8_t node,
uint16_t addr,
uint16_t num,
uint8_t * coils)
Reads the coil(s) from the server with the specified node address.
The example reads the state of two coils at Modbus addresses 0
to 1
, from a Modbus server with node address 10
:
uint8_t coils[2] = { 0 };
TbxMbClientReadCoils(modbusClient, 10U, 0U, 2U, coils);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
addr |
Starting element address (0..65535) in the Modbus data table for the coil read operation. |
num |
Number of elements to read from the coils data table. Range can be 1 ..2000 . |
coils |
Pointer to array with TBX_ON / TBX_OFF values where the coil state will be written to. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientReadInputs
uint8_t TbxMbClientReadInputs(tTbxMbClient channel,
uint8_t node,
uint16_t addr,
uint16_t num,
uint8_t * inputs)
Reads the discrete input(s) from the server with the specified node address.
The example reads the state of two discrete inputs at Modbus addresses 10000
to 10001
, from a Modbus server with node address 10
:
uint8_t inputs[2] = { 0 };
TbxMbClientReadInputs(modbusClient, 10U, 10000U, 2U, inputs);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
addr |
Starting element address (0..65535) in the Modbus data table for the discrete input read operation. |
num |
Number of elements to read from the discrete inputs data table. Range can be 1 ..2000 . |
inputs |
Pointer to array with TBX_ON / TBX_OFF values where the discrete input state will bewritten to. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientReadInputRegs
uint8_t TbxMbClientReadInputRegs(tTbxMbClient channel,
uint8_t node,
uint16_t addr,
uint8_t num,
uint16_t * inputRegs)
Reads the input register(s) from the server with the specified node address.
The example reads two input registers at Modbus addresses 30000
to 30001
, from a Modbus server with node address 10
:
uint16_t inputRegs[2] = { 0 };
TbxMbClientReadInputRegs(modbusClient, 10U, 30000U, 2U, inputRegs);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
addr |
Starting element address (0..65535) in the Modbus data table for the input register read operation. |
num |
Number of elements to read from the input registers data table. Range can be 1 ..125 . |
inputRegs |
Pointer to array where the input register values will be written to. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientReadHoldingRegs
uint8_t TbxMbClientReadHoldingRegs(tTbxMbClient channel,
uint8_t node,
uint16_t addr,
uint8_t num,
uint16_t * holdingRegs)
Reads the holding register(s) from the server with the specified node address.
The example reads two holding registers at Modbus addresses 40000
to 40001
, from a Modbus server with node address 10
:
uint16_t holdingRegs[2] = { 0 };
TbxMbClientReadHoldingRegs(modbusClient, 10U, 40000U, 2U, holdingRegs);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
addr |
Starting element address (0..65535) in the Modbus data table for the holding register read operation. |
num |
Number of elements to read from the holding registers data table. Range can be1 ..125 . |
holdingRegs |
Pointer to array where the holding register values will be written to. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientWriteCoils
uint8_t TbxMbClientWriteCoils(tTbxMbClient channel,
uint8_t node,
uint16_t addr,
uint16_t num,
uint8_t const * coils)
Writes the coil(s) to the server with the specified node address.
The example writes the state of two coils at Modbus addresses 0
to 1
, to a Modbus server with node address 10
:
uint8_t coils[2] = { TBX_OFF, TBX_OFF };
TbxMbClientWriteCoils(modbusClient, 10U, 0U, 2U, coils);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
addr |
Starting element address (0..65535) in the Modbus data table for the coil write operation. |
num |
Number of elements to write to the coils data table. Range can be 1 ..1968 . |
coils |
Pointer to array with the desired TBX_ON / TBX_OFF coil values. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientWriteHoldingRegs
uint8_t TbxMbClientWriteHoldingRegs(tTbxMbClient channel,
uint8_t node,
uint16_t addr,
uint8_t num,
uint16_t const * holdingRegs)
Writes the holding register(s) to the server with the specified node address.
The example writes two holding registers at Modbus addresses 40000
to 40001
, to a Modbus server with node address 10
:
uint16_t holdingRegs[2] = { 63U, 127U };
TbxMbClientWriteHoldingRegs(modbusClient, 10U, 40000U, 2U, holdingRegs);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
addr |
Starting element address (0..65535) in the Modbus data table for the holding register write operation. |
num |
Number of elements to write to the holding registers data table. Range can be1 ..123 . |
holdingRegs |
Pointer to array with the desired holding register values. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientDiagnostics
uint8_t TbxMbClientDiagnostics(tTbxMbClient channel,
uint8_t node,
uint16_t subcode,
uint16_t * count)
Perform diagnostic operation on the server for checking the communication system.
The example obtains the number of packets with a correct CRC, received by a Modbus server with node address 10
:
uint16_t count = 0U;
TbxMbClientDiagnostics(modbusClient, 10U, TBX_MB_DIAG_SC_SERVER_MESSAGE_COUNT, &count);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
subcode |
Sub-function code for specifying the diagnostic operation to perform. Currently supported values: - TBX_MB_DIAG_SC_QUERY_DATA - TBX_MB_DIAG_SC_CLEAR_COUNTERS - TBX_MB_DIAG_SC_BUS_MESSAGE_COUNT - TBX_MB_DIAG_SC_BUS_COMM_ERROR_COUNT - TBX_MB_DIAG_SC_BUS_EXCEPTION_ERROR_COUNT - TBX_MB_DIAG_SC_SERVER_MESSAGE_COUNT - TBX_MB_DIAG_SC_SERVER_NO_RESPONSE_COUNT |
count |
Location where the retrieved count value will be written to. Only applicable for the sub-function codes that end with _COUNT . |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
TbxMbClientCustomFunction
uint8_t TbxMbClientCustomFunction(tTbxMbClient channel,
uint8_t node,
uint8_t const * txPdu,
uint8_t * rxPdu,
uint8_t * len)
Send a custom function code PDU to the server and receive its response PDU. Thanks to this functionality, the user can support Modbus function codes that are either currently not supported or user defined extensions.
The txPdu
and rxPdu
parameters are pointers to the byte array of the PDU. The first byte (i.e. txPdu[0]
) contains the function code, followed by its data bytes. When calling this function, set the len
parameter to the length of the txPdu
. This function updates the len
parameter with the length of the received PDU, which it stores in rxPdu
.
The example shows how to add support for function code 17 (Report Server ID). It's the counter-part to the example for TbxMbServerSetCallbackCustomFunction(). According to the Modbus protocol, the response to the Report Server ID request is device specific. The device implementation decides the number of bytes for the Server ID and if additional data is added to the response. The following code snippet implements support for Report Server ID, where it reads out the 16-bit server ID of a Modbus server with node address 10
:
uint16_t AppReportServerId(tTbxMbClient channel,
uint8_t node)
{
/* static to lower stack load. */
static uint8_t response[TBX_MB_TP_PDU_MAX_LEN];
uint8_t request[1] = { 17U };
uint8_t len = 1U;
uint16_t result = 0U;
/* Transceive function code 17 - Report Server ID. */
if (TbxMbClientCustomFunction(channel, node, request,
response, &len) == TBX_OK)
{
/* Response length as expected? */
if (len == 5U)
{
/* Not an exception response and byte count correct? */
if ((response[0] == 17U) && (response[1] == 3U))
{
/* Read out the received server ID. */
result = TbxMbCommonExtractUInt16BE(&response[2]);
}
}
}
/* Give the result back to the caller. */
return result;
}
/* Read the server ID. */
uint16_t serverId = AppReportServerId(modbusClient, 10U);
Parameter | Description |
---|---|
channel |
Handle to the Modbus client channel for the requested operation. |
node |
The address of the server. This parameter is transport layer dependent. It is needed on RTU/ASCII, yet don't care for TCP unless it is a gateway to an RTU network. If it's don't care, set it to a value of 1 . |
txPdu |
Pointer to a byte array with the PDU to transmit. |
rxPdu |
Pointer to a byte array with the received response PDU. |
len |
Pointer to the PDU length, including the function code. |
Return value |
---|
TBX_OK if successful, TBX_ERROR otherwise. |
Event
TbxMbEventTask
void TbxMbEventTask(void)
Task function that drives the entire Modbus stack. It processes internally generated events. How to call this function depends on the selected operating system abstraction layer (OSAL), which you determine based on the source/osal/tbxmb_XXX.c
source file you compile and link with your firmware.
In a traditional superloop application (tbxmb_superloop.c
), call this function continuously in the infinite program loop:
#include <microtbx.h>
#include <microtbxmodbus.h>
void main(void)
{
/* TODO Initialize the clock, enable peripherals and configure GPIO pins. */
/* TODO Construct a Modbus transport layer object. */
/* TODO Construct a Modbus client or server object. */
/* Enter the program's infinite loop. */
for(;;)
{
/* Continuously call the Modbus stack event task function. */
TbxMbEventTask();
}
}
When using an RTOS (e.g. tbxmb_freertos.c
), create a new task during application initialization and call this function from this task's infinite loop:
#include <microtbx.h>
#include <microtbxmodbus.h>
#include "FreeRTOS.h"
#include "task.h"
void AppModbusTask(void * pvParameters);
void main(void)
{
/* TODO Initialize the clock, enable peripherals and configure GPIO pins. */
/* TODO Construct a Modbus transport layer object. */
/* TODO Construct a Modbus client or server object. */
/* Create the Modbus task. */
xTaskCreate(AppModbusTask, "ModbusTask", configMINIMAL_STACK_SIZE, NULL, 4U, NULL);
/* Start the RTOS scheduler. Note that this function does not return. */
vTaskStartScheduler();
}
void AppModbusTask(void * pvParameters)
{
/* Enter infinite task loop. */
for (;;)
{
/* Continuously call the Modbus stack event task function. */
TbxMbEventTask();
}
}
There is one exception: When using a traditional super application in combination with just a Modbus client. In this case you can omit the call to this task function. With this combination, the communication with a Modbus server happens in a blocking manner and the event task is automatically called internally, while blocking. Convenient and easy, but not optimal from a run-time performance. For this reason it is recommended to use an RTOS in combination with a Modbus client.
Common
TbxMbCommonExtractUInt16BE
uint16_t TbxMbCommonExtractUInt16BE(uint8_t const * data)
Helper function to extract an unsigned 16-bit value from the data of a Modbus packet, where 16-bit values are always stored in the big endian format.
Parameter | Description |
---|---|
data |
Pointer to the byte array that holds the two bytes to extract, stored in the big endian format. |
Return value |
---|
The 16-bit unsigned integer value. |
TbxMbCommonStoreUInt16BE
void TbxMbCommonStoreUInt16BE(uint16_t value,
uint8_t * data)
Helper function to store an unsigned 16-bit value in the data of a Modbus packet, where 16-bit values are always stored in the big endian format.
Parameter | Description |
---|---|
value |
The unsigned 16-bit value to store. |
data |
Pointer to the byte array where to store the value in the big endian format. |
RTU
TbxMbRtuCreate
tTbxMbTp TbxMbRtuCreate(uint8_t nodeAddr,
tTbxMbUartPort port,
tTbxMbUartBaudrate baudrate,
tTbxMbUartStopbits stopbits,
tTbxMbUartParity parity)
Creates a Modbus RTU transport layer object, which can later on be linked to a Modbus client or server channel.
Example for the following communication settings:
- First serial port on the board.
- Baudrate 19200 bits/second.
- 8 data-bits (default and fixed for an RTU transport layer).
- even parity.
- 1 stop-bit.
- Node address 10.
tTbxMbTp modbusTp = TbxMbRtuCreate(10U, TBX_MB_UART_PORT1, TBX_MB_UART_19200BPS,
TBX_MB_UART_1_STOPBITS, TBX_MB_EVEN_PARITY);
Parameter | Description |
---|---|
nodeAddr |
The address of the node. Can be in the range 1 ..247 for a server node. Set it to 0 fora client. |
port |
The serial port to use. The actual meaning of the serial port is hardware dependent. It typically maps to the UART peripheral number. E.g. TBX_MB_UART_PORT1 = USART1 onan STM32. |
baudrate |
The desired communication speed. |
stopbits |
Number of stop bits at the end of a character. |
parity |
Parity bit type to use. |
Return value |
---|
Handle to the newly created RTU transport layer object if successful, NULL otherwise. |
TbxMbRtuFree
void TbxMbRtuFree(tTbxMbTp transport)
Releases a Modbus RTU transport layer object, previously created with TbxMbRtuCreate().
Parameter | Description |
---|---|
transport |
Handle to RTU transport layer object to release. |
UART
TbxMbUartTransmitComplete
void TbxMbUartTransmitComplete(tTbxMbUartPort port)
Event function to signal to the UART module that the entire transfer, initiated by TbxMbPortUartTransmit
, completed. This function should be called by the hardware specific UART port (located in tbxmb_port.c
) at TX interrupt level.
Parameter | Description |
---|---|
port |
The serial port that the transfer completed on. |
TbxMbUartDataReceived
void TbxMbUartDataReceived(tTbxMbUartPort port,
uint8_t const * data,
uint8_t len)
Event function to signal the reception of new data to the UART module. This function should be called by the hardware specific UART port (located in tbxmb_port.c
) at RX interrupt level.
Parameter | Description |
---|---|
port |
The serial port that the transfer completed on. |
data |
Byte array with newly received data. |
len |
Number of newly received bytes. |