banner
yono

yono

哈喽~欢迎光临
follow
github

Introduction to the Modbus Protocol

Reference Materials#

Each blog site is missing chapters and sentences, with chaotic formatting and occasional errors, so it is not recommended to refer to them.

Here is the information from the Modbus Chinese website

MODBUS Protocol Chinese/English Version Preview and Download | Modbus IoT Cloud Platform

More authoritative is the official documentation

MODBUS Application Protocol 1 1 b

And other official documents can be found here

Modbus Specifications and Implementation Guidelines

Of course, I am not very satisfied with the official documents either. To maintain their ancient design architecture, the introduction of various frame segments is not intuitive, and there are also a few typos.

image

Below is the effective information I have rewritten.

Additionally, there is a library I implemented myself

stbanana/modbusX: modbus protocol support (github.com)

Protocol Features#

Overall Frame Structure#

Message HeaderAddress FieldFunction CodeData FieldCheck Field
RTU1 byte (Slave ID)1 byten bytes variable2 bytes (CRC-MB16 for all other content)
TCP6 bytes
(2 bytes Transaction ID +
2 bytes Protocol Identifier - all 0 +
2 bytes Total Length of Remaining Bytes - including Slave ID)
1 byte (Slave ID)1 byten bytes variable

Regarding the message header, it is classified into the address field in the overall model of the official document, but the actual total length of bytes includes the Slave ID. This is probably because when there was only a serial protocol in the early days, the overall model was already established, and the newly added Modbus TCP could only be messed up for compatibility.

I have directly reclassified it here, which is not standard, but I am happy with it.

Register Attributes#

RW AttributeBit Count
Coils (0x01)Read/Write1 bit
Discrete Input Registers (0x02)Read Only1 bit
Holding Registers (0x03)Read/Write16 bits
Input Registers (0x04)Read Only16 bits

Overall Model#

Use software to abstract a memory structure, with different meaningful data stored at each address, similar to FPGA simulating SRAM. However, not every register address is 16 bits; it can also be 1 bit. The attributes are RO/RW.

RTU Series#

(0x01) Read Coils#

Master Request#

Address FieldFunction CodeStarting AddressCoil CountCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeByte CountCoil StatusCheck Field
1 byte1 byte1 byte (calculating Coil Status byte count)n bytes2 bytes (CRC-MB16)

Example#

Request to read coil data from address 20 to 38, the response address is from low to high, and the final byte is padded with 0 in the high position.

[!NOTE]

The final output status for 38-36 response bytes is padded with five remaining bits (up to the high position).

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x01Function Code0x01
Starting Address High 8 bits0x00Byte Count0x03
Starting Address Low 8 bits0x13Output Status 27-200xCD
Output Count High 8 bits0x00Output Status 35-280x6B
Output Count Low 8 bits0x13Output Status 38-360x05
Check CRC Low 8 bits0xA9Check CRC Low 8 bits0x42
Check CRC High 8 bits0xC8Check CRC High 8 bits0x82

(0x02) Read Discrete Input Registers#

Master Request#

Address FieldFunction CodeStarting AddressDiscrete Input CountCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeByte CountDiscrete Input StatusCheck Field
1 byte1 byte1 byte (calculating Discrete Input Status byte count)n bytes2 bytes (CRC-MB16)

Example#

Request to read discrete input register data from address 197 to 218, the response address is from low to high, and the final byte is padded with 0 in the high position.

[!NOTE]

The final input status for 218-213 response bytes is padded with two remaining bits (up to the high position).

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x02Function Code0x02
Starting Address High 8 bits0x00Byte Count0x03
Starting Address Low 8 bits0xC4Input Status 204-1970xAC
Output Count High 8 bits0x00Input Status 212-2050xDB
Output Count Low 8 bits0x16Input Status 218-2130x35
Check CRC Low 8 bits0xB8Check CRC Low 8 bits0x22
Check CRC High 8 bits0x39Check CRC High 8 bits0x88

(0x03) Read Holding Registers#

Master Request#

Address FieldFunction CodeStarting AddressHolding Register CountCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeByte CountHolding Register StatusCheck Field
1 byte1 byte1 byte (calculating Holding Register Status byte count)n bytes2 bytes (CRC-MB16)

Example#

Request to read holding register data from address 108 to 110

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x03Function Code0x03
Starting Address High 8 bits0x00Byte Count0x06
Starting Address Low 8 bits0x6BRegister Value High Byte (108)0x02
Register Count High 8 bits0x00Register Value Low Byte (108)0x2B
Register Count Low 8 bits0x03Register Value High Byte (109)0x00
Check CRC Low 8 bits0x74Register Value Low Byte (109)0x00
Check CRC High 8 bits0x17Register Value High Byte (110)0x00
Register Value Low Byte (110)0x64
Check CRC Low 8 bits0x05
Check CRC High 8 bits0x7A

