ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
modbus_master.h File Reference

Modbus TCP master codec + register scanner (PROTOCORE_ENABLE_MODBUS_MASTER). More...

#include "protocore_config.h"

Go to the source code of this file.

Classes

struct  ModbusMasterNs
 Dispatch table. Addressed by offset, so the layout is asserted below. More...
 

Functions

 PROTOCORE_NS_LAYOUT (ModbusMasterNs, build_read, parse_response, build_read_bits, parse_read_bits_response, build_write_single_coil, build_write_multiple_coils, build_write_single, build_write_multiple, parse_write_response, build_mask_write, build_read_write_multiple, parse_mask_write_response)
 
size_t protocore_modbus_master_build_read (uint8_t *work, uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out, size_t cap)
 Build a read-request ADU (FC 0x03 holding or 0x04 input registers).
 
int protocore_modbus_master_parse_response (uint8_t *work, const uint8_t *adu, size_t len, uint16_t *regs_out, size_t max_regs, uint8_t *exception_out)
 Parse a read-response ADU into register values.
 
size_t protocore_modbus_master_build_read_bits (uint8_t *work, uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out, size_t cap)
 Build a read-bits request ADU (FC 0x01 coils or 0x02 discrete .
 
int protocore_modbus_master_parse_read_bits_response (uint8_t *work, const uint8_t *adu, size_t len, uint16_t count, uint8_t *bits_out, size_t max_bits, uint8_t *exception_out)
 Parse a read-bits response ADU (FC 0x01 / 0x02) into one byte (0/1).
 
size_t protocore_modbus_master_build_write_single_coil (uint8_t *work, uint16_t txid, uint8_t unit, uint16_t addr, proto_bool on, uint8_t *out, size_t cap)
 Build a Write Single Coil request ADU (FC 0x05).
 
size_t protocore_modbus_master_build_write_multiple_coils (uint8_t *work, uint16_t txid, uint8_t unit, uint16_t start, const uint8_t *bits, uint16_t count, uint8_t *out, size_t cap)
 Build a Write Multiple Coils request ADU (FC 0x0F).
 
size_t protocore_modbus_master_build_write_single (uint8_t *work, uint16_t txid, uint8_t unit, uint16_t addr, uint16_t value, uint8_t *out, size_t cap)
 Build a Write Single Register request ADU (FC 0x06).
 
size_t protocore_modbus_master_build_write_multiple (uint8_t *work, uint16_t txid, uint8_t unit, uint16_t start, const uint16_t *values, uint16_t count, uint8_t *out, size_t cap)
 Build a Write Multiple Registers request ADU (FC 0x10).
 
int protocore_modbus_master_parse_write_response (uint8_t *work, const uint8_t *adu, size_t len, uint16_t *addr_out, uint8_t *exception_out)
 Parse a write-response ADU (FC 0x05, 0x06, 0x0F, or 0x10). A normal .
 
size_t protocore_modbus_master_build_mask_write (uint8_t *work, uint16_t txid, uint8_t unit, uint16_t addr, uint16_t and_mask, uint16_t or_mask, uint8_t *out, size_t cap)
 Build a Mask Write Register request ADU (FC 0x16). The slave .
 
size_t protocore_modbus_master_build_read_write_multiple (uint8_t *work, uint16_t txid, uint8_t unit, uint16_t read_start, uint16_t read_count, uint16_t write_start, const uint16_t *values, uint16_t write_count, uint8_t *out, size_t cap)
 Build a Read/Write Multiple Registers request ADU (FC 0x17): write.
 
int protocore_modbus_master_parse_mask_write_response (uint8_t *work, const uint8_t *adu, size_t len, uint16_t *addr_out, uint16_t *and_out, uint16_t *or_out, uint8_t *exception_out)
 Parse a Mask Write Register response (FC 0x16), which echoes the .
 

Variables

PROTOCORE_NS ModbusMasterNs ModbusMaster PROTOCORE_UNUSED
 Module namespace.
 

Detailed Description

Modbus TCP master codec + register scanner (PROTOCORE_ENABLE_MODBUS_MASTER).

The master/client side of Modbus: build a read-request ADU (MBAP header + PDU) and parse the slave's response into register values, so an application can poll or auto-discover a slave's registers. Pure - no sockets, no heap - so it is host-tested as a full round-trip against the slave codec (Modbus.process_adu). The app supplies the transport (send the ADU, receive the reply).

Auto-discovery pattern: walk the address space one read at a time; a register exists where the response parses without a Modbus exception.

work is bytes the CALLER holds. This module reads none of them: it carries nothing between calls, so there is no state to keep and nothing to wipe. The parameter is there so a caller drives every namespace the same way.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file modbus_master.h.

Function Documentation

◆ PROTOCORE_NS_LAYOUT()

PROTOCORE_NS_LAYOUT ( ModbusMasterNs  ,
build_read  ,
parse_response  ,
build_read_bits  ,
parse_read_bits_response  ,
build_write_single_coil  ,
build_write_multiple_coils  ,
build_write_single  ,
build_write_multiple  ,
parse_write_response  ,
build_mask_write  ,
build_read_write_multiple  ,
parse_mask_write_response   
)

◆ protocore_modbus_master_build_read()

size_t protocore_modbus_master_build_read ( uint8_t *  work,
uint8_t  fc,
uint16_t  txid,
uint8_t  unit,
uint16_t  start,
uint16_t  count,
uint8_t *  out,
size_t  cap 
)

Build a read-request ADU (FC 0x03 holding or 0x04 input registers).

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
fcMODBUS_FC_READ_HOLDING_REGS (0x03) or MODBUS_FC_READ_INPUT_REGS (0x04)
txidtransaction id echoed by the slave (caller's correlation token)
unitunit / slave id
startfirst register address
countnumber of registers (1..125)
outdestination buffer
capdestination capacity (>= 12)
Returns
The size_t.

◆ protocore_modbus_master_parse_response()

int protocore_modbus_master_parse_response ( uint8_t *  work,
const uint8_t *  adu,
size_t  len,
uint16_t *  regs_out,
size_t  max_regs,
uint8_t *  exception_out 
)

Parse a read-response ADU into register values.

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
aduresponse bytes (MBAP + PDU)
lenresponse length
regs_outdestination for parsed 16-bit register values
max_regscapacity of regs_out
exception_outset to the Modbus exception code if the slave returned one (then the function returns 0
Returns
The int.

◆ protocore_modbus_master_build_read_bits()

size_t protocore_modbus_master_build_read_bits ( uint8_t *  work,
uint8_t  fc,
uint16_t  txid,
uint8_t  unit,
uint16_t  start,
uint16_t  count,
uint8_t *  out,
size_t  cap 
)

Build a read-bits request ADU (FC 0x01 coils or 0x02 discrete .

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
fcMODBUS_FC_READ_COILS (0x01) or ::MODBUS_FC_READ_DISCRETE_INPUTS (0x02)
txidtransaction id echoed by the slave
unitunit / slave id
startfirst bit address
countnumber of bits (1..2000)
outdestination buffer
capdestination capacity (>= 12)
Returns
The size_t.

◆ protocore_modbus_master_parse_read_bits_response()

int protocore_modbus_master_parse_read_bits_response ( uint8_t *  work,
const uint8_t *  adu,
size_t  len,
uint16_t  count,
uint8_t *  bits_out,
size_t  max_bits,
uint8_t *  exception_out 
)

Parse a read-bits response ADU (FC 0x01 / 0x02) into one byte (0/1).

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
aduAdu
lenLen
countthe number of bits requested (1..2000)
bits_outdestination for count unpacked bits (nullable to just validate)
max_bitscapacity of bits_out
exception_outset to the Modbus exception code if the slave returned one (then 0 is returned)
Returns
The int.

◆ protocore_modbus_master_build_write_single_coil()

size_t protocore_modbus_master_build_write_single_coil ( uint8_t *  work,
uint16_t  txid,
uint8_t  unit,
uint16_t  addr,
proto_bool  on,
uint8_t *  out,
size_t  cap 
)

Build a Write Single Coil request ADU (FC 0x05).

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
txidTxid
unitUnit
addrAddr
onthe coil value; encoded on the wire as 0xFF00 (on) or 0x0000 (off) per the Modbus spec
outOut
capdestination capacity (>= 12)
Returns
The size_t.

◆ protocore_modbus_master_build_write_multiple_coils()

size_t protocore_modbus_master_build_write_multiple_coils ( uint8_t *  work,
uint16_t  txid,
uint8_t  unit,
uint16_t  start,
const uint8_t *  bits,
uint16_t  count,
uint8_t *  out,
size_t  cap 
)

Build a Write Multiple Coils request ADU (FC 0x0F).

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
txidTxid
unitUnit
startStart
bitsone byte (0/1) per coil to write; packed LSB-first into the wire bytes
countnumber of coils (1..1968)
outOut
capdestination capacity (>= 14 + ceil(count/8))
Returns
The size_t.

◆ protocore_modbus_master_build_write_single()

size_t protocore_modbus_master_build_write_single ( uint8_t *  work,
uint16_t  txid,
uint8_t  unit,
uint16_t  addr,
uint16_t  value,
uint8_t *  out,
size_t  cap 
)

Build a Write Single Register request ADU (FC 0x06).

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
txidtransaction id echoed by the slave
unitunit / slave id
addrregister address
value16-bit value to write
outdestination buffer
capdestination capacity (>= 12)
Returns
The size_t.

◆ protocore_modbus_master_build_write_multiple()

size_t protocore_modbus_master_build_write_multiple ( uint8_t *  work,
uint16_t  txid,
uint8_t  unit,
uint16_t  start,
const uint16_t *  values,
uint16_t  count,
uint8_t *  out,
size_t  cap 
)

Build a Write Multiple Registers request ADU (FC 0x10).

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
txidtransaction id echoed by the slave
unitunit / slave id
startfirst register address
valuesthe count register values
countnumber of registers (1..123)
outdestination buffer
capdestination capacity (>= 13 + 2*count)
Returns
The size_t.

◆ protocore_modbus_master_parse_write_response()

int protocore_modbus_master_parse_write_response ( uint8_t *  work,
const uint8_t *  adu,
size_t  len,
uint16_t *  addr_out,
uint8_t *  exception_out 
)

Parse a write-response ADU (FC 0x05, 0x06, 0x0F, or 0x10). A normal .

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
aduresponse bytes (MBAP + PDU)
lenresponse length
addr_outset to the echoed address / start (nullable)
exception_outset to the Modbus exception code if the slave returned one (then 0 is returned)
Returns
The int.

◆ protocore_modbus_master_build_mask_write()

size_t protocore_modbus_master_build_mask_write ( uint8_t *  work,
uint16_t  txid,
uint8_t  unit,
uint16_t  addr,
uint16_t  and_mask,
uint16_t  or_mask,
uint8_t *  out,
size_t  cap 
)

Build a Mask Write Register request ADU (FC 0x16). The slave .

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
txidTxid
unitUnit
addrAddr
and_maskAnd mask
or_maskOr mask
outOut
capdestination capacity (>= 14)
Returns
The size_t.

◆ protocore_modbus_master_build_read_write_multiple()

size_t protocore_modbus_master_build_read_write_multiple ( uint8_t *  work,
uint16_t  txid,
uint8_t  unit,
uint16_t  read_start,
uint16_t  read_count,
uint16_t  write_start,
const uint16_t *  values,
uint16_t  write_count,
uint8_t *  out,
size_t  cap 
)

Build a Read/Write Multiple Registers request ADU (FC 0x17): write.

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
txidTxid
unitUnit
read_start/ read_count the registers to read back (1..125)
read_countRead count
write_start/ write_count the registers to write (1..121); values holds write_count words
valuesValues
write_countWrite count
outOut
capdestination capacity (>= 17 + 2*write_count)
Returns
The size_t.

◆ protocore_modbus_master_parse_mask_write_response()

int protocore_modbus_master_parse_mask_write_response ( uint8_t *  work,
const uint8_t *  adu,
size_t  len,
uint16_t *  addr_out,
uint16_t *  and_out,
uint16_t *  or_out,
uint8_t *  exception_out 
)

Parse a Mask Write Register response (FC 0x16), which echoes the .

Parameters
workPROTOCORE_MODBUS_MASTER_BORROW bytes the caller took. Not held past the call.
aduAdu
lenLen
addr_out/ and_out / or_out receive the echoed fields (each nullable)
and_outAnd out
or_outOr out
exception_outset to the Modbus exception code if the slave returned one
Returns
The int.

Variable Documentation

◆ PROTOCORE_UNUSED

PROTOCORE_NS ModbusMasterNs ModbusMaster PROTOCORE_UNUSED
Initial value:
= {
int protocore_modbus_master_parse_mask_write_response(uint8_t *work, const uint8_t *adu, size_t len, uint16_t *addr_out, uint16_t *and_out, uint16_t *or_out, uint8_t *exception_out)
Parse a Mask Write Register response (FC 0x16), which echoes the .
size_t protocore_modbus_master_build_write_single_coil(uint8_t *work, uint16_t txid, uint8_t unit, uint16_t addr, proto_bool on, uint8_t *out, size_t cap)
Build a Write Single Coil request ADU (FC 0x05).
size_t protocore_modbus_master_build_write_multiple(uint8_t *work, uint16_t txid, uint8_t unit, uint16_t start, const uint16_t *values, uint16_t count, uint8_t *out, size_t cap)
Build a Write Multiple Registers request ADU (FC 0x10).
size_t protocore_modbus_master_build_read(uint8_t *work, uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out, size_t cap)
Build a read-request ADU (FC 0x03 holding or 0x04 input registers).
int protocore_modbus_master_parse_write_response(uint8_t *work, const uint8_t *adu, size_t len, uint16_t *addr_out, uint8_t *exception_out)
Parse a write-response ADU (FC 0x05, 0x06, 0x0F, or 0x10). A normal .
size_t protocore_modbus_master_build_mask_write(uint8_t *work, uint16_t txid, uint8_t unit, uint16_t addr, uint16_t and_mask, uint16_t or_mask, uint8_t *out, size_t cap)
Build a Mask Write Register request ADU (FC 0x16). The slave .
size_t protocore_modbus_master_build_read_write_multiple(uint8_t *work, uint16_t txid, uint8_t unit, uint16_t read_start, uint16_t read_count, uint16_t write_start, const uint16_t *values, uint16_t write_count, uint8_t *out, size_t cap)
Build a Read/Write Multiple Registers request ADU (FC 0x17): write.
size_t protocore_modbus_master_build_write_multiple_coils(uint8_t *work, uint16_t txid, uint8_t unit, uint16_t start, const uint8_t *bits, uint16_t count, uint8_t *out, size_t cap)
Build a Write Multiple Coils request ADU (FC 0x0F).
size_t protocore_modbus_master_build_read_bits(uint8_t *work, uint8_t fc, uint16_t txid, uint8_t unit, uint16_t start, uint16_t count, uint8_t *out, size_t cap)
Build a read-bits request ADU (FC 0x01 coils or 0x02 discrete .
int protocore_modbus_master_parse_read_bits_response(uint8_t *work, const uint8_t *adu, size_t len, uint16_t count, uint8_t *bits_out, size_t max_bits, uint8_t *exception_out)
Parse a read-bits response ADU (FC 0x01 / 0x02) into one byte (0/1).
int protocore_modbus_master_parse_response(uint8_t *work, const uint8_t *adu, size_t len, uint16_t *regs_out, size_t max_regs, uint8_t *exception_out)
Parse a read-response ADU into register values.
size_t protocore_modbus_master_build_write_single(uint8_t *work, uint16_t txid, uint8_t unit, uint16_t addr, uint16_t value, uint8_t *out, size_t cap)
Build a Write Single Register request ADU (FC 0x06).

Module namespace.

Definition at line 225 of file modbus_master.h.