Converting S5 to S7: Migrating DX, DO, and Pointer Logic

David Krause14 min read
S7-300SiemensTutorial / 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

1. S5 to S7 Conversion Overview

The Siemens STEP 5 to STEP 7 Converter (also referenced as "Converting S5 Files") automates the structural migration of *.S5D program files into the STEP 7 (S7) project environment. The converter translates most operators 1:1 but leaves several constructs that require manual post-editing, especially those involving the S5-specific data block categories (DX), area-internal indirect addressing (DO), 16-bit fixed-point constants (KF), and the 16-bit S5 pointer format. This article walks through a real S5 snippet, runs it through the converter, and performs the manual corrections required to produce functionally equivalent S7 code on an S7-300 CPU (the typical drop-in replacement for legacy S5-115U/135U/155U controllers).

The official reference for this process is the Siemens manual "From S5 to S7", entry ID 45531547, available as PDF download and SIOS entry 45531547. Section 3.13 of that manual is dedicated to the address-conversion challenges covered here.

2. Prerequisites

Before running the converter, ensure the following are installed and available:

  • STEP 7 V5.x (V5.5 SPx recommended) - the converter is a STEP 7 classic tool and is not available in TIA Portal.
  • A configured S7-300 or S7-400 station with a CPU that supports the required program size (S7-31xC or S7-31xT for most S5-115U replacements).
  • The original STEP 5 source file (*.S5D) including the symbol table (*.Z0/*.SEQ) and any DX/DB cross-reference list (*.XR).
  • A backup of the S5 program, since the converter consumes a working copy.
  • SIMATIC Manager open with a writable S7 project that contains a target station of the correct family.
Note: The STEP 5 to S7 converter runs inside SIMATIC Manager. It is invoked by selecting Options → Converting S5 Files after a target S7 program container has been created. It is not a TIA Portal action.

3. The S5 Source Program

The starting S5 program is shown below. It is a small STL block fragment that initializes two flag words, opens an extended data block (DX 80), performs an indirect read from that block using a flag word as the data offset, and writes the result into FW 200.

:L   KF  +0        // Load fixed-point constant 0 into ACCU 1
:T   FW  206      // Transfer ACCU 1-L to flag word 206
:T   FW  208      // Transfer ACCU 1-L to flag word 208
:CX  DX   80      // Open extended data block 80 (DX)
:DO  FW  244      // Use FW 244 as the indirect byte offset for DW
:L   DW    0      // Load data word at (base + offset) into ACCU 1
:T   FW  200      // Transfer ACCU 1-L to flag word 200

Each S5 operator is explained in §3.1–§3.4, because the converter's output is only intelligible once the S5 semantics are understood.

3.1 KF - 16-bit Fixed-Point Constant

KF denotes a 16-bit signed integer constant in the range -32768 to +32767. The leading + is optional. In S7, this becomes a direct integer literal in an L statement; the KF keyword is dropped.

3.2 T FW - Transfer to Flag Word

S5 "flag" memory is the equivalent of S7 "Merkers" (M memory). FW n is a 16-bit aligned word; FY n and FD n are the byte/double-word views. The converter renames FW to MW automatically. Address ranges map 1:1: S5 FW 0-254 corresponds to S7 MW 0-254.

3.3 CX DX - Open Extended Data Block

S5 supports several data block classes: DB (data block), DX (extended data block), and historically SB (sequence block). The CX (or C) operator opens the referenced block, which is the current block for subsequent L DW or T DW operations. In S7, all of these classes are unified as DB. The S5-to-S7 converter will translate the block number (e.g., DX 80 → DB 80) but will not create the DB body; that must be imported manually from the original *.S5D DX definition or recompiled from the S5 source.

3.4 DO - Indirect Data-Word Offset

The DO FW n operator preloads the address register used for the subsequent L DW / T DW access. In S5, the value of FW n is interpreted as a signed 16-bit byte offset (range -32768 to +32767) added to the base address of the currently opened data block. S7 implements the same behavior with the area-internal pointer DBW[MD n], but the storage format inside MD n is a 32-bit pointer in the P#byte.bit form, not a 16-bit byte offset. This is the single largest source of post-conversion bugs.

4. The S5 Memory Model vs S7 Memory Model

Region S5 Name S7 Name Address Width Notes
Flag/Marker F (FW/FY/FD) M (MW/MB/MD) 1 byte / 1 word / 2 words 1:1 mapping; byte ordering is the same on S7-300/400.
Input I (IW/IB/ID) I (IW/IB/ID) Same Process image is rebuilt on S7 side.
Output Q (QW/QB/QD) Q (QW/QB/QD) Same Same as input.
Data block (DB) DB DB Up to 64 KB (S7-400); up to 16 KB on most S7-300 CPUs Direct equivalent.
Extended data block DX DB Same as DB Unified; number may need to be remapped to fit S7 DB range (0–16000 on S7-300, 0–65535 on S7-400).
Sequence block SB DB / FB Program step memory No direct equivalent; must be hand-rewritten as FB or subroutine.
Timer / Counter T / C T / C Different instance DBs Counters/timers use IEC 0-511 range; values are BCD on S5, INT/BCD on S7.

5. ACCU and Status Word Differences

The S5 CPU has a two-accumulator architecture (ACCU 1 and ACCU 2) with a status word (STW) at the start of each operation. S7-300/400 also has a two-accumulator architecture, but the STW layout is reorganized and the meaning of /FC, RLO, and OR is identical at the binary level. The S5-to-S7 converter emits two temporary variables, conv_akku1 (DWORD) and conv_stw (WORD), in the temporary local stack of the converted block whenever the source code intermixes operations that, on S5, implicitly rely on the carry, overflow, or result bit being read in the next network. The converter preserves any cross-network ACCU state by spilling it to conv_akku1 at network boundaries. These two variables must not be deleted or renamed, and they must not be declared in any other block's TEMP section.

Tip: If the converted block fails to compile with a "Duplicate TEMP symbol" error, search the whole program for a previous conv_akku1 declaration; the converter may have re-inserted it because the source was previously converted and saved.

6. Running the Converter

  1. Open SIMATIC Manager and select the S7 program (S7-300 station → S7 Program → Blocks).
  2. Choose Options → Converting S5 Files.
  3. Browse to the *.S5D file. The dialog reports the number of detected PB/OB/SB/FB/DB/DX blocks.
  4. Assign a target S7 block number to each S5 block. The converter will warn if a target number is already in use.
  5. Click Convert. The resulting S7 source files are placed in the Sources container of the S7 program.
  6. Open each generated STL source and compile it with File → Compile (or right-click → Compile).

The conversion log is written to a text file in the source directory. Read it carefully - the converter annotates each non-translatable line with a comment beginning with // *** CONV ***.

7. Auto-Generated S7 Code (Pre-Manual-Fix)

Running the converter on the S5 source in §3 yields, after compilation, the following STL output:

      L   0
      T   MW 206
      T   MW 208
AUF   DB  80              // DX 80 -> DB 80 (auto)
      L   DBW [MD 244]    // DO FW 244 -> DBW[MD 244] (auto)
      T   MW 200

This compiles without error, but it is not functionally equivalent to the S5 source. Three classes of error are present:

  1. The DB 80 body has not been imported; if DB 80 does not yet exist, the CPU will go to SF (system fault) at first access with error SF: DB not loaded / SF LED + SF on the diagnostic buffer entry "OB loading error / DB not present".
  2. MD 244 is interpreted as a 32-bit area-internal pointer in P#byte.bit format. The S5 program stores a 16-bit byte offset in FW 244. The two formats are not interchangeable.
  3. The conv_akku1 / conv_stw temporaries are not yet declared in the block's TEMP area, because the S5 snippet is too short to trigger the converter's spill heuristics. For this snippet they are not required, but they will appear in any non-trivial converted block.

8. Manual Correction 1 - DX 80 to DB 80

The DX data block must be transferred as a DB. Two methods are supported:

8.1 Re-import from STEP 5 source

If the original *.S5D contains the DX 80 in textual form, paste the data values into a new DB source:

DATA_BLOCK DB 80
TITLE = 'Migrated from DX 80'
VERSION : 0.1
  STRUCT
   DW0   : WORD  := W#16#0;
   DW2   : WORD  := W#16#0;
   DW4   : INT   := 0;
   (...etc...)
  END_STRUCT ;
END_DATA_BLOCK

8.2 Byte-wise copy from DX 80 dump

If only a binary DX dump is available, use the converter's Convert DX option (when present) or write a small S7 FB that reads the S5 online dump and re-stores it into DB 80. The DB number 80 is preserved because it fits inside the S7-300 DB range (0-16000) and the S7-400 range (0-65535).

Note: If DX 80 was numbered 200-255 on an S5-155U, verify that the target CPU supports DB numbers in that range. S7-31xC CPUs cap at DB 16000. If the DX number is outside the S7 DB range, remap to a free DB number and update every AUF DB reference in the converted code (search-and-replace in the Sources container).

9. Manual Correction 2 - S5 Pointer to S7 Pointer

The S5 source assumes that FW 244 is loaded elsewhere with a 16-bit byte offset such as 0, 2, 4, …, 254. The S7 DBW[MD 244] construct, however, requires the full 32-bit area-internal pointer format:

Field Bit range Meaning Example (P#100.0)
Bit address 0-2 0-7 → bit position inside the byte 000₂ = 0
Byte address 3-31 Byte offset (always on byte boundary for DBW) 0x0064 = 100

The on-wire integer value of the pointer is therefore byte_offset * 8 + bit_number. For the common case where DBW access is on a word boundary and bit 0 is irrelevant, the conversion is:

  MD 244 (S7)  =  FW 244 (S5) * 8

Two ways to apply this in the S7 program:

9.1 Pre-multiply in the load routine (recommended)

Wherever the S5 program sets FW 244, change it to load MD 244 and multiply by 8:

      L   #byteOffset      // 16-bit signed offset (was FW 244 in S5)
      ITD                   // -> 32-bit signed
      SLD   3               // logical shift left by 3 = multiply by 8
      T   MD 244            // P#pointer in S7 format

Now the original S7 line L DBW [MD 244] behaves identically to L DW 0 + DO FW 244 in S5.

9.2 Use AR1 with P# arithmetic (alternative)

For more complex indirect logic, the cleaner pattern is:

      L   P#0.0
      L   MD 244            // assumes MD 244 is already a P# pointer
      +D
      LAR1
      L   DBW [AR1, P#0.0]

Either pattern works; choose 9.1 if the S5 program only used byte offsets, and 9.2 if the S5 program already composed the pointer in any nontrivial way.

10. Manual Correction 3 - ACCU Spill / Temporary Variables

The converter auto-declares conv_akku1 (DWORD) and conv_stw (WORD) in the converted block's TEMP section whenever the S5 source references result bits (AN, AB, OS, OV) across network boundaries or interleaves load/transfer with jump/compare operations on ACCU 1-L. Manual addition is rarely needed for small blocks. If a converted block has an undeclared conv_akku1 reference, declare the symbol in the block's TEMP area:

VAR_TEMP
  conv_akku1 : DWORD;
  conv_stw   : WORD;
END_VAR

11. Final S7 Source

After applying §8 (DB 80 created) and §9.1 (offset * 8 stored in MD 244), the converted block reads:

      L   0
      T   MW 206
      T   MW 208
AUF   DB  80
      L   DBW [MD 244]
      T   MW 200

This is now functionally identical to the S5 source, assuming MD 244 is populated as a P# pointer by an upstream network.

12. Verification Procedure

  1. Compile the S7 program. Address-overlap errors (e.g., MW 244 used in two blocks) will surface here.
  2. Download to the S7-300 CPU in STOP mode. Watch the diagnostic buffer for any DB-load or pointer-format SF entries.
  3. Run a single scan with PG online monitor. Watch ACCU 1 and MD 244 in the converted block; verify the value of MD 244 is a multiple of 8 when DBW[MD 244] is read.
  4. Force MD 244 = 0, 8, 16, 80, 800 (0x320) to exercise small and large offsets. Verify DBW at each is read without SF.
  5. Compare MW 200 against the S5 reference value read from the same data on the S5-115U/135U. Tolerance: exact match (DWORD load, WORD transfer, no scaling).
  6. Diagnostic buffer check: confirm no event 0x2520 (OB not loaded), no event 0x2942 (DB not present), no event 0x2521 (DX substituted) which would indicate the converter left an unresolved DX reference.

13. Troubleshooting Matrix

Symptom SF / Event Likely Root Cause Fix
CPU goes to STOP at first DB 80 access 0x2520 / 0x2942 DB 80 not present Import DX 80 as DB 80 (§8).
CPU goes to STOP, "Area length error" 0x2522 / 0x2530 MD 244 (P#) points past end of DB 80 Clamp pointer to DB length; check upstream offset math.
Read returns wrong word (off by N words) None MD 244 is byte offset, not P# Multiply offset by 8 (§9.1).
Compile error "Unknown operator CX" Compiler Source not run through converter Re-run §6; do not hand-paste S5 into STEP 7 STL.
Compile error "DB number 240 not allowed on this CPU" Compiler DX number outside S7-300 DB range Remap to a free DB ≤ 16000; update AUF DB.
Compile error "Unknown symbol conv_akku1" Compiler TEMP not declared Add §10 declaration.
Conv_log.txt lists "*** Operator SB not supported ***" Converter log Sequence block in source Manually rewrite as FB with STEP / SPL logic.
Run-time: output toggles in wrong order None Status word spill missing between networks Add conv_akku1 / conv_stw (uncommon; converter usually handles this).

14. Field-Proven Caveats

  • The S5 KF is 16-bit signed; an out-of-range value (> 32767 or < -32768) in the S5 program must be carried over as an S7 INT literal. The compiler will catch a too-large literal only when the source is set to Symbolic; in STL with an L statement, an out-of-range value is silently truncated at download. Always validate the source range before conversion.
  • S5 BCD timers and counters (T 0-127, C 0-127) are stored in BCD; S7 timers/counters (T 0-511) are stored in BCD on S7-300/400 but the value layout is identical. Cross-conversion is direct. If the project is later moved to TIA Portal / S7-1200/1500, the IEC timer DBs and S5TIME / TIME data types diverge - that migration is out of scope here.
  • S5 program blocks numbered 0-255 may overlap the S7 OB/FB/DB numbering conventions. The converter reassigns block numbers during conversion; the conversion log records the new numbers. Document the old → new mapping in the S7 project's Documentation folder.
  • If the original S5 program uses DO FW 0 as a scratch offset and the value is never initialized, the S7 code will read whatever was last loaded into MD 0 (an S7 M-flag, often part of the watchdog). Always pre-initialize MD 0 / the indirect offset to a known safe value at startup (OB100).
  • The converter does not translate S5 JU / JC relative jumps to S7 labels automatically in all firmware versions of STEP 7; the worst case is a hand-rewritten jump table. Validate every SPB / SPM / SPA target in the converted code.

What is the difference between DX and DB in STEP 5, and how is DX handled in S7?

STEP 5 distinguishes DB (data block) from DX (extended data block) and SB (sequence block) by class, with the CX / C operator selecting the class. STEP 7 unifies all of these into DB. The S5-to-S7 converter renames DX 80 to DB 80 automatically, but the DB body must still be imported from the STEP 5 source or re-entered by hand; the converter does not generate the data values.

How do I convert an S5 16-bit byte offset (FW) to an S7 32-bit P# pointer (MD)?

Multiply the 16-bit offset by 8 and store the result in the corresponding 32-bit MD. In STL: L <offset>; ITD; SLD 3; T MD <n>. The S7 DBW[MD n] form then reads the same byte as the S5 DO FW n; L DW 0 did.

What are the conv_akku1 and conv_stw temporary variables in the converted S7 block?

They are auto-generated DWORD and WORD temporaries inserted by the S5-to-S7 converter to spill ACCU 1 and the status word across network boundaries, because the S5 CPU allowed cross-network ACCU state while S7 STL does not. They must be declared in the block's VAR_TEMP section and must not be deleted, renamed, or duplicated across blocks.

Why does the S7 CPU go to STOP with "DB not loaded" after conversion?

The converter renames the DX number to a DB number but does not import the DB body. The DB must be re-entered from the STEP 5 source data or created with the same data structure. On S7-300, the DB number must be in the range 0–16000; on S7-400, 0–65535. An out-of-range DB number from a legacy S5-155U (e.g., DX 200–255) will also trigger the same STOP.

Can the S5 to S7 converter be used in TIA Portal?

No. The S5-to-S7 converter is a STEP 7 V5.x tool only. TIA Portal does not import S5 programs directly. The standard migration path is S5 → STEP 7 V5.x (using the converter) → TIA Portal (using the TIA "Migrate project" function on the STEP 7 V5.x project). The pointer and DX corrections described in this article are still required at the V5.x stage before migrating to TIA Portal.

Back to blog