Resolving MODBUSCP FB108 Error 80B1 on S7-400 Parameter DB

David Krause15 min read
ModbusSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Overview: MODBUSCP FB108 Error 80B1 on S7-400

Expanding an existing S7-400 station with additional Modbus TCP connections is a common retrofit task, but it frequently surfaces latent configuration issues that were masked when only one connection was active. The symptom reported in the field is that FB108 (MODBUSCP) returns hex error 80B1 continuously after a CPU restart, even though every data block referenced in the documentation appears to be loaded into the CPU online view. The control program calls FB108 cyclically in OB1, performs the initialisation sequence in OB100, and uses NetPro-configured S7 connections that map to Modbus TCP endpoints on the partner devices.

The error presents an interesting diagnostic dilemma because the immediate cause (a connection-side failure from AG_SEND or AG_RECV) is not the root cause. The real defect lies one layer deeper, inside the parameter data block (PARAM_CP) that supplies the MODBUSCP instance with the numbers of the data blocks it should use to send and receive. When the actual values of that parameter DB come from a previous test project rather than the current project, FB108 attempts to access DB numbers that do not correspond to the live SEND/RECV DBs in the production project, and the lower-level communication blocks report the resulting inconsistency as 80B1.

This article walks through the full diagnostic and resolution workflow: it explains the runtime architecture of FB108 on S7-400, lists the six DBs that must exist online, clarifies why OB100 initialisation and OB1 cyclic execution must both be present, decodes the meaning of error 80B1 in the AG_SEND/AG_RECV context, and details the field-proven procedure for restoring the PARAM_CP actual values so the new connections come up cleanly after a restart.

MODBUSCP FB108 Architecture and Required Data Blocks

FB108 (MODBUSCP) is the Modbus master/slave driver function block shipped with the Siemens Modbus library for S7-400 CPUs. Each Modbus connection requires its own instance of FB108 with its own instance DB, plus a shared set of parameter and I/O data blocks. The block internally calls AG_SEND and AG_RECV to exchange data with the Ethernet CP (CP 443-1) and uses the S7 connection that NetPro establishes on top of the CP.

Six data blocks must exist in the S7-400 CPU for every Modbus connection handled by FB108:

Data Block Role Content
REG_KEY Register key DB Modbus register mapping table that defines which Modbus registers/addresses are exposed to the S7 user program.
PARAM_CP Parameter DB Connection parameters; contains the DB numbers of CONTROL_DATA, SENDDATA_DB, and RECDATA_DB used by this connection.
CONTROL_DATA Control data DB Modbus state machine, status, command, and diagnostic information used internally by FB108.
MODBUSCP_IDB Instance DB of FB108 Per-connection instance data, generated automatically when FB108 is placed in the program.
SENDDATA_DB Send data DB Data to be transmitted to the Modbus partner (master write / slave response payload).
RECDATA_DB Receive data DB Data received from the Modbus partner (master read / slave request payload).

The numbers of CONTROL_DATA, SENDDATA_DB, and RECDATA_DB are not hardcoded inside FB108. They are stored as actual values inside the PARAM_CP data block and passed to FB108 on each call. If those numbers point to wrong DBs, FB108 will issue I/O accesses to addresses that do not match the SEND/RECV data structures used by AG_SEND/AG_RECV, and the communication layer will reject the access with error 80B1.

OB100 Initialisation vs. OB1 Cyclic Execution

FB108 is a stateful block. It must be initialised exactly once at CPU startup (or restart) and then driven cyclically every OB1 scan. Splitting these two roles between OB100 and OB1 is mandatory and not optional.

OB Purpose Input Pattern Execution
OB100 Initialisation (startup/restart) REQ := TRUE and INIT := TRUE on a one-shot call to FB108 Runs once on cold/warm restart; brings the Modbus state machine into IDLE and registers the connection.
OB1 Cyclic execution REQ := FALSE and INIT := FALSE, but keep EN := TRUE and connect all DB pointers Runs every cycle; processes Modbus state transitions and triggers AG_SEND/AG_RECV.

Typical OB100 call snippet in Structured Text (ST) or LAD representation:

CALL FB108, "MODBUSCP_IDB"     // per-connection instance DB
  REQ   := TRUE                 // one-shot trigger
  INIT  := TRUE                 // initialise state machine
  PARAM := "PARAM_CP"           // pointer/DB number for parameter data
  ...

OB1 call snippet:

CALL FB108, "MODBUSCP_IDB"
  REQ   := FALSE                // no startup trigger
  INIT  := FALSE                // already initialised in OB100
  PARAM := "PARAM_CP"
  ...

If the OB100 call is missing, FB108 never performs the one-time handshake with the CP and the connection stays in an undefined state. If only OB100 is present and OB1 is missing, FB108 never advances its internal state machine after initialisation. Both OBs must exist, and each new connection needs its own instance DB and its own FB108 call site.

