Function Codes, Register Spaces, and the Myth of a Single Address in MODBUS RTU addressing

Engineers working with MODBUS RTU addressing often assume that a register address uniquely identifies a data point inside a device. This article builds on the fundamentals explained in Demystifying MODBUS RTU addressing. In practice, this assumption leads to confusion, misconfigured SCADA systems, and lengthy troubleshooting sessions.

The root cause is simple: MODBUS does not use a single, flat address space. Instead, it defines multiple independent register spaces, and the register type is selected implicitly by the Function Code. Logical address formats such as 4XXXX or 3XXXXX are human conventions layered on top of the protocol and do not exist at the communication level.

This article explores how MODBUS actually addresses data and why the Function Code can be considered a “senior address” or namespace selector.

MODBUS RTU addressing: there is no single address space

At the protocol level, MODBUS defines four distinct data models:

  • Coils (discrete outputs)
  • Discrete inputs
  • Input registers
  • Holding registers

Each of these represents an independent address space, with addresses ranging from 0 to 65535.

MODBUS RTU Addressing and Function Codes: Selecting Register Space

modbus-rtu-addressing-register-spaces and function codes diagram

This means that address 13 can legally exist four times inside the same device:

  • coil 13
  • discrete input 13
  • input register 13
  • holding register 13

They are not ambiguous because they are never accessed in the same way. In MODBUS RTU, the register type is never transmitted explicitly. Instead, it is implied by the Modbus Function Codes.

For example:

  • Function Code 01 → read coils
  • Function Code 02 → read discrete inputs
  • Function Code 03 → read holding registers
  • Function Code 04 → read input registers

From this perspective, the Function Code acts as a selector that determines which register space the subsequent address refers to.

In other words, the actual protocol-level address is not just the register address field. It is the combination of:

  • Function Code
  • PDU register address

This is why the same PDU address value can legitimately access completely different data depending on the Function Code used.

PDU addresses are always zero-based in MODBUS RTU addressing

Inside the MODBUS PDU, the register address is a 16-bit, zero-based value ranging from 0 to 65535. This is the only address that is transmitted on the wire.

There is no concept of “40001”, “30010”, or “10025” in the MODBUS RTU frame. Those formats exist solely for documentation and user interfaces.

Any addressing scheme that starts at 1 or includes a leading digit to indicate the register type is a logical convention, not a protocol requirement.

The origin of logical addresses and offsets in MODBUS RTU addressing

To make MODBUS addresses easier for humans to interpret, manufacturers and software vendors introduced logical addressing schemes with offsets. The address format follows conventions used by many SCADA systems, as described by Fernhill Software.

Commonly used conventions include:

  • Coils: 0 or 1
  • Discrete inputs: 10001
  • Input registers: 30001
  • Holding registers: 40001

These offsets do not change how the protocol operates. They simply encode two pieces of information into a single number:

  • the register type
  • the register index

Different vendors may choose different offsets, different digit lengths, or even omit offsets entirely. This is why device documentation and SCADA software often appear inconsistent.

Why SCADA software often causes confusion with MODBUS RTU addressing

Most SCADA systems ask the user to enter a “register address” and a “register type” separately. Others expect a single logical address, such as 400131.

Internally, however, every MODBUS master performs the same steps:

  1. Select the Function Code based on the register type
  2. Convert the logical address to a zero-based PDU address
  3. Transmit only the Function Code and the PDU address

Understanding this internal process makes it clear why changing the logical address format does not affect the actual communication, as long as the final PDU address and Function Code are correct.

Thinking about MODBUS RTU addressing the right way

A useful mental model is to think of MODBUS addressing as a two-level system:

  • The Function Code selects the register space
  • The PDU address selects the element within that space

Once this model is adopted, many common misunderstandings disappear:

  • identical register numbers no longer seem problematic
  • offsets are clearly seen as UI conventions
  • documentation inconsistencies become easier to interpret

Conclusion

MODBUS RTU does not provide a single global address space. Instead, it relies on multiple independent register spaces selected implicitly by the Function Code. Logical addresses, offsets, and numbering schemes are tools for humans, not part of the protocol itself. At the communication level, only the Function Code and the zero-based PDU address matter. Recognizing this distinction is key to designing robust MODBUS integrations, interpreting device documentation correctly, and avoiding unnecessary addressing errors.