Skip to content
Start free evaluation

PDU, ADU and function codes

A Modbus message has two layers. The inner PDU (protocol data unit) is the same on every transport; the outer ADU (application data unit) depends on the transport. This page is based on sections 4.1 (protocol description), 5 (function code categories), 6 (function code descriptions) and 7 (exception responses) of the MODBUS Application Protocol Specification V1.1b3.

A PDU is a one-byte function code followed by data, 253 bytes at most.

+------------------+-----------------------------+
| function code 1B | data 0-252B |
+------------------+-----------------------------+

Reading one holding register at address 0 looks like this:

request PDU 03 0000 0001 function 03, start address 0, quantity 1
response PDU 03 02 002A function 03, byte count 2, value 0x002A (42)

Writing 42 to holding register 0 is 06 0000 002A, and the normal response echoes the same five bytes.

PDComm accepts a PDU as a hex string ("0300000001") or a byte array ([3,0,0,0,1]) and returns responses as arrays of decimal bytes ([3,2,0,42]). Never put an MBAP header, a unit address, a CRC or an LRC into a PDU: the transport adds and removes them.

The ADU wraps the PDU with addressing and error checking. The same read request on each transport:

Transport ADU layout Maximum size Bytes of the same request
Modbus TCP 7-byte MBAP header + PDU 260 bytes 00 01 00 00 00 06 01 03 00 00 00 01
RTU 1-byte unit address + PDU + 2-byte CRC 256 bytes 01 03 00 00 00 01 84 0A
ASCII : + hex characters (address, PDU, LRC) + CR LF 513 characters :010300000001FB + CR LF

Section 5 sorts function codes into three categories:

Category Range Meaning
Public Defined codes in 1–64, 73–99 and 111–127 Defined and validated by the Modbus Organization.
User-defined 65–72 and 100–110 Free for a vendor to define, with no interoperability guarantee.
Reserved Some other codes Used by legacy products; don’t use them for new functions.

Values of 128 and above are for exception responses: an exception response carries the request’s function code plus 0x80.

PDComm supports these 19 public function codes. The capabilities command returns the same list in its functions field.

Code (dec / hex) Name Spec Example request PDU PDComm limits
1 / 0x01 Read Coils §6.1 0100000008 Quantity 1–2000
2 / 0x02 Read Discrete Inputs §6.2 0200000008 Quantity 1–2000
3 / 0x03 Read Holding Registers §6.3 0300000001 Quantity 1–125
4 / 0x04 Read Input Registers §6.4 0400000001 Quantity 1–125
5 / 0x05 Write Single Coil §6.5 050000FF00 Value FF00 (on) or 0000 (off)
6 / 0x06 Write Single Register §6.6 060000002A
7 / 0x07 Read Exception Status §6.7 07 Serial line only
8 / 0x08 Diagnostics §6.8 0800001234 Serial line only; sub-functions below
11 / 0x0B Get Comm Event Counter §6.9 0B Serial line only
12 / 0x0C Get Comm Event Log §6.10 0C Serial line only; last 64 events
15 / 0x0F Write Multiple Coils §6.11 0F0000000801A5 Quantity 1–1968
16 / 0x10 Write Multiple Registers §6.12 1000000001020009 Quantity 1–123
17 / 0x11 Report Server ID §6.13 11 Serial line only
20 / 0x14 Read File Record §6.14 140706000100000001 File number 1 or higher, records 0–9999
21 / 0x15 Write File Record §6.15 1509060001000000010009 Checks every record range before writing any
22 / 0x16 Mask Write Register §6.16 160000FF000055 Result = (current AND And_Mask) OR (Or_Mask AND NOT And_Mask)
23 / 0x17 Read/Write Multiple Registers §6.17 170000000100000001020009 Read 1–125, write 1–121; writes before reading
24 / 0x18 Read FIFO Queue §6.18 180000 Up to 31 values; reading doesn’t empty the queue
43 / 0x2B Read Device Identification (MEI 14) §6.21 2B0E0100 Read codes 1 (basic) to 4 (individual)
  • Serial line only functions are the ones the specification restricts to serial lines. A PDComm TCP server answers them with exception 01, and a PDComm TCP client refuses to send them and returns the Unsupported error.
  • MEI 13 (CANopen General Reference, §6.20) is an opaque extension interface. The default server answers it with exception 01.
  • User-defined codes also get exception 01 from the default server.

A diagnostics request carries a two-byte sub-function code and two bytes of data. PDComm supports these 15 sub-functions:

Sub-function (dec / hex) Name Request PDU Response
0 / 0x0000 Return Query Data 0800001234 Echoes the data.
1 / 0x0001 Restart Communications Option 0800010000 Responds, then restarts and clears the counters. Data FF00 also clears the event log.
2 / 0x0002 Return Diagnostic Register 0800020000 Diagnostic register value
3 / 0x0003 Change ASCII Input Delimiter 0800030A00 Responds, then changes the ASCII end character.
4 / 0x0004 Force Listen Only Mode 0800040000 No response; enters listen-only mode.
10 / 0x000A Clear Counters and Diagnostic Register 08000A0000 Clears the counters and the diagnostic register.
11 / 0x000B Return Bus Message Count 08000B0000 Messages seen on the bus
12 / 0x000C Return Bus Communication Error Count 08000C0000 CRC and LRC errors
13 / 0x000D Return Bus Exception Error Count 08000D0000 Exception responses sent
14 / 0x000E Return Server Message Count 08000E0000 Messages addressed to this server
15 / 0x000F Return Server No Response Count 08000F0000 Messages left unanswered
16 / 0x0010 Return Server NAK Count 0800100000 NAKs
17 / 0x0011 Return Server Busy Count 0800110000 Busy exceptions
18 / 0x0012 Return Bus Character Overrun Count 0800120000 Character overruns
20 / 0x0014 Clear Overrun Counter and Flag 0800140000 Clears the overrun counter and flag.

A server in listen-only mode answers nothing. The only way out is sub-function 1 (Restart Communications Option), and even that request gets no response.

When a server can’t process a request it sends a two-byte exception response:

request PDU 03 FFFF 0001 read 1 register at address 65535
exception response 83 02 0x03 + 0x80, exception code 02

Section 7 defines these exception codes:

Code Name Meaning
01 Illegal Function The server doesn’t support the function, or doesn’t allow it in its current state.
02 Illegal Data Address The address, or the address plus quantity, doesn’t exist in the server.
03 Illegal Data Value A value or length in the request is invalid.
04 Server Device Failure An unrecoverable error occurred while processing the request.
05 Acknowledge The server accepted a long-running request; poll for the result later.
06 Server Device Busy The server is busy; send the request again later.
08 Memory Parity Error The server found a parity error in file record memory.
0A Gateway Path Unavailable The gateway has no path to the target.
0B Gateway Target Device Failed to Respond The gateway got no response from the target device.

An exception response is a normal Modbus response. In PDComm, a request or execute that receives one succeeds, and its result has "status":"exception". Connection failures, timeouts, invalid JSON and a connect without a license, by contrast, make the call fail: the C API returns PDCOMM_MODBUS_SERVICE_ERROR from pdcomm_modbus_call, and C++ and .NET throw.

{"ok":true,"result":{"response":[131,2],"source":"local","status":"exception"}}

Exception responses lists when a PDComm server sends each one.

PDComm processes the same PDU in two ways, told apart by the result’s source field:

Command source Processing
execute local Runs against the endpoint’s own data model without any I/O. Use it to check server behavior.
request wire A connected client sends the request to the peer and receives the response.

A local result proves nothing about communication. Check a wire result to confirm you actually talked to a device.