Decoding Error Code 80B1

Hex 80B1 is not a Modbus-protocol error code; it is an S7-communication-layer error code generated by the lower-level AG_SEND / AG_RECV function blocks that FB108 invokes internally to move data between the CPU and the CP. The same hex value is used in two distinct contexts:

Hex Code Decimal Source FB Meaning in the AG_SEND/AG_RECV Context
80B1 32945 AG_RECV / AG_SEND The connection ID or connection type does not match a connection configured in NetPro, or the configured connection is not established / not available, or the resources needed to service the call are not available.

On S7-400, the AG layer blocks are:

  • AG_SEND — FB12 (per S7-400 standard library assignment).
  • AG_RECV — FB13 (per S7-400 standard library assignment).

FB108's output STATUS_FUNC identifies which of these blocks actually raised the error. The field report shows STATUS_FUNC returning TEST_DB for all three new connections, which indicates that the error path runs through SFC24 (TEST_DB) — a system function that tests a data block for presence and consistency — rather than through AG_SEND/AG_RECV directly. This is a strong signal that the mismatch lies at the DB level: FB108 is asking SFC24 to validate a DB whose number does not correspond to any DB currently loaded in the CPU, and SFC24 reports the failure back as 80B1 through the MODBUSCP status chain.

Diagnostic implication: If STATUS_FUNC returns TEST_DB, the next step is not to chase the S7 connection configuration but to inspect every DB number stored inside PARAM_CP as an actual value. The connection in NetPro is almost certainly correct; the link that is broken is the pointer from PARAM_CP to the actual SENDDATA/RECDATA/CONTROL_DATA DBs of the current project.

Diagnostic Workflow: STATUS_FUNC and SFC24 (TEST_DB)

The standard Siemens diagnostic path when FB108 reports a persistent error is to read the four status outputs of the block at the OB1 call site while online with the CPU. For the S7-400 the relevant outputs include:

  • STATUS — aggregated status word (Modbus level).
  • STATUS_FUNC — name or identifier of the lower-level FB/SFC that triggered the error.
  • STATUS_SFB — additional status from the lower-level block.
  • ERROR — boolean, true when STATUS <> 0.

Step-by-step diagnostic procedure:

  1. Go online with the S7-400 CPU in STEP 7 (target system > online > view).
  2. Open the OB1 call site of FB108 for the failing connection.
  3. Add the four status outputs to the monitor view (right-click > monitor/modify).
  4. Trigger a CPU restart (STOP/RUN or power cycle) so that OB100 runs and the new connections are reinitialised.
  5. Read STATUS_FUNC immediately after restart. If it reads TEST_DB, the failure is at the SFC24 DB-validation layer, not at AG_SEND/AG_RECV.
  6. Run SFC24 manually in the program editor (LAD/FBD/ST) against each candidate DB number from PARAM_CP. Any DB number that fails the SFC24 call is a strong candidate for a stale actual value.
  7. Compare the offline PARAM_CP actual values with the online view. Mismatches between offline and online are the root cause in the vast majority of these cases.

The SFC24 manual call in STL/ST looks like:

CALL SFC 24 ("TEST_DB")
  DB_NUMBER  := 200             // or any DB number from PARAM_CP
  RET_VAL    := MW100           // 0000 hex = OK, non-zero = fault

A non-zero RET_VAL from SFC24 confirms that the DB number is not present in the CPU. A zero return confirms that the DB exists. If the DB exists but FB108 still reports 80B1, the next hypothesis is that the DB exists in the project but with a different structure than what PARAM_CP and FB108 expect — for example, a REG_KEY DB with a different register count, or a SENDDATA_DB whose length does not match the Modbus mapping table.

Root Cause: Stale Actual Values Inside PARAM_CP

The specific field finding is that the initial values of PARAM_CP in the offline project were correct (they pointed at the right DBs of the current project), but the actual values in the online CPU were inherited from a previous test project. Initial values are the values stored inside the DB source as defaults; actual values are the values currently held in the DB after the CPU has been running. They can diverge when a DB is downloaded with the "Download to target / initialise" option that preserves actual values, or when a project is reused and the DB contents are never reset.

The risk profile of this mismatch is severe. If the test-project DB numbers happened to exist in the production project, FB108 would have written data into unrelated data blocks and silently corrupted process values. In this specific case, the test-project DB numbers did not exist in the current project, which produced the 80B1 error at the SFC24 validation step — a failure that is preferable to silent corruption but still blocks the connection.

Field lesson: Always check both the offline initial values and the online actual values of every parameter DB that drives a communication block. The offline view alone gives a false sense of correctness when the CPU retains a previous project's actual values after download.

