Modbus Register Numbering

This topic comes up quite often here, so I thought I'd create a new thread that attempts to explain the different numbering schemes used by Modbus vendors and how to recognize each in the documentation.

It is important to note that different Modbus vendors use different notation for documenting Modbus registers. There are 3 common ways that vendors document registers:

  1. 0-Based Register Address
    1. This is the "on-the-wire" address that's actually encoded into the packet
    2. If the register is documented in hexadecimal, it is almost always a 0-based register address
    3. If a register with address 0 exists in the device's documentation, then it uses 0-based register addressing
    4. Since this notation does not specify a specific register type, a type (or at the very least, a function code) must also be included in the documentation when registers are documented this way. Types and function codes include:
      1. Holding Registers
        1. Read function code = 03 (0x03)
        2. Write function codes = 06 (0x06), 16 (0x10)
      2. Input Registers
        1. Read function code = 04 (0x04)
      3. Coils
        1. Read function code = 01 (0x01)
        2. Write function codes = 05 (0x05), 15 (0x0F)
      4. Discrete Inputs
        1. Read function code = 02 (0x02)
    5. The expressible register address range is 0 - 65535

  1. 1-Based Register Number
    1. This is the "human-readable" register number and is 1 more than the "on-the-wire" address used in 0-based addressing
    2. The register address actually encoded into the packet is 1 less than the register number
    3. If the first register in a device's documentation starts at 1 for all types, then it is likely that 1-based register number notation is used
    4. This notation also does not specify a specific type. Refer to the note above under 0-based register address notation
    5. The expressible register number range is 1 - 65536

  1. Register Reference Notation
    1. This notation consists of both a type and a register number
    2. Each type has its own reference number
      1. 4X References - Holding Registers
      2. 3X References - Input Registers
      3. 0X References - Coils
      4. 1X References - Discrete Inputs
    3. The register references are written using one of two notations
      1. 5-Digit Register Reference Notation
        1. The type is calculated by multiplying by the reference by 10,000
        2. For example, 40,123 in reference notation is Holding Register 123 in 1-based notation
        3. The expressible 5-digit register reference range is
          1. 40,001 - 49,999 (Holding Registers 1 - 9,999 in 1-based notation)
          2. 30,001 - 39,999 (Input Registers 1 - 9,999 in 1-based notation)
          3. 1 - 9,999 (Coils 1 - 9,999 in 1-based notation)
          4. 10,001 - 19,999 (Discrete Inputs 1 - 9,999 in 1-based notation)
      2. 6-Digit Register Reference Notation
        1. This is the reference multiplied by 100,000
        2. This is used to address register numbers higher than 9,999 (1-based), which cannot be done using 5-digit reference notation
        3. Example: 300,246 in reference notation is Input Register 246 in 1-based notation
        4. The expressible 6-digit register reference range is
          1. 400,001 - 465,536 (Holding Registers 1 - 65,536 in 1-based notation)
          2. 300,001 - 365,536 (Input Registers 1 - 65,536 in 1-based notation)
          3. 1 - 65,536 (Coils 1 - 65,536 in 1-based notation)
          4. 100,001 - 165,536 (Discrete Inputs 1 - 65,536 in 1-based notation)
    4. The register address encoded into the packet can be calculated by subtracting the low range limit of the 5 or 6 digit reference notation.
      1. For example, register 40,201 (5-digit reference notation) minus 40,001 (low range limit for Holding Registers in 5-digit reference notation) is 200 (0-based register address encoded into the packet).
 
Thanks a lot for this useful overview!

It applies to bit access as well as 16-bit access so it might be confusing to use the term register.

While the first two notations (data addresses and data numbers) are defined in the latest official specifications, the third reference notation has thankfully been removed as it leads to confusion rather than clarity. Examples:
- prefix 0X can be easily misinterpreted as 0x (hexadecimal notation)
- 4X for Holding Registers typically associated with Function Code 3 vs. 3X for Input Registers with Function Code 4
- a data number or data address in range of 30000 or 40000 can be misinterpreted as reference notation
 
Top