Writing Siemens S7-1200 PLC Tags: DB, Slice Access, and POKE

David Krause16 min read
SiemensTIA PortalTutorial / How-to
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

Overview of PLC Tag Writing Methods

Writing to PLC tags on a Siemens S7-1200 or S7-1500 controller is a routine commissioning and runtime task that can be performed from several engineering surfaces: TIA Portal logic (LAD/FBD/ST), HMI input fields on WinCC Comfort/Advanced/Professional, VB or C scripts inside WinCC runtime, the integrated CPU Web Server, and external S7 clients using the S7 communication protocol. Each surface has its own syntax, its own prerequisites, and its own pitfalls. The choice between them depends on whether the target data is a bit, byte, word, double word, or structured user-defined type, and whether the application demands symbolic or absolute addressing.

In TIA Portal V20 and later, the default programming model is fully symbolic. PLC tag names declared inside a data block (DB) become globally accessible symbols that the compiler resolves against the optimized or standard DB block. Older S7-300/400 habits of typing DB1.DBW20 directly into logic still work as absolute addressing, but TIA Portal surfaces a yellow warning icon in the cross-reference when an absolute address is referenced without a corresponding symbolic declaration. The recommended workflow is to declare every tag inside a DB with a name, data type, and (optionally) absolute address, and let the program reference the symbol.

This reference covers five practical methods for writing a tag value into the controller:

  1. Absolute DB addressing with DB1.DBW20, DB1.DBB0, DB1.DBX0.0, and DB1.DBD0.
  2. Symbolic tag addressing using the DB tag name as the symbol.
  3. Slice access for individual bits inside a UINT/WORD tag, using the %X0 through %X15 notation.
  4. POKE direct memory write from STL.
  5. Web Server AWP commands using HTTP POST/GET to write tags from a custom HTML page.
Engineering note: Use absolute addressing only for legacy code migration or when a SCADA/HMI driver explicitly publishes absolute addresses. For new programs in TIA Portal V17 and later, prefer symbolic access; the compiler and the online watch table both benefit from named tags.

Prerequisites and Environment

Before any tag-write method can be deployed, the following engineering prerequisites must be met:

  • Programming environment: TIA Portal V17, V18, V19, or V20 with the STEP 7 Basic or Professional component installed. The TIA Portal V20 reference documentation on Using tags within the program describes the structure of a variable as Name + Data type + Absolute address and confirms that PLC tags and DB variables in blocks with standard access expose an absolute address automatically.
  • PLC firmware: S7-1200 CPU firmware V4.0 or later (recommended V4.5 or V4.6 for the standard CPUs) or any S7-1500 firmware. The integrated Web Server is available on S7-1200 firmware V4.0+ and on all S7-1500 CPUs.
  • DB block attribute: The DB that contains the target tags must be created with Standard access (not Optimized) if absolute addressing (DB1.DBW20) is to be used directly from STL or from an HMI. Symbolic access can be either Standard or Optimized.
  • PLC tag table: Default tag table or a user-defined tag table with the relevant PLC tags declared for write operations from HMI panels that reference the PLC tag list (not the DB symbol).

Verifying the DB attribute is critical. Open the DB in TIA Portal, right-click the DB header, choose Properties, and on the Attributes tab confirm that Optimized block access is unchecked. If optimized block access is enabled, the absolute address DB1.DBW20 cannot be guaranteed at compile time because the compiler is free to reorder tags inside the block. Symbolic access still works in optimized blocks, but absolute addressing from external clients (HMI, SCADA, OPC UA) may need either an explicit AT construct or a non-optimized DB.

Absolute DB Addressing: DB1.DBW20 and Variants

Absolute addressing addresses the data block by its block number, the offset within the block by a byte address, and the bit offset within a byte. The mnemonic pattern is:

Data Width Syntax Example Bits Used
Bit DB<n>.DBX<b>.<bit> DB1.DBX0.0 1
Byte DB<n>.DBB<b> DB1.DBB0 8
Word (16-bit) DB<n>.DBW<b> DB1.DBW0 16
DWord (32-bit) DB<n>.DBD<b> DB1.DBD0 32