Step-by-Step Resolution: Correcting PARAM_CP Actual Values

  1. Open PARAM_CP in the STEP 7 editor and switch to the "Data View" tab.
  2. Compare the "Initial Value" column against the "Actual Value" column for every field that references another DB number.
  3. Identify the three fields that point to CONTROL_DATA, SENDDATA_DB, and RECDATA_DB.
  4. For each of the three new connections, set the actual values to match the correct DB numbers of the current project.
  5. Save and download PARAM_CP to the CPU with the "Download with consistency check" option. Avoid "Download block to PG/PC" for this step; you want the new values in the CPU, not in the PG.
  6. After download, switch the CPU to STOP and back to RUN so that OB100 re-runs and FB108 reinitialises with the corrected PARAM_CP contents.
  7. Monitor STATUS_FUNC in OB1. It should now change from TEST_DB to either OK (no error) or to one of the AG_SEND/AG_RECV names.
  8. If STATUS_FUNC reports AG_SEND or AG_RECV, proceed to NetPro validation (next section). If it still reports TEST_DB, repeat the inspection — there may be more than one DB pointer field in PARAM_CP with a stale value.

Bulk reset alternative: select PARAM_CP in the S7 program, right-click > "Reset to initial values" — this restores every actual value to the offline initial value. Use this method only after confirming that the initial values are correct. The reset forces OB100 to use a consistent starting state on the next startup.

NetPro Connection Validation

After PARAM_CP is repaired, error 80B1 can still appear if the S7 connection itself is not correctly configured in NetPro. Verify the following for each new connection:

Setting Required Value Check Method
Connection type S7 connection (TCP/IP) to partner Open NetPro, double-click the connection, confirm type = "S7 connection".
Connection ID Unique per connection, matches the value passed to FB108 / AG_SEND / AG_RECV Cross-check the ID field in NetPro against the input parameter on FB108 / AG_SEND / AG_RECV call sites.
Partner IP address Correct IP of the Modbus partner NetPro partner properties > addresses.
Partner port / TSAP Matches the partner device configuration NetPro partner properties > addresses.
Active connection establishment Set on the side that initiates the TCP session NetPro > connection properties > special properties.
Compiled and downloaded NetPro configuration compiled and downloaded to the CP Right-click CP > download to PG/PC or download station to target.

Common NetPro pitfalls on S7-400 include mismatched connection IDs between the S7 program call site and the NetPro configuration, duplicate connection IDs, and forgetting to compile NetPro after a new connection is added. All three produce 80B1-class errors from AG_SEND/AG_RECV when the OB1 code runs.

Commissioning Verification Checklist

Run the following checks in order after the resolution. Each item has a pass/fail criterion that is observable online.

# Check Pass Criterion
1 All six required DBs present online for every connection Online view lists REG_KEY, PARAM_CP, CONTROL_DATA, MODBUSCP_IDB, SENDDATA_DB, RECDATA_DB for each connection.
2 SFC24 returns 0000 hex for every DB number used by PARAM_CP RET_VAL of every SFC24 call = W#16#0000.
3 OB100 runs once on restart STEP 7 online > module information > OB1 / OB100 execution counts show OB100 ticked exactly once.
4 OB1 cycles continuously OB1 execution counter increments steadily in online view.
5 FB108 STATUS_FUNC changes from TEST_DB to OK Monitor view shows STATUS_FUNC = OK or the corresponding AG_SEND/AG_RECV identifier.
6 FB108 STATUS = 0 Monitor view shows STATUS = W#16#0000.
7 CP443-1 reports the S7 connection as established CP diagnostics > connection list shows the connection as "Established".
8 Modbus partner responds to test request SENDDATA_DB contents are echoed in RECDATA_DB after a master read transaction.

Related Error Codes and Edge Cases

While 80B1 is the headline error in this case, FB108 and its supporting blocks can surface a number of adjacent codes that share the same family of causes. The table below captures the codes most likely to appear during a similar retrofit.

Hex Code Typical Source Likely Cause on S7-400 / FB108 First Diagnostic Step
80B1 AG_SEND / AG_RECV or SFC24 Connection ID mismatch, NetPro not compiled/downloaded, or PARAM_CP actual values point to wrong DBs. Check STATUS_FUNC; if TEST_DB, audit PARAM_CP actual values.
80B2 AG_SEND / AG_RECV CP cannot establish the TCP session (network, partner not ready, IP routing). Check CP diagnostics, ping partner, verify TSAP and port.
80B3 AG_SEND / AG_RECV Partner rejected the connection (remote resource not available). Check partner device, Modbus server state, partner-side firewall.
80C3 / 80C4 AG_SEND / AG_RECV CPU resources exhausted on local (80C3) or partner (80C4) side. Reduce number of parallel jobs; check CPU load.
0xA0xx FB108 Modbus-level Modbus protocol error (illegal function, illegal address, illegal data value, slave device failure). Check STATUS_FUNC for Modbus exception class and verify register map.
W#16#80B1 with STATUS_FUNC = TEST_DB SFC24 inside FB108 DB number from PARAM_CP does not exist or DB has wrong structure. Reset PARAM_CP actual values to initial values of the current project.

