Modbus/TCP
All Data is MSB (so, e.g. 0x1234 is encoded as 0x12 0x34 in bytes).
Header
This tis the general Modbus header for all requests and responses
| Offset | Count | Description |
|---|---|---|
| 0x0000 | 2 | Request identifier to reliably connect the response back to the request |
| 0x0002 | 2 | Protocol identifier, 0 for Modbus |
| 0x0004 | 2 | Number of remaining bytes after this |
| 0x0006 | 1 | Unit identifier (0xFF if not used) |
| 0x0007 | 1 | Function code (usually but not in every case) |
Error response
When an error occurs, the 8th bit in the response's function code is set to 1 (so, 128 or 0x80 is added / ORed) and and only an error code is added as data
Functions
Function 1: Read Coils
Function 2: Read Discrete Inputs
Function 3: Read Multiple Holding Registers
Request
| Offset | Count | Description |
|---|---|---|
| 0x0000 | 2 | Request identifier to reliably connect the response back to the request |
| 0x0002 | 2 | Protocol identifier, 0 for Modbus |
| 0x0004 | 2 | Number of remaining bytes after this (here: 6) |
| 0x0006 | 1 | Unit identifier (0xFF if not used) |
| 0x0007 | 1 | Function code (here: 3) |
| 0x0008 | 2 | Start address to read from |
| 0x000A | 2 | Number of words to read |
E.g. request 1, reading 5 words from address 2000:
00 01 00 00 00 06 FF 03 07 D0 00 05
00 01: Request identifier 100 00: Modbus protocol00 06: 6 bytes come after thisFF: Nevermind the unit03: Function code 3 (Read Multiple)07 D0: Start at address 2000 (0x07D0)00 05: Read 5 words
You can post a request to a Modbus server via linux commands ncand xxd:
echo -n -e '\x00\x01\x00\x00\x00\x06\xFF\x03\x07\xD0\x00\x05' | nc -vv -q 0 192.168.0.1 502 | xxd -ps
echo: put the data to send on the pipe-n: Do not terminate with a new-line-e: Unescape the bytes\x00...: The bytes to send in escaped string form
nc: Connect to the server and send the data from the pipe-vv: Print verbose information about the connection-q 0: Terminate the connection after 0 seconds after the data was received192.168.0.1: The Modbus server address502: The port the Modbus service is provided on (default is 502)
xxd: Convert the response to hex data-ps: Output as simple hex without adrress and string repesentation
Response
| Offset | Count | Description |
|---|---|---|
| 0x0000 | 2 | Request identifier (mirrored from the request) |
| 0x0002 | 2 | Protocol identifier, 0 for Modbus |
| 0x0004 | 2 | Number of remaining bytes after this |
| 0x0006 | 1 | Unit identifier (0xFF if not used) |
| 0x0007 | 1 | Function code (here: 3) |
| 0x0008 | 1 | Number of data bytes to follow in this response (maybe to split the response to multiple responses?) |
| 0x0009 | * | The result data of the read, 2 bytes per word |
E.g. from the request above
00 01 00 00 00 0d ff 03 0a 11 11 20 02 30 03 40 04 50 05
00 01: Request identifier 100 00: Modbus protocol00 0d: 13 bytes come after thisff: The unit identifier 255 is returned03: The response is to function code 30a: 10 data bytes following10 01: First word @2000 (0x07D0): 0x1001 = 409720 02: Second word @2001 (0x07D1): 0x2002 = 8194- ...
Error codes:
01: Function code not supported02: Invalid address range03: Invalid number of registers to read (123 max)04: Unable to read registers
Function 4: Read Input Register
Function 5: Write Single Coil
Function 6: Write Single Holding Register
Function 15: Write Multiple Coils
Function 16: Write Multiple Holding Registers
Request
| Offset | Count | Description |
|---|---|---|
| 0x0000 | 2 | Request identifier to reliably connect the response back to the request |
| 0x0002 | 2 | Protocol identifier, 0 for Modbus |
| 0x0004 | 2 | Number of remaining bytes after this (here: 7 + WordCount * 2) |
| 0x0006 | 1 | Unit identifier (0xFF if not used) |
| 0x0007 | 1 | Function code (here: 16 = 0x10) |
| 0x0008 | 2 | Start address to write to |
| 0x000A | 2 | Number of words to write |
| 0x000C | 1 | Number of bytes to follow (WordCount * 2, maybe to split the request into multiple packages?) |
| 0x000E | * | Word data, 2 bytes for each word |
E.g. request 1, reading 5 words from address 2000:
00 01 00 00 00 11 FF 10 07 D0 00 05 0A 11 01 22 02 33 03 44 04 55 05
00 01: Request identifier 100 00: Modbus protocol00 11: 0x11 = 17 bytes come after thisFF: Nevermind the unit10: Function code 16 (Write Multiple)07 D0: Start at address 2000 (0x07D0)00 05: 5 words to write0A: 10 data bytes to follow (2 * 5)11 01: First word @2000 (0x07D0): 0x1101 = 435322 02: Second word @2001 (0x07D1): 0x2202 = 8706- ...
You can post a request to a Modbus server via linux commands ncand xxd:
echo -n -e '\x00\x01\x00\x00\x00\x11\xFF\x10\x07\xD0\x00\x05\x0A\x11\x01\x22\x02\x33\x03\x44\x04\x55\x05' | nc -vv -q 0 192.168.0.1 502 | xxd -ps
echo: put the data to send on the pipe-n: Do not terminate with a new-line-e: Unescape the bytes\x00...: The bytes to send in escaped string form
nc: Connect to the server and send the data from the pipe-vv: Print verbose information about the connection-q 0: Terminate the connection after 0 seconds after the data was received192.168.0.1: The Modbus server address502: The port the Modbus service is provided on (default is 502)
xxd: Convert the response to hex data-ps: Output as simple hex without adrress and string repesentation
Response
| Offset | Count | Description |
|---|---|---|
| 0x0000 | 2 | Request identifier (mirrored from the request) |
| 0x0002 | 2 | Protocol identifier, 0 for Modbus |
| 0x0004 | 2 | Number of remaining bytes after this (here: 6) |
| 0x0006 | 1 | Unit identifier (0xFF if not used) |
| 0x0007 | 1 | Function code (here: 0x11 = 16) |
| 0x0008 | 2 | Address of the first write written |
| 0x000A | 2 | The number of words written |
E.g. from the request above
00 01 00 00 00 06 ff 10 07 d0 00 05
00 01: Request identifier 100 00: Modbus protocol00 0d: 13 bytes come after thisff: The unit identifier 255 is returned10: The response is to function code 1607 d0: Write started at address 0x07D0 = 200000 05: 5 words have been written
Error codes:
01: Function code not supported02: Invalid address range03: Invalid number of registers to write (123 max)04: Unable to write registers