— The Verbs of Communication

(Module 4 · Modbus Data Model & Function Codes)


Learning objectives

By the end of this chapter you will be able to …

  1. Enumerate every public Modbus function code (FC01 – FC24, FC43) and know its legal data tables.
  2. Decode request and response PDUs byte-by-byte for all high-volume codes (FC01/02/03/04/05/06/15/16/23).
  3. Recognise diagnostic and file-access op-codes (FC07/08/20/21) and decide when not to use them.
  4. Implement best-practice polling strategies that slash bandwidth by 60 % and avoid “write-clobber” race conditions.
  5. Troubleshoot exception frames; map each exception code to a probable root cause and field fix.

11.1 Why function codes matter

A Modbus message has only two semantic fields: Function Code + Data.
The code is the verb; it declares what the master wants the slave to do with the data addressed in Chapter 10.

Concept lens Data tables = nouns; Function code = verb.
e.g. “Read (verb) 16 Holding Registers (noun) starting at 40001.”


11.2 Function-code landscape

BlockFCVerbTarget tableSupported by
Bit Read01Read Coils0X (RW bits)99 %
02Read Discrete Inputs1X (RO bits)95 %
Bit Write05Write Single Coil0X95 %
15 (0Fh)Write Multiple Coils0X90 %
Word Read03Read Holding Regs4X100 %
04Read Input Regs3X98 %
Word Write06Write Single Reg4X98 %
16 (10h)Write Multiple Regs4X95 %
Combo23 (17h)Read/Write Multi-Reg4X70 %
Diagnostics07Read Exception Statusn/aPLC-class
08Diagnostics (various sub-functions)n/aRare
File / Mask20Read File RecordFile spacePLC, RTU
21Write File Record
Encapsulated43MEI (Encap. Interface)Device ID / CANopen mapNewer slaves

(Figure 11-1 placeholder: “Function-code universe” mind-map.)


11.3 Deep dive: core public function codes

11.3.1 FC 01 – Read Coils (bits RW)

FieldRequestResponse
Addr Hi/LoStart coil offsetechoes
Qty Hi/Lo# coils (1 – 2 000)echoes
ByteCnt then packed bits (LSB = first coil)

Bandwidth tip – always read coils in groups of 8/16/32 so the packed byte boundary matches polling block; avoids padding.

11.3.2 FC 03 – Read Holding Registers

ByteRequestExample
0-1Start Addr Hi/Lo0x00 0x10 (40017 human)
2-3Quantity Hi/Lo0x00 0x06 (6 regs)

Response – ByteCount = Qty × 2, then 2 × Qty data bytes.

Off-by-one reminder – start address is zero-based offset into 4X table.

11.3.3 FC 15 (0Fh) – Write Multiple Coils

Payload formula:

ByteCnt = ⌈Qty / 8⌉
FrameLen = 1 Addr 1 FC 2 Start 2 Qty 1 ByteCnt  N(Bytes) 2 CRC

Write masks inside payload bit-pack; unused trailing bits must be zero.

11.3.4 FC 23 (17h) – Read/Write Multiple Registers

One frame, two operations.

  • Request PDU contains read start/qty + write start/qty + write bytes.
  • Response PDU returns only read section.

Use when you must read-modify-write without race risk (e.g. HMI adjusting PID but needing current value first).

(Listing 1: Python pymodbus FC23 call.)


11.4 Diagnostic & rare codes (overview)

FCSub-funcPurposeReplaced by
07Return coil & DI summary in one byteVendor-specific heartbeat
0800Echo loopbackICMP ping in TCP world
0804Force listen-only modeNot advisable; can brick slave
20/21PLC file record opsEthernet/IP, S7comm
43/14Read Device IDReturns model/serial in ASCIIGood for asset mgmt

Most modern OT stacks ignore 07/08; FC43/14 is worth enabling for automatic asset inventory.


11.5 Exception Responses Refresher

(See Chapter 13 for full table.)

CodeTypical triggerField remedy
01 Illegal FunctionMaster polled FC05 but slave is RO sensorChange poll list
02 Illegal Data AddressOffset beyond mapFix register map
03 Illegal Data ValueQty = 0 or > specBreak burst into smaller chunks
06 Slave BusyPLC executing flash updateIncrease retry back-off
0B Gateway Target FailSerial slave offlineCheck RS-485 t-line

Exception frames consume far less bandwidth than timeouts; pollers should handle them gracefully (no 5 s reconnect penalty).


11.6 Polling & write strategies

ScenarioBest FCBlock sizeWhy
HMI screen – 50 coils scattered01 (coils) + map them contiguous64One frame ≈ 10 ms
Historian – log 1 000 analogs03 (holding) or 04 (input)125 per frame (max)Lowest overhead
Set 10 set-points atomically23 Read/Write≤ 10Avoid racing another master
Toggle single output051Quick, deterministic

Bandwidth rule
Cycle time ≈ Frames × (Header + Payload) ÷ link speed + TCP/Rtu gap.
Aggregating registers is the #1 lever.


11.7 Implementation patterns

Client side

for block in grouped_registers(table=4X, width<=125):
    rsp = read(block)
    if rsp.exception:
        log_and_skip

Server side

switch(func_code) {
 case 0x03: read_holding(); break;
 case 0x10: write_multi_holding(); break;
 default: return_exception(ILLEGAL_FUNC);
}

Security filter – drop FC05/06/15/16 if station is “read-only” zone.


11.8 Troubleshooting cheatsheet

SymptomLikely mis-used FCFix
Only first register updatesMaster used FC06 on multi-word floatUse FC16
Slave returns exception 01Master polling unsupported FC24 (mask write)Disable mask write or upgrade slave
Data flips every pollTwo masters both FC16 same regsSplit address space or implement token

11.9 Best-practice summary

  1. Read big, write small. Group reads up to 125 regs; keep writes minimal.
  2. Prefer FC23 for atomic R/W scenarios to eliminate race conditions.
  3. Know the table ↔ FC matrix – never write to 3X or 1X.
  4. Trap exceptions; they’re free diagnostics compared with timeouts.
  5. Document every FC allowed on a device – simplest firewall is an allow-list.

Placeholder assets

IDIdea
Fig-11-1Mind-map of all function codes grouped by category
Fig-11-2Side-by-side FC03 normal vs exception frames
Listing 1Python FC23 example
Table-11-AQuick-ref cheat table (FC, hex, table, R/W)

Next chapter: Chapter 12 — Handling Data in Modbus: Endianness, Floats & Advanced Types, where we’ll deep-dive into 32-bit floats, 64-bit doubles, BCD, string packing, and bit-level access tricks.

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts

Chapter 18 – Integrating Modbus with PLCs

— Configuration & Programming (Module 5 · Development & Implementation – Bringing Modbus to Life) Learning objectives Configure three flagship PLC families (Siemens S7-1500, Rockwell ControlLogix, Beckhoff CX/TwinCAT3) as Modbus masters and…

Chapter 5 – Modbus RTU

— Efficient Binary Communication (Module 2 · Modbus Serial Protocols — The Original Workhorses) Goal of this chapter Make you 100 % confident with every bit, byte, gap, and CRC…