For engineers migrating from S7-400 / STEP 7 V5.x to the TIA Portal environment, the same family of DB-length and DB-number errors appears in the S7-1200 / S7-1500 Modbus RTU instruction MB_HOLD_REG: when the addressed area is longer than the DB, the instruction raises a similar error in TIA Portal Modbus RTU error messages. The principle is identical — a mismatch between the parameter block and the actual DB length — and the corrective action is the same: align the parameter block with the live DB structure of the current project.

On other Modbus-capable controllers such as the Eaton easyE4, equivalent error codes for the Modbus TCP client are documented separately; cross-referencing those tables is useful when validating the partner-side behaviour rather than the S7-side. See the Eaton easyE4 Modbus TCP client error codes page for a comparison reference of Modbus TCP client-side error classes (although the hex codes are platform-specific).

Best-Practice Notes for Multi-Connection FB108 Retrofits

When more than one Modbus connection is added to an existing S7-400 station, the following practices reduce the chance of a repeat of the 80B1 failure described above:

  • One instance DB per connection. Every FB108 instance must be placed on its own unique MODBUSCP_IDB. Sharing an instance DB across connections breaks the per-connection state machine.
  • Unique PARAM_CP per connection. Sharing a single PARAM_CP across multiple FB108 instances is not supported. Each connection must have its own parameter DB with its own DB number references.
  • Always run SFC24 in commissioning. Calling SFC24 against every DB number referenced from PARAM_CP before commissioning takes seconds and rules out the entire DB-mismatch class of failure in one pass.
  • Reset PARAM_CP actual values after download. After any download that changes PARAM_CP, force "Reset to initial values" so that no prior-project actual values survive into the next startup.
  • Compile NetPro after every connection change. Forgetting to compile NetPro is the single most common cause of "the connection is configured but does not work".
  • Document the DB-number contract. Maintain a small spreadsheet that lists every connection, every DB number it uses, and the symbolic name. This makes audits like the one in this article a five-minute task rather than a multi-hour investigation.

Frequently Asked Questions

What does hex error 80B1 mean on an S7-400 when MODBUSCP FB108 is called?

Error 80B1 in the FB108 context is generated by the lower-level AG_SEND, AG_RECV, or SFC24 block that FB108 calls internally. It indicates that the connection ID configured in NetPro does not match the connection requested by the program, that the connection resources are not available, or — when STATUS_FUNC reports TEST_DB — that a DB number referenced from PARAM_CP does not exist or is inconsistent with the loaded DB structure. Cross-check STATUS_FUNC first to identify which of the three sources is raising the error.

Why does OB100 have to initialise FB108 separately from OB1?

FB108 is a stateful block. OB100 runs once at cold/warm restart with REQ=TRUE and INIT=TRUE to bring the Modbus state machine into the IDLE state and register the connection with AG_SEND/AG_RECV. OB1 runs every scan with REQ=FALSE and INIT=FALSE to advance the state machine and process cyclic Modbus transactions. If either OB is missing, FB108 either never initialises or never advances, and the connection stays in an undefined state.

How do I tell whether the failure is in NetPro or in PARAM_CP?

Read STATUS_FUNC online while the CPU is running. If STATUS_FUNC reports AG_SEND or AG_RECV, the failure is on the connection side and NetPro is the first place to inspect (connection ID, partner IP/TSAP, active-establishment flag, NetPro compilation). If STATUS_FUNC reports TEST_DB, the failure is on the DB side and PARAM_CP is the first place to inspect (actual values vs. initial values, DB numbers of CONTROL_DATA / SENDDATA_DB / RECDATA_DB).

Can I share a single PARAM_CP across multiple FB108 instances?

No. Each FB108 instance must reference its own PARAM_CP with its own DB number pointers. Sharing PARAM_CP across connections causes the first connection that runs to overwrite the parameter set used by the other connections, producing intermittent 80B1 errors and unstable Modbus traffic.

How do I reset PARAM_CP actual values to the initial values of the current project?

Open PARAM_CP in the STEP 7 editor, right-click the data block, and select "Reset to initial values". This rewrites every actual value to the initial value defined in the offline project. After the reset, perform a STOP/RUN transition on the CPU so that OB100 re-runs against the corrected parameter set, and re-monitor STATUS_FUNC in OB1 to confirm the error is gone.

Back to blog