The byte offset b is always on byte boundaries; bit access uses DBX<b>.<bit> where <bit> is 0 to 7. Writing a value with absolute addressing in STL looks like this:

L      0                        // Load constant 0 into ACCU1
T     "DB_name".DBW20           // Transfer to DB1 word at byte 20
T     "DB_name".DBW22           // Transfer to DB1 word at byte 22
T     "DB_name".DBW24           // Transfer to DB1 word at byte 24

The same operation in Structured Text (SCL) is written symbolically but compiles down to the same machine code:

"DB_name".FUNKCUSKA_TIPKA := 0;
"DB_name".FUNKCUSKA_TIPKB := 0;
"DB_name".FUNKCUSKA_TIPKC := 0;

When TIA Portal flags a yellow warning on the absolute reference, the message reads "Direct access to operand in standard block". The warning does not block compilation or download; it is a code-quality hint that the program is referencing an address that has not been bound to a symbol. To clear the warning, declare the symbol with the same byte offset inside the DB block:

  1. Open the DB in the project tree.
  2. Right-click the row at the desired byte offset and select Add new row.
  3. Enter the tag name, choose Word or Bool as the data type, and confirm the Address column reflects %DB1.DBW20.
  4. Replace all DB1.DBW20 references with the new tag symbol.
Caution: Mismatching the DB number in the absolute path (for example DB2.DBW20 instead of DB1.DBW20) will compile cleanly but write to the wrong block at runtime. Always confirm the DB number from the project tree, not from the address string in the cross-reference.

Symbolic Tag Addressing in DB Blocks

Symbolic addressing names a tag at declaration time and references the tag by its name throughout the program. This is the TIA Portal V20 default for both S7-1200 and S7-1500 controllers. A symbolic tag declaration inside a DB has three required fields:

Field Purpose Example
Name The symbol referenced in code FUNKCUSKA_TIPKA
Data type Bit width and semantics UINT, BOOL, REAL
Address Optional; the absolute offset the compiler will assign %DB1.DBW20

Once declared, the symbol is used in every code segment. A typical clear-all routine in LAD looks like:

      "DB_name".FUNKCUSKA_TIPKA       // MOVE 0 to the tag
      "DB_name".FUNKCUSKA_TIPKB
      "DB_name".FUNKCUSKA_TIPKC
      |
      +---( MOVE )--- 0

In STL the same intent is expressed with three transfer instructions (or a loop using a tag-indexed pointer, but the simple form is preferred for clarity):

L      0
T     "DB_name".FUNKCUSKA_TIPKA
T     "DB_name".FUNKCUSKA_TIPKB
T     "DB_name".FUNKCUSKA_TIPKC

Symbolic addressing carries three operational advantages over absolute addressing:

  • Compiler-managed offsets. If a tag is inserted or removed in the middle of the DB, the compiler reassigns addresses. Code that uses symbols continues to compile; code that uses absolute addresses silently shifts target bytes and produces runtime bugs.
  • Cross-reference integrity. The cross-reference (Ctrl+Shift+F in TIA Portal) tracks every reference to a symbol. Absolute-only references appear with a yellow warning and no symbol link.
  • HMI/SCADA binding. WinCC Comfort and WinCC Professional automatically populate the HMI tag list with symbolic DB tags when the HMI is configured against the PLC project. No manual entry of DB1.DBW20 is required.

Slice Access for Bit-Level Operations

Slice access (German Slicen) exposes individual bits of a multi-bit tag without forcing a separate BOOL tag declaration. The syntax is "<tag_name>".%X<bit>, where <bit> is the zero-based bit index inside the tag. A 16-bit UINT or WORD tag therefore has slice indices 0 through 15.

Consider a tag FUNKCUSKA_TIPKA declared as UINT in DB1 at byte offset 20. Mapping bit indexes 0, 1, and 15 to bit addresses 20.0, 20.1, and 20.15 yields the following slice references:

"DB_name".FUNKCUSKA_TIPKA.%X0   // 20.0
"DB_name".FUNKCUSKA_TIPKA.%X1   // 20.1
"DB_name".FUNKCUSKA_TIPKA.%X15  // 20.15

Slice access is most useful when many boolean flags are packed into a single UINT for HMI handshaking (one bit per button, one bit per status LED). Writing a value with slices is identical to writing any BOOL tag:

L      0
T     "DB_name".FUNKCUSKA_TIPKA.%X0
T     "DB_name".FUNKCUSKA_TIPKA.%X1
T     "DB_name".FUNKCUSKA_TIPKA.%X15

The underlying memory is the same as absolute addressing — a 16-bit WORD at byte 20 of DB1 — but the symbolic name combined with the bit index eliminates the need to maintain parallel BOOL declarations for each flag.

Engineering note: Slice access is permitted on BYTE, WORD, DWORD, INT, UINT, DINT, UDINT, SINT, USINT, REAL, LREAL, and CHAR/WCHAR tags. It is not permitted on BOOL, STRING, or STRUCT tags. Attempting to slice a STRING results in a compile error.

POKE Function for Direct Memory Access

The POKE instruction in STL writes directly to any memory area: inputs (POKE_I), outputs (POKE_Q), merkers (POKE_M), or DB (POKE_D). Unlike symbolic or absolute DB addressing, POKE does not require the target to be declared as a tag in any block; it writes to the absolute byte address supplied in the operand. POKE is sometimes called a "cheat" because it bypasses the symbolic model that TIA Portal enforces, but it remains the right tool when porting legacy S7-300/400 STL code or when a runtime pointer is required.

Syntax for POKE to a data block word:

CALL  POKE
     SrcBlock   := DB1
     SrcByteOffset := 0
     SrcValue   := W#16#1234
     DestBlock  := DB1
     DestByteOffset := 20
     DestArea   := DB
     DestWordLen := W

For bit-level writes inside a DB, POKE does not directly take a bit offset; the program must write to the containing byte and then mask the bits in ACCU1. The more common pattern is to use absolute DB addressing with DB1.DBX20.0 or symbolic addressing with the slice access described above. POKE is best reserved for the case where the target DB number or byte offset is computed at runtime from another tag:

