Problem Description
When programming Siemens S7-1500 controllers in Statement List (STL) using TIA Portal V20, a common failure pattern appears when engineers attempt indirect data block access through the OPN instruction. The classic symptom is that DBW (data block word) reads return zero or stale values even though the target DB is being opened with a dynamic number stored in a memory word.
A representative failing sequence looks like this:
OPN DB[Heat] // Heat = MW110, currently 131
L 131
T Heat
A "BIT1"
A(
L DBW 360
L DBW 362
>=I
...
Engineers observe that DBW 360 and DBW 362 evaluate to 0 instead of the actual values stored at offsets 360 and 362 in DB131. The same code works if the DB number is hard-coded with OPN DB 131, but breaks when the number is parameterized through a marker word and an indexed OPN call.
The root cause is not a bug in the instruction. It is a fundamental behaviour of the S7-1500 CPU's DB register that is not always obvious to engineers transitioning from S7-300/400 or from ladder logic.
Root Cause Analysis
The S7-1500 CPU maintains two register pairs that track the currently open data block:
| Register Pair | Purpose | Indexed access syntax |
|---|---|---|
| DB / DI | Two independent DB register pairs, each holding a DB number |
DBW, DBB, DBD use the DB pair; DIW, DIB, DID use the DI pair |
When the program issues a fully qualified DB access such as "DB_L2_Cmd_OP_Transfert".G1_TEMP — that is, an absolute or symbolic access that names the data block explicitly — the CPU loads the number of that named DB into the DB register before reading the operand. This is the same mechanism that makes a symbol like "Motor_DB".Speed work without an explicit OPN in front of it.
The user's failing code mixes two addressing styles inside the same AND block:
- An indexed access —
DBW 360,DBW 362,DBW 364— which depends on the DB register containing DB131. - A fully qualified access —
"DB_L2_Cmd_OP_Transfert".G1_TEMP— which silently writes a new value into the DB register as the compiler resolves the symbol.
Once any fully qualified DB access is evaluated inside the statement, the DB register no longer points to DB131. Every subsequent DBW read in that same network — or even in the next network, depending on cycle position — is interpreted against the wrong DB, and may even resolve against DB0 (the null block) where every DBW reads as zero.
Background: The OPN Instruction in S7-1500 STL
The OPN (Open data block in DB register) instruction for S7-1500 STL transfers the number of a global data block into the DB register. After OPN executes, any subsequent DBW, DBB, or DBD operand access reads from that DB until either the register is overwritten by another OPN or by a fully qualified access.
Key facts that govern the behaviour:
-
OPN DB <n>opens DB numbernin the DB register. -
OPN DB[MW110]opens the DB whose number is the current value of MW110. -
OPN DI <n>opens instance DBnin the DI register. - A fully qualified symbolic access (e.g.,
"MyDB".TagorDB20.DBW0) writes that DB number into the DB register as a side effect. -
OPN DB 0opens the null DB;DBWreads from DB0 always return 0.
This last point is the trap. The CPU does not raise an error when the DB register is silently repointed — it simply routes the next indexed access to whatever DB is now loaded.
Why the Failing Network Returns Zero
Walk through the original network step by step:
OPN DB[Heat] // (1) DB register := DB131
L 131
T Heat // (2) Heat := 131 (redundant, fine)
A "BIT1"
A(
L DBW 360 // (3) reads DBW360 of DB131 — OK the first time
L DBW 362
>=I
L DBW 360 // (4) reads DBW360 of DB131 — OK
L DBW 364
>=I
L DBW 360 // (5) reads DBW360 of DB131 — OK
L "DB_L2_Cmd_OP_Transfert".G1_TEMP // (6) DB register := DB_L2_Cmd_OP_Transfert
>=I
L DBW 360 // (7) reads DBW360 of DB_L2_Cmd_OP_Transfert, NOT DB131
T #G1_MaxTemp
)
Statement (6) is the point of failure. The compiler resolves "DB_L2_Cmd_OP_Transfert".G1_TEMP by loading that DB's number into the DB register before reading the tag. From that moment on, every DBW in the same network is interpreted against DB_L2_Cmd_OP_Transfert, not DB131. The values seen in DBW360, DBW362, DBW364 will be whatever those offsets happen to contain in that DB — which in the user's case is zero, giving the impression that "the indexed access is broken."
The same problem recurs in each of the four O(...) branches. The fully qualified read of G1_TEMP in every branch silently invalidates the indexed reads that follow it within the same AND/OR block.
Verified Solution: Reopen the DB Before Every Indexed Read
The reliable fix is to re-issue OPN DB[Heat] (or OPN DB Heat) immediately before any indexed DBW access that follows a fully qualified access. The corrected network looks like this:
OPN DB[Heat]
L 131
T Heat
A "BIT1"
A(
// --- Branch 1: DBW360 is the maximum ---
OPN DB[Heat] // reopen DB131 before every indexed read
L DBW 360
L DBW 362
>=I
L DBW 360
L DBW 364
>=I
L DBW 360
L "DB_L2_Cmd_OP_Transfert".G1_TEMP
>=I
L DBW 360
T #G1_MaxTemp
)
Repeat the OPN DB[Heat] line in front of every O(...) branch as well. The instruction is a single STL word (2 bytes) and executes in microseconds; there is no measurable performance penalty on S7-1500 CPUs.
OPN DB[Heat] immediately before every indexed DBW/DBB/DBD read in the network. Do not rely on the register value surviving a single STL line that contains a fully qualified reference.Alternative Pattern: Use a Local Copy to Avoid the Register Clash
If the OPN-per-read pattern is too verbose — for example, in a function that runs against four different DB numbers — copy the fully qualified tag into a temporary local variable first, then perform the comparisons against that local. This keeps the indexed DBW reads untouched:
// Copy G1_TEMP into a temp, using the DI register pair so the DB
// register is not disturbed:
L "DB_L2_Cmd_OP_Transfert".G1_TEMP
T #G1_OpTemp // INT local in the FC/FB interface
OPN DB[Heat] // DB register := DB131
L 131
T Heat
A "BIT1"
A(
L DBW 360
L DBW 362
>=I
L DBW 360
L DBW 364
>=I
L DBW 360
L #G1_OpTemp // use the local copy, no DB-register side effect
>=I
L DBW 360
T #G1_MaxTemp
)
This pattern is more readable and removes a class of register-overwrite bugs. It is the recommended approach for any FC or FB that mixes indirect and fully qualified DB access.
Alternative Pattern: Use the DI Register for Indexed Access
The S7-1500 keeps a second register pair (DI) for instance DBs. DIW, DIB, and DID read against the DI register, which is not affected by "DB...".Tag fully qualified access. If the target data blocks are instances of a known FB, open them with OPN DI[Heat] and read with DIW:
OPN DI[Heat] // opens the instance DB at number Heat in the DI register
L DIW 360
L DIW 362
>=I
L DIW 360
T #G1_MaxTemp
This is the cleanest pattern when the indexed DB is always an instance of a particular FB type. It also removes the need to keep reopening after every fully qualified DB access, because the DI register is not touched by "MyDB".Tag references.
Alternative Pattern: Symbolic Multiplexing with the PEEK/POKE Helpers
For S7-1500/1200 projects that prefer symbolic-only code, a user-defined FB can wrap PEEK (read) and POKE (write) to a parameterized DB number. The wrapper hides the indexed STL altogether. The disadvantage is that PEEK/POKE operate on byte offsets and do not honour the DB's declared data type, so the calling code must keep offsets consistent with the DB structure.
| Pattern | Pros | Cons | When to use |
|---|---|---|---|
OPN DB[Heat] + indexed DBW
|
Direct, type-aware, fastest | DB register is volatile; reopen before every read | Performance-critical loops, large DBs |
Local copy of fully qualified tag + indexed DBW
|
Readable, register-safe | Extra local variable | FC/FB that mixes both access styles |
OPN DI[Heat] + indexed DIW
|
DB register never disturbed | Only works for instance DBs | Indexing across instances of the same FB |
| PEEK/POKE wrapper FB | Pure symbolic code | Byte-offset, no type checking | Configuration tools, HMI-driven DBs |
Verification Procedure
After applying the fix, verify the network behaves as intended. Use the S7-1500 online watch table and program-status tools available in TIA Portal V20.
-
Watch table setup. Create a watch table that contains:
-
MW110(theHeatmarker) -
DB131.DBW360,DB131.DBW362,DB131.DBW364 DB_L2_Cmd_OP_Transfert.G1_TEMP- The output tag
#G1_MaxTemp
-
-
Pre-condition. Force three distinct values into DBW360, DBW362, DBW364 (e.g., 100, 200, 300) and a threshold into
G1_TEMP(e.g., 50). -
Single-step the network. Right-click the network in the FC/FB and choose "Monitor with single step" (or use the STL debugger). Confirm that immediately before the first
L DBW 360, the DB register shows DB131 (visible in the CPU's register view under "STW / DB / DI"). -
Run cyclic. Set
MW110 := 131and confirm#G1_MaxTemptracks the maximum of the three DBW values that exceedsG1_TEMP. Repeat for MW110 := 132 with DB132 populated, and for MW110 := 133 with DB133 populated. -
Negative test. Set MW110 := 0 and confirm the network does not crash but
#G1_MaxTempis undefined or zero (DB0 returns zero for everyDBW). Add a range check onHeatbefore theOPNif the value can ever be zero.
Diagnostic Buffer and Error Codes
The S7-1500 rarely surfaces a hard error for a stale DB register, but it does log certain conditions in the diagnostic buffer:
| Event ID | Meaning | Likely cause |
|---|---|---|
| 0x2520 / 0x2530 | Data block not found / wrong number | MW110 contains a DB number that does not exist (e.g., 0, or a number above the configured max DB) |
| 0x35xx | I/O access error | Not relevant to pure DB reads |
| 0x5500 / 0x5501 | Programming error, area length violation | Indexed DBW offset larger than the open DB's length |
DBW reads return zero because DB0 is treated as the fallback. Add a L Heat; L 1; >=I; L Heat; L MaxDB; <=I; A "BIT1"; guard to suppress the network on invalid indices.Common Pitfalls and Field-Proven Caveats
-
Indexed
OPNwith a constant operand.OPN DB 131andOPN DB[MW110]behave identically with respect to the register; the difference is only in where the DB number comes from. The pitfall is mixing the indexed and fully qualified forms in the same network without reopening. -
Order of evaluation in STL. STL executes strictly top to bottom. The first fully qualified DB reference in the network wins, and every
DBWbelow it sees the new DB number. Reorder the network so all fully qualified reads come before the indexed reads, and copy the result into locals, or reopen the indexed DB after each fully qualified read. -
Symbol resolution in TIA Portal V20. If the target DB has the "Optimized block access" attribute, indexed
DBWaccess with absolute offsets is still permitted in STL but the offsets refer to the compiled layout, not the source order. Check the DB's properties and the "Offset" column in the data view. - Multi-instance DBs. For FBs that use multi-instances, the DI register is the natural place for indexed reads; the DB register is reserved for global DBs. Mixing them is a common source of subtle bugs.
-
AR1 / AR2 pointer side effects.
LAR1andLAR2with DB-relative addressing are independent of the DB register and are not disturbed by fully qualified access. They can be a robust alternative for very large, deeply indexed scans. -
Memory word type.
MW110must be wide enough to hold the maximum DB number. For projects that may exceed 32767 DBs, use aDWORDmarker andOD/ODinstructions;OPN DB[MW110]with a 16-bit MW caps at 32767.
S7-300/400 vs. S7-1500 Behaviour
Engineers who learned indirect DB access on S7-300/400 sometimes expect the DB register to be sticky until a new OPN is issued. On S7-300/400, fully qualified DB access writes the DB register, but a warning is logged in the diagnostic buffer more often. On S7-1500, the register is overwritten silently and the diagnostic buffer stays clean, which is why the symptom is "values are zero" rather than "addressing error." Treat the DB register as transient in both families, but verify with online monitoring on S7-1500 because no event is generated.
Commissioning Checklist
- Confirm
Heat(MW110) is a 16-bit (or 32-bit) marker that holds the active DB number; check the project default and the data type. - For every network that combines indexed and fully qualified DB access, place
OPN DB[Heat](orOPN DI[Heat]) immediately before the first indexed read of each branch. - If using the local-copy pattern, ensure the temporary is declared in the FC/FB interface with the correct data type (INT for
DBW, DINT forDBD). - In the watch table, monitor the DB register (visible in the CPU register view) while single-stepping the network. It should show the expected DB number at every
DBW/DIWread. - Add a range check on
Heatto preventOPN DB 0and out-of-range DB numbers. - For projects that must work on both S7-300/400 and S7-1500, prefer the
OPN DI[Heat]+DIWpattern; it is portable and avoids the DB register clash.
Summary
The OPN instruction in S7-1500 STL is correct and reliable. The "values are zero" symptom arises because fully qualified DB references inside the same network silently repoint the DB register away from the index-loaded DB. The robust patterns are: reopen DB[Heat] before every indexed read, copy fully qualified tags into locals and compare against those, or use the DI register pair with DIW/DIB/DID for instance DBs. Each pattern keeps the indexed and fully qualified access styles from interfering with each other, and each is verifiable in the TIA Portal V20 online watch table.
FAQ
Why does my S7-1500 STL network read DBW values as zero after OPN DB[Heat]?
Because a fully qualified DB access (for example, "DB_L2_Cmd_OP_Transfert".G1_TEMP) inside the same network silently overwrites the DB register. After the overwrite, every DBW is read from the wrong DB, and if the network reopens DB0, every value is zero. Reopen the indexed DB with OPN DB[Heat] immediately before each indexed read, or copy the fully qualified tag into a local variable first.
Is the OPN instruction different in S7-1500 STL compared to S7-300/400 STL?
The instruction itself is the same, but the S7-1500 overwrites the DB register on fully qualified symbolic access without raising a diagnostic event, whereas S7-300/400 often logs a warning. Treat the DB register as transient on both families and reissue OPN before any indexed read that follows a fully qualified reference.
Can I use OPN DI[Heat] with DIW to avoid the DB register problem?
Yes. OPN DI[Heat] opens the instance DB in the DI register pair, which is not disturbed by fully qualified "DB...".Tag access. Use DIW, DIB, and DID for indexed reads. This is the cleanest pattern for indexing across instances of the same FB.
What is the maximum DB number I can load with OPN DB[MW110]?
With a 16-bit MW, the maximum value is 32767. If your project may exceed that, use a 32-bit MD marker and confirm the S7-1500 firmware you are running supports the resulting index. S7-1500 CPUs as of firmware V2.0 support 16-bit OPN DB indices; the 32-bit form is permitted on newer firmware and is documented in the STL manual.
How do I confirm the DB register value during online monitoring in TIA Portal?
Open the online watch table or the program status view, then in the "Register" area of the S7-1500 online interface, monitor the DB and DI register contents. The register is updated on every OPN and on every fully qualified DB access. Single-stepping the network lets you see exactly which instruction changes the register and which indexed read is affected.