(0x04) Read Input Registers#

Master Request#

Address FieldFunction CodeStarting AddressInput Register CountCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeByte CountInput Register StatusCheck Field
1 byte1 byte1 byte (calculating Input Register Status byte count)n bytes2 bytes (CRC-MB16)

Example#

Request to read holding register data from address 9 to 10

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x04Function Code0x04
Starting Address High 8 bits0x00Byte Count0x06
Starting Address Low 8 bits0x6BRegister Value High Byte (9)0x02
Register Address High 8 bits0x00Register Value Low Byte (9)0x2B
Register Address Low 8 bits0x03Register Value High Byte (10)0x00
Check CRC Low 8 bits0xC1Register Value Low Byte (10)0x00
Check CRC High 8 bits0xD7Check CRC Low 8 bits0xF3
Check CRC High 8 bits0xF4

(0x05) Write Single Coil#

[!NOTE]

When writing a single coil, the output value part only allows FF 00 to represent ON, and 00 00 to represent OFF; other values are invalid.

Master Request#

Address FieldFunction CodeOutput AddressOutput ValueCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeAddressOutput ValueCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Example#

Request to write the coil data at address 173 to ON

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x05Function Code0x05
Register Address High 8 bits0x00Register Address High 8 bits0x00
Register Address Low 8 bits0xACRegister Address Low 8 bits0xAC
Register Value High 8 bits0xFFRegister Value High 8 bits0xFF
Register Value Low 8 bits0x00Register Value Low 8 bits0x00
Check CRC Low 8 bits0x4CCheck CRC Low 8 bits0x4C
Check CRC High 8 bits0x1BCheck CRC High 8 bits0x1B

(0x06) Write Single Holding Register#

Master Request#

Address FieldFunction CodeHolding Register AddressRegister ValueCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeHolding Register AddressRegister ValueCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Example#

Request to write the holding register data at address 2 to 0x0003

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x06Function Code0x06
Register Address High 8 bits0x00Register Address High 8 bits0x00
Register Address Low 8 bits0x02Register Address Low 8 bits0x02
Register Value High 8 bits0x00Register Value High 8 bits0x00
Register Value Low 8 bits0x03Register Value Low 8 bits0x03
Check CRC Low 8 bits0x2CCheck CRC Low 8 bits0x2C
Check CRC High 8 bits0x0BCheck CRC High 8 bits0x0B

(0x0F) Write Multiple Coils#

Master Request#

Address FieldFunction CodeStarting AddressQuantity to SetByte CountSet ValuesCheck Field
1 byte1 byte2 bytes2 bytes1 byte (calculating Set Values byte count)n bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeStarting AddressQuantity SetCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Example#

Request to write 10 coils starting from address 20

[!NOTE]

A total of 2 bytes (16 bits) need to be written, with 6 remaining bits padded with 0 (up to the high position).

Coil Address27262524232221202928
Corresponding Value1100110100000001

After filling according to the specification, the actual Set Values segment should be 0xCD 0x01

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x0FFunction Code0x0F
Starting Address High 8 bits0x00Starting Address High 8 bits0x00
Starting Address Low 8 bits0x13Starting Address Low 8 bits0x13
Quantity High 8 bits0x00Quantity High 8 bits0x00
Quantity Low 8 bits0x0AQuantity Low 8 bits0x0A
Byte Count0x02Check CRC Low 8 bits0x24
Set Values (27~20 Address)0xCDCheck CRC High 8 bits0x09
Set Values (29~28 Address)0x01
Check CRC Low 8 bits0x72
Check CRC High 8 bits0xCB

(0x10) Write Multiple Holding Registers#

Master Request#

Address FieldFunction CodeStarting AddressQuantity to SetByte CountSet ValuesCheck Field
1 byte1 byte2 bytes2 bytes1 byte (calculating Set Values byte count)n bytes2 bytes (CRC-MB16)

Slave Response#

Address FieldFunction CodeStarting AddressQuantity SetCheck Field
1 byte1 byte2 bytes2 bytes2 bytes (CRC-MB16)

Example#

Request to write 4 holding registers starting from address 34