L     "runtime_db_number"          // Load dynamic DB number
T     #t_db_no
L     "runtime_byte_offset"        // Load dynamic byte offset
T     #t_byte
L     W#16#0001                    // Bit pattern to write
T     "DB_any".DBW[#t_byte]        // Index-based write

POKE requires that the destination block is not optimized and that the runtime authentication level in the PLC security settings allows write access to absolute addresses from external sources. If the PLC is configured with the default write-protection, POKE from an HMI or from external S7 clients is rejected.

Web Server AWP Commands for Browser-Based Tag Writing

S7-1200 firmware V4.0 and all S7-1500 CPUs ship with an integrated Web Server that serves HTML pages authored in the TIA Portal project tree. AWP (Automation Web Programming) commands are Siemens-specific HTML extensions that bind PLC tags to HTML elements. The Web Server can both read and write tags: the IN direction is CPU-to-browser (display); the OUT direction is browser-to-CPU (write). IN tags are placed on a form so the browser can submit them back to the CPU.

A minimal custom page that writes to a PLC tag is:

<!-- AWP: In_Variable = '"MyDB".MyTag' -->
<html>
<head><title>Write Tag</title></head>
<body>
<form method="POST" action="">
  <input type="text" name='<!-- AWP_Out_Variable Name = "" -->' />
  <input type="hidden" name='<!-- AWP_Out_Variable Name = "MyDB".MyTag" -->'
         value='<!-- AWP_In_Variable Name = '"MyDB".MyTag"' -->' />
  <input type="submit" value="Write" />
</form>
</body>
</html>

The four AWP command variants used for tag write are:

Command Direction Transport Use Case
:<!-- AWP_In_Variable Name = ... --> CPU to browser HTML value attribute, GET or POST Display current value on the page
:<!-- AWP_Out_Variable Name = ... --> Browser to CPU Form submission via GET or POST Write a new value into the tag
:<!-- AWP_Enum_Def Name = ... --> Static Compile time Map tag value to text label
:<!-- AWP_Command_... --> Browser to CPU Form submit Trigger control commands (e.g., set/reset a bit)

Three field-proven rules when deploying AWP pages:

  1. The CPU Web Server must be enabled in Device Configuration > Web Server, and "Allow read/write access from a custom web page" must be checked for any tag write to succeed.
  2. The tag must be in a DB that is Standard access or in the global PLC tag table. Tags inside an Optimized DB can be read via AWP but writing may be blocked by the read-only check at submit time.
  3. The HTTP method (GET vs. POST) determines how the tag value travels to the CPU. GET places the value in the URL query string (visible in the browser address bar, limited to roughly 2 KB). POST places the value in the request body (invisible, recommended for production).
Security warning: An AWP page with write capability exposed on the plant network is a direct tag-write attack surface. Enable Web Server user authentication (introduced in S7-1200 firmware V4.5) and restrict the page to a VLAN that is isolated from the office network.

WinCC Integration: HMI Input Fields and VB Scripts

WinCC Comfort, Advanced, and Professional panels and runtime PC systems offer three surfaces for tag writing that do not require code in the PLC:

Surface Trigger Use Case Driver
Input field Operator types value, presses Enter or tab Manual setpoint entry, recipe selection S7 direct, OPC UA
Button with tag action Operator presses button One-shot writes (start, stop, reset) S7 direct, OPC UA
VB/C script Scheduled, event, or button-triggered Computed values, conditional writes Tag I/O interface or S7 connection

An Input Field on a WinCC screen is the simplest path: drag the DB tag into the screen, change the property Configuration > Mode to Input/output, and configure the limits and the on-write event. The HMI driver writes the value into the PLC on tag change; no code in the PLC is required.

A WinCC VB script that writes a tag from runtime uses the SmartTag interface:

Sub WriteValue()
    Dim tagVal
    Set tagVal = SmartTags("MyDB.MyTag")
    tagVal.QualityCode = 0        // 0 = Good
    tagVal.Value = 1234
    SmartTags("MyDB.MyTag") = tagVal
End Sub

The script above must be attached to an event — typically a button click or a scheduled timer — for the write to fire. The HMI's internal PLC connection handles the S7 protocol write; no additional configuration is needed.

Best Practices: Symbolic vs Absolute Addressing

A consistent tagging policy avoids the yellow-warning cascade that older TIA Portal projects accumulate. The recommended pattern is:

  1. Declare every tag inside a DB with a name, data type, and (optionally) a comment. Avoid relying on absolute addresses for any tag that is referenced more than once.
  2. Use Standard access DBs when external HMI or SCADA systems need to read the absolute address. Use Optimized access only when the project is fully internal and the HMI is configured symbolically.
  3. Group flag bits into a UINT or WORD when there are more than four boolean flags for the same subsystem, and access them via slice notation (%X0, %X1, ...).
  4. Reserve POKE for runtime-computed DB numbers and byte offsets. Avoid POKE for static tag writes; the symbol path is faster to author and easier to maintain.
  5. When porting legacy STL from S7-300/400, leave the absolute DB syntax in place temporarily but add a parallel symbolic declaration so the cross-reference resolves. Replace the absolute references one by one in subsequent revisions.
  6. Use AWP only for read-only displays and ad-hoc commissioning interfaces. Production write paths should go through the HMI tag system or through an OPC UA server, not through the Web Server, unless the panel/PC is isolated from the office network.

Verification and Commissioning

After any tag-write method is configured, verify the write path end-to-end with the following checklist:

  1. Online & Diagnostics: In TIA Portal, right-click the PLC and select Online & Diagnostics > Watch tables. Create a new watch table, add the symbolic tag, force a write from the HMI or script, and confirm the value updates in the watch table within one OB1 cycle.
  2. Monitor & Force: Toggle Monitor on the DB and confirm the yellow online value updates as expected. If the value does not change, the DB is likely Optimized and the external client is writing to a stale symbol — switch to Standard access or re-bind the symbol in the HMI tag list.
  3. Cross-reference integrity: Open the cross-reference for the tag (Ctrl+Shift+F). Every reference — program, HMI, watch table — should appear. A reference that does not appear means the symbol is not bound and the write target is the wrong tag.
  4. AWP round-trip test: Open the custom Web Server page in a browser, type a value, submit the form, and confirm the value appears in the watch table within one second. If it does not, check that the Allow write access from custom web page option is enabled in the CPU's Web Server settings.
  5. WinCC tag diagnostics: In WinCC Runtime, open the tag diagnostics view (Tools > Tag Debug). Confirm the connection state is green and the Quality Code on the written tag returns to Good (0xC0) after the write.

If the watch table shows the value change but the application logic does not react, the issue is almost always in the program: the tag is being overwritten somewhere else in the same OB cycle. Search the cross-reference for every assignment of the tag and verify the intended logic.

Troubleshooting Matrix

Symptom Likely Cause Resolution
Yellow warning on DB1.DBW20 reference Tag not declared symbolically Add the tag to the DB with matching byte offset
Write succeeds in watch table but program ignores it Another tag or function block overwrites the value Search the cross-reference for the tag and audit the OB1 cycle
AWP page loads but form submission does not change the tag Web Server write access disabled Enable Allow write access from custom web page in the CPU Web Server properties
WinCC input field does not update the PLC HMI tag list references wrong DB number Rebuild the HMI tag from the symbolic DB reference, not from an absolute address
Slice access %X15 fails to compile Tag data type too narrow Confirm the tag is at least 16 bits (WORD/UINT/INT) before slicing bit 15
POKE writes to the wrong byte Source and destination offsets swapped Verify SrcByteOffset and DestByteOffset arguments
TIA Portal rebuilds the project but absolute offsets shift DB is configured Optimized Change DB to Standard access, recompile, re-download
External S7 client receives a quality bad on write CPU write-protection enabled Adjust the protection level under Device Configuration > Security

Frequently Asked Questions

How do I write to DB1.DBW20 from STL in TIA Portal?

Load the value into ACCU1 with L 0 (or any constant) and transfer it with T "DB_name".DBW20. The DB must be configured with Standard access; otherwise the absolute address is not guaranteed. For symbolic write, declare a tag inside the DB at offset 20 and reference the tag symbol directly.

Can I use slice access like %X0 on an S7-1200 DB tag?

Yes, in TIA Portal V14 and later, slice access on BYTE, WORD, DWORD, INT, UINT, DINT, UDINT, SINT, USINT, REAL, LREAL, and CHAR tags is permitted. The syntax is "DB_name".TAGNAME.%X<bit>, where bit ranges from 0 to (width - 1). Slice access is rejected on BOOL, STRING, and STRUCT tags.

Why does my custom Web Server page not write back to the tag?

Two checks are required: the CPU Web Server property Allow write access from a custom web page must be enabled, and the target tag must be declared as a PLC tag or inside a Standard-access DB. The HTML form must include an AWP_Out_Variable directive so the browser knows which form field maps to which PLC tag.

What is the difference between symbolic and absolute addressing in TIA Portal?

Symbolic addressing references a tag by its name (declared in a DB or PLC tag table); absolute addressing references a tag by its byte offset and bit index (e.g., DB1.DBW20). Symbolic access survives DB reordering; absolute access does not. TIA Portal warns on absolute access because future edits can silently shift the target.

Should I use POKE or symbolic assignment to clear a block of tags?

Prefer symbolic assignment for static tag lists. POKE is appropriate when the target DB number or byte offset is computed at runtime (dynamic DB switching, indirect addressing). For a fixed set of tags at known offsets, three or four symbolic MOVE blocks are easier to maintain than POKE.

How do I bind an HMI input field to a DB tag in WinCC?

In the HMI configuration, drag the DB tag from the project tree onto the screen. Configure the input field properties to Mode = Input/output and set the desired limits. The HMI tag is created automatically against the DB tag symbol; the runtime write is handled by the HMI driver over S7 or OPC UA.

Back to blog