Direct answer: a Modbus register map tells you, for every value, its data table (and so its function code), address, data type, scale and unit. Send the address as a 0-based offset (holding register 40001 goes out as address 0), read each 32-bit value as two consecutive registers, then try the byte orders ABCD, CDAB, BADC and DCBA until the number lands in the expected range. Our free Modbus register interpreter shows all four side by side.

Who this is for: plant and commissioning engineers connecting an energy meter, VFD or sensor to a PLC, SCADA or gateway, with the vendor’s register map in one hand and strange numbers on screen.

What you’ll be able to do after reading:

  • Pick the right function code for each row of a map.
  • Convert a 4xxxx register number into the address your master sends.
  • Decode 16-bit, 32-bit and float values and find their byte order from one known reading.
  • Apply scaling and units, and commission a new device with a checklist.

What does a Modbus register map contain?

A register map binds a device’s internal values to Modbus addresses. The Modbus Application Protocol Specification V1.1b3 calls this mapping “totally vendor device specific”, so two meters measuring the same voltage can look nothing alike on the wire. A usable map gives, for each value:

  • Parameter name and unit, such as line voltage in V.
  • Data table or function code.
  • Address, as a 0-based offset or a 1-based number such as 40001.
  • Data type and number of registers.
  • Word order for 32-bit values, and any scale factor.
  • Read only or writable.

If a column is missing, ask the vendor before you start polling.

Embedos blogs embedos-blogs: PLC rack with I/O modules and labelled wiring in an industrial control panel, the kind of Modbus master that reads a register map

Which function code reads which data table?

The table follows section 4.3 and the function code chapters of the application protocol spec. The 0x, 1x, 3x and 4x prefixes come from the older Modicon Modbus Protocol Reference Guide PI-MBUS-300 Rev. J, which many manuals still follow.

Data table Object Access Read function code Write function code Legacy reference
Coils 1 bit Read and write 01 05 (single), 15 (multiple) 0xxxx
Discrete inputs 1 bit Read only 02 None 1xxxx
Input registers 16-bit word Read only 04 None 3xxxx
Holding registers 16-bit word Read and write 03 06 (single), 16 (multiple) 4xxxx

One 03 or 04 request reads up to 125 registers; 01 or 02 up to 2000 bits. The spec lets devices overlay tables, so use the function code the map names.

Why is my reading off by one register?

The spec numbers elements in the data model from 1 to n but addresses them in the request from 0 to 65535, so a value numbered X is sent as address X minus 1. Its own example reads registers 108 to 110 with a starting address of 00 6B hex, which is 107.

The Modicon guide says the same thing in 4xxxx language: holding register 40001 is sent as address 0000, and 40108 as 006B hex. The leading 4 is not sent at all, because function code 03 already says “holding register”.

  1. A five-digit map number starting with 3 or 4 is a register number: subtract 30001 or 40001 to get the offset.
  2. Check your master. Some drivers take the register number and subtract 1 themselves; others want the offset. The driver manual says which.
  3. Prove it with a value shown on the device display. If it only looks right after shifting one register, you are off by one.

On 32-bit values this is easy to miss: you join halves of two different values and get a number that is wrong but not absurd.

Which data types will you meet in a register map?

The protocol itself only defines bits and 16-bit registers. Anything wider is the vendor packing bytes across consecutive registers.

Type Registers Range or format Typical use
uint16 1 0 to 65535 Status, scaled values
int16 1 -32768 to 32767 (two’s complement) Temperatures, signed power
uint32 2 0 to 4294967295 Energy counters, run hours
int32 2 -2147483648 to 2147483647 Signed totals, position
float32 2 IEEE 754 single precision: 1 sign bit, 8 exponent bits, 23 fraction bits Voltage, current, flow, pressure

The float format is defined in IEEE 754-2019, which is a paid standard. For a free explanation, the Wikipedia article on single-precision floating point is good further reading.

Embedos blogs embedos-blogs: single-phase DIN rail energy meter with screw terminals and kWh display

What do ABCD, CDAB, BADC and DCBA mean?

Inside one register the spec is fixed: big-endian, so 0x1234 is sent as 0x12 then 0x34. It does not fix which register comes first when a value needs two, and vendors chose differently.

Call the bytes of the first register you read A and B, and the bytes of the second register C and D. The four orders then mean:

Order Byte sequence used Common name
ABCD Register 1 high, register 1 low, register 2 high, register 2 low Big-endian
CDAB Register 2 first, then register 1 Word swapped
BADC Register order kept, bytes swapped inside each register Byte swapped
DCBA Everything reversed Fully reversed (little-endian)

Drivers and manuals use their own labels, such as “swap words” or “low word first”. Match on the byte pattern, not the name.

Worked example: decoding two registers in all four orders

An illustrative case, not a specific device: a meter’s map lists line voltage as float32 in two holding registers. Your master reads 0xB333 (45875) then 0x4367 (17255), so A = B3, B = 33, C = 43, D = 67.

Order Bytes float32 value
ABCD B3 33 43 67 -4.174 × 10-8
CDAB 43 67 B3 33 231.7
BADC 33 B3 67 43 8.354 × 10-8
DCBA 67 43 33 B3 9.218 × 1023

Only CDAB gives a believable line voltage, so this device sends the low word first. Set your master to word swapped and confirm against the meter display.

By hand, 0x4367B333 has sign bit 0 and exponent 0x86 = 134; minus the bias of 127 gives 27 = 128. The fraction 0x67B333 / 223 = 0.8101562, so the value is 128 × 1.8101562 = 231.6999969, shown as 231.7. Float32 cannot hold 231.7 exactly, so round to the map’s resolution.

The same check in Python:

import struct
r1, r2 = 0xB333, 0x4367            # registers in the order read
abcd = struct.pack('>HH', r1, r2)  # B3 33 43 67
cdab = struct.pack('>HH', r2, r1)  # 43 67 B3 33
print(struct.unpack('>f', abcd)[0])  # -4.1737987288570366e-08
print(struct.unpack('>f', cdab)[0])  # 231.6999969482422

In our free Modbus register interpreter, paste 0xB333 0x4367 in the order read. It lists float32 for ABCD, CDAB, BADC and DCBA, plus integer readings. Its built-in example, 0x4126 and 0x6666, decodes to 10.4 in ABCD.

Test with a non-zero value: 0.0 is 00 00 00 00 in every order. And confirm the data type first: read as int32, the same registers give 1130869555 in CDAB order.

Tell us what you need on site

Need this on your plant? Tell us your requirement

How do scaling factors and units work?

Many devices send a scaled integer instead of a float, with a multiplier in the map.

  • uint16 with scale 0.1 V: raw 2317 means 231.7 V.
  • int16 with scale 0.1 °C: raw 0xFF38 is -200, so -20.0 °C. Read as uint16 it becomes 6533.6 °C: a sign error, not a hot panel.
  • uint32 energy counter: registers 0x0001 and 0x86A0 in ABCD order give 100000. If the map says 0.01 kWh per count, that is 1000.00 kWh.

Watch units as closely as scale: W against kW is a factor of 1000. Some maps keep the scale in a separate register that you must read too.

How do I check raw Modbus RTU frames before decoding?

The Modbus over Serial Line Specification and Implementation Guide V1.02 puts a CRC-16 at the end of every RTU frame, sent low byte first. Check captured frames with our CRC and checksum calculator: its CRC-16/MODBUS preset gives 0x4B37 for the test string 123456789, sent as 37 then 4B. If the CRC fails, fix wiring or serial settings before blaming the map. For how RTU and TCP frames differ, see our post on Modbus RTU vs Modbus TCP.

Commissioning checklist for a new Modbus device

Check How to confirm Done
Map matches the device Model and firmware on the map match the label ☐
Function code per value 03 holding, 04 input, 01 or 02 bits ☐
Addressing convention Read a value you can see on the display; no off-by-one ☐
Data type Width, sign, integer or float ☐
Word and byte order Decode a non-zero known value in all four orders ☐
Scale and unit Compare with the display at two different values ☐
Sign handling Check a negative value where the process allows ☐
Block reads 125 registers maximum; avoid unmapped addresses (exception 02, Illegal Data Address) ☐
Writes last Only after reads are proven, with the process safe ☐
Record settings Order, scale and addresses in the commissioning sheet ☐

For a wider plan that starts with read-only functions across a whole line, see our guide to retrofitting legacy machines with OPC UA or Modbus.

Questions engineers ask about Modbus register maps

Is register 40001 the same as address 0?

In the Modicon convention, yes. Holding register 40001 is sent as address 0 with function code 03. Check whether your master wants the register number or the offset.

Why does my Modbus float read as a huge or tiny number?

The word or byte order in your master does not match the device. Decode the two registers in all four orders and pick the one inside the expected range.

What is the difference between input registers and holding registers?

Both are 16-bit words. Input registers are read only (function code 04); holding registers can be read and written (03, 06, 16).

FAQ

Does Modbus define a float data type?

No. The spec defines bits and 16-bit registers. Floats are a vendor convention that packs an IEEE 754 single-precision value into two registers.

Which byte order is the Modbus standard?

The spec fixes big-endian order inside each register. ABCD extends the same rule to two registers, but the spec does not mandate which register comes first.

How many registers can I read in one request?

Up to 125 with function code 03 or 04.

Does the register interpreter send my data anywhere?

No. The tool page states that decoding runs in your browser and nothing is sent. Its calculation basis is listed on the tools standards and disclaimer page.

Next step

Have two registers that will not decode? Paste them into the free Modbus register interpreter and compare all four orders against the reading on the device display. Embedos Edge is a platform of products, solutions, dashboards, insights and services.

Next step

Whatever master you use, decoding starts with the vendor’s register map.
Email: team@embedos.io

Help Us Help You Leverage The Power Of Industrial Automation & Industrial IoT – IIoT.