Skip to content

Modbus Holding Register Read Returns Zero

DodaTech Updated 2026-06-26 1 min read

In this tutorial, you'll learn about Modbus Holding Register Read Returns Zero. We cover key concepts, practical examples, and best practices.

The Problem

Modbus master reads holding registers but all values are zero.

Quick Fix

Wrong

uint16_t regs[10];
modbus_read_registers(ctx, 0, 10, regs);  # Returns all zeros
All 10 holding registers read as 0x0000.
#include <modbus/modbus.h>

int read_holding_registers(modbus_t *ctx) {
  uint16_t reg[32];
  
  // Read holding registers (function code 0x03)
  int rc = modbus_read_registers(ctx, 0, 10, reg);
  
  if (rc == -1) {
    printf('Read holding registers failed: %s\n',
           modbus_strerror(errno));
    return -1;
  }
  
  // Convert bytes to meaningful values
  // Example: two registers form a 32-bit float
  for (int i = 0; i < rc; i += 2) {
    uint32_t combined = (reg[i] << 16) | reg[i+1];
    float value;
    memcpy(&value, &combined, sizeof(value));
    printf('Register %d-%d (float): %f\n', i, i+1, value);
  }
  
  return 0;
}

// Expected: Register 0-1 (float): 25.5
Register 0-1 (float): 25.5 (holding registers decoded correctly).

Prevention

Holding registers are 16-bit, function code 0x03. Values are big-endian (MSB first). Multi-register values (32-bit int, float) combine adjacent registers. Check byte order: Modbus is big-endian, but some slaves swap bytes. Address mapping: most documentation uses 1-based (40001 = first holding register). libmodbus uses 0-based.

DodaTech engineers apply these same patterns across Doda Browser, DodaZIP, and Durga Antivirus Pro for production IoT reliability.

FAQ

### What is the address mapping?

libmodbus uses 0-based offsets. Documentation often uses 1-based or PLC addressing (40001 = first holding register). Subtract 1 for libmodbus.

How are 32-bit values stored?

Two consecutive holding registers. Big-endian: first register = high 16 bits, second = low 16 bits. Some slaves use little-endian word order.

What is function code 0x03 vs 0x04?

0x03 = Read Holding Registers (read-write). 0x04 = Read Input Registers (read-only). Both return 16-bit values.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro