# Read/Write Memory – Read Command (03)

{% hint style="info" %}
When reading large values using different data formats (e.g., Float32 or Int64) and performing conversions, very small differences may occur due to internal calculation methods, typically less than 1/10,000, which is considered normal.

Registers from different parameter categories cannot be read across categories. A single read command can access up to 40 registers. Requests exceeding this length will be ignored.
{% endhint %}

#### **Function Code:** 03

This command can read single or multiple holding registers, used to access configuration parameters defined in the device’s Holding Registers.

#### **Read/Write Memory – Read Command (03) Format**

![](https://3404778090-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi4ECt41Kyy9211OWazj4%2Fuploads%2FRDPIYYi5jti5cuB5GScu%2Fmodbus-03-TX-diagram-en.png?alt=media\&token=9118d9b0-8657-44cc-9cde-baad5c2218cf)

![](https://3404778090-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi4ECt41Kyy9211OWazj4%2Fuploads%2FlDwdjwUgzzWLAWyfIKc6%2Fmodbus-03-RX-diagram-en.png?alt=media\&token=9751a213-080f-48eb-bef2-e85f3a875e5a)

#### Modbus RTU **Example of Reading Read/Write Memory Holding Registers (03)**

Using Function Code 03 to read the "A08 Pipe Material" register as an example:

According to the Read/Write Memory – Read List, the starting address is 000A, register length is 1 (one register), data type is Int16 (16-bit integer), and the number of registers to read is 0001 (1 register).

Per device specifications, A08 Pipe Material is stored as an Int16 (16-bit integer), occupying 1 register (2 bytes), with Big Endian byte order.

**Master Sends Read Command (TX Frame)**\
**TX Request Command:**

```
01 03 00 0A 00 01 A4 0E
```

* Slave Address = 01
* Function Code = 03
* Starting Register Address: 000A (A08 Pipe Material register)
* Number of Registers to Read: 0001 (1 register)
* CRC Checksum: A40E (Error-checking code calculated using the CRC algorithm)

**Slave Response Data (RX Frame)**

Assume the Pipe Material code is 3 (Hex: 0003).

**RX Response Data:**

```
01 03 02 00 03 B8 44
```

* Slave Address: 01
* Function Code: 03
* Byte Count: 02 (1 register, 2 bytes)
* Data Bytes: 0003 (Pipe Material code – PP material)
* CRC Checksum: B844 (Error-checking code calculated using the CRC algorithm)

#### **Data Parsing and Conversion (to Decimal)**

#### **Step A** – Arrange the Data

* Received Data: 0003
* Data Type: Int16 (16-bit integer)

#### **Step B – Convert to Decimal and Map Material**

* Convert the hexadecimal value 0003 to decimal:\
  Decimal Calculation: (0 × 256) + 3 = 3\
  Final Value: 3
* Material Mapping: Refer to the A08 Pipe Material list. The value 3 corresponds to PP material.

### **FAQ**

* **Why is there a difference between the “Memory Map” and the “PLC Read Address”?**

Users may see that the memory map shows **40005**, but in the PLC, **you need to enter 4 (or 0004) to read the correct value**.

This is due to Modbus addressing: human-readable addresses (memory map) and actual device read addresses (communication addresses) have a fixed offset.

For **Function Code 03**, **40001** is the base address. Reading starts from this base, so 40001 corresponds to offset **0000** and read address **0000**.

<div align="left"><figure><img src="https://3404778090-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fi4ECt41Kyy9211OWazj4%2Fuploads%2FRaDBO20sysllv5K1KuXe%2Fmodbus-img4.jpeg?alt=media&#x26;token=9d8d7799-e27a-4de4-8ad2-fbbc6fc56c11" alt="" width="540"><figcaption></figcaption></figure></div>

Therefore, when the document indicates reading **40005**, the actual starting address in the Modbus **Function Code 03** packet is **0004**, i.e.:

**Actual communication address=Document address−40001**

{% hint style="info" %}
**Note:** Modbus uses 0-based addressing (communication packets start from 0), So, in general : Actual communication address=Document address−40001.

**BUT, i**f the PLC or HMI is set to 1-based addressing (software adds 1), enter the starting address according to the software’s rules to read the correct register.
{% endhint %}