RequestResponse
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x10Function Code0x10
Starting Address High 8 bits0x00Starting Address High 8 bits0x00
Starting Address Low 8 bits0x22Starting Address Low 8 bits0x22
Quantity High 8 bits0x00Quantity High 8 bits0x00
Quantity Low 8 bits0x04Quantity Low 8 bits0x04
Byte Count0x08Check CRC Low 8 bits0x61
Set Value High 8 bits (34 Address)0x00Check CRC High 8 bits0xC0
Set Value Low 8 bits (34 Address)0x40
Set Value High 8 bits (35 Address)0x00
Set Value Low 8 bits (35 Address)0x24
Set Value High 8 bits (36 Address)0x00
Set Value Low 8 bits (36 Address)0x01
Set Value High 8 bits (37 Address)0xBF
Set Value Low 8 bits (37 Address)0x52
Check CRC Low 8 bits0x5F
Check CRC High 8 bits0xCC

Exception Response Frame#

Address FieldFunction CodeException CodeCheck Field
1 byte1 byte (Function Code + 0x80)1 byte2 bytes (CRC-MB16)
Exception CodeNameMeaning
0x01Illegal Function CodeThe function code of the received request is not allowed. It may be that the function code is not supported or that it is in an error state while processing the request.
0x02Illegal Data AddressThe data address received in the inquiry is not allowed. In particular, the combination of starting address and transmission length is invalid. For a controller with 100 registers, a request with a starting address of 96 and a length of 4 will succeed, while a request with a starting address of 96 and a length of 5 will generate exception code 0x02.
0x03Illegal Data ValueThis actually means that the data segment is illegal. For example, an illegal data segment length, or the number of registers written or read does not match the data segment. Note that this does not mean that the register was written with a value outside the expected range; actual write failures (this situation is 0x04).
0x04Slave Device FailureAn error occurred when the server (or slave) performed the requested operation on the register, such as writing a value outside the expected range.
0x05AcknowledgeThis is not an error, but indicates that a long-running command has been received and processing has begun.
0x06Slave Device BusyThe slave is busy processing a long-running command. (The request that caused this error should be resent when the slave is idle.)
0x08Memory Parity ErrorAn attempt was made to read a record file, but a parity error was found in memory.
0x0AGateway Path UnavailableUsed with gateways, indicating that the gateway cannot allocate an internal communication path from input port to output port for processing the request. This usually means that the gateway is misconfigured or overloaded.
0x0BGateway Target Device Failed to RespondUsed with gateways, indicating that no response was received from the target device. This usually means that the device is not on the network.

TCP Series#

In short, Modbus TCP is just a wrapper for the previous message header compared to RTU, while removing the CRC check 👍. == Because the TCP management layer's link transmission is already very robust, while serial transmission is not robust ==

The transaction number in the message header will continuously increment when the host (TCP client) initiates a request, and the slave (TCP server) will respond with the same transaction number to indicate which request is being processed. Therefore, Modbus TCP inherently supports multiple frame transmissions, and the host will not misunderstand the response 👍.

Personally, I prefer this smooth communication protocol. || Let the physical link layer handle the accuracy of the information; it’s all foggy, but checks are still necessary ||

(0x01) Read Coils#

Master Request#

Transaction IDProtocol IdentifierTotal LengthAddress FieldFunction CodeStarting AddressCoil Count
2 bytes2 bytes (all 0)2 bytes (total length of remaining bytes)1 byte1 byte2 bytes2 bytes

Slave Response#

Transaction IDProtocol IdentifierTotal LengthAddress FieldFunction CodeByte CountCoil Status
2 bytes2 bytes (all 0)2 bytes (total length of remaining bytes)1 byte1 byte1 byte (calculating Coil Status byte count)n bytes

Example#

Request to read coil data from address 20 to 38, the response address is from low to high, and the final byte is padded with 0 in the high position.

[!NOTE]

The final output status for 38-36 response bytes is padded with five remaining bits (up to the high position).

RequestResponse
Transaction ID High 8 bits0x00Transaction ID High 8 bits0x00
Transaction ID Low 8 bits0x01Transaction ID Low 8 bits0x01
Protocol Identifier 16 bits (all 0)0x00 0x00Protocol Identifier 16 bits (all 0)0x00 0x00
Total Length High 8 bits0x00Total Length High 8 bits0x00
Total Length Low 8 bits0x06Total Length Low 8 bits0x06
Address Field (Slave ID)0x01Address Field (Slave ID)0x01
Function Code0x01Function Code0x01
Starting Address High 8 bits0x00Byte Count0x03
Starting Address Low 8 bits0x13Output Status 27-200xCD
Output Count High 8 bits0x00Output Status 35-280x6B
Output Count Low 8 bits0x13Output Status 38-360x05

Other protocols will not be elaborated on

Other protocols will not be elaborated on

In short, Modbus TCP is just a wrapper for the previous message header compared to RTU, while removing the CRC check 👍.

This article is synchronized and updated to xLog by Mix Space. The original link is https://www.yono233.cn/posts/shoot/24_7_26_modbus

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.