Converting REAL to S5T# Timer Format on Siemens S7-300/400 PLCs

David Krause11 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

Overview

On Siemens S7-300 and S7-400 controllers, legacy SIMATIC timers (S5T# format) and IEC timers (SFB3/SFB4/SFB5) accept preset values encoded as 16-bit BCD words with a time-base nibble. When a calculation in the user program produces a floating-point time value (e.g. 0.5 s from a PID output, scaling block, or flow totalizer), that REAL must be scaled, rounded, and re-encoded before it can be loaded into a timer's TV input. This reference documents the bit layout, the STL conversion sequence, the clamping limits, and the SFB-based alternatives that avoid the legacy S5T# encoding entirely.

The conversion technique below works in STEP 7 V5.x and the legacy S7-300/400 instruction set. On S7-1200/1500, the IEC timers (TP, TON, TOF) accept TIME/LTIME directly, so this conversion is unnecessary on those platforms.

S5T# Time Format Specification

The 16-bit S5T# word is divided into a 2-bit time base (bits 15-14) and a 14-bit BCD value (bits 13-0). The time base selects the resolution applied to the BCD count.

Time base (bits 15-14) Resolution BCD range Effective range Hex base word
00 0.01 s (10 ms) 000 - 999 10 ms - 9.99 s W#16#0000
01 0.1 s (100 ms) 000 - 999 0.1 s - 99.9 s W#16#1000
10 1 s 000 - 999 1 s - 999 s W#16#2000
11 10 s 000 - 999 10 s - 9990 s W#16#3000

The absolute maximum addressable interval is S5T#9990s (2 h 46 min 30 s). Any value above this must be clamped to W#16#3999; the CPU will reject a malformed word with no specific error code at the timer call, but the timer will simply not start.

Prerequisites

  • STEP 7 V5.5 SP2 or later, or compatible TIA Portal version with S7-300/S7-400 support
  • Firmware on the S7-300 CPU ≥ V2.0 (required for all timer SFBs); for S7-400 any standard firmware works
  • REAL variable holding the desired delay in seconds (e.g. REAL_TimeValue in a DB or local temp)
  • WORD variable declared as the S5T# target (e.g. S5_TimeValue in the same DB)
  • Optional: instance DB for SFB4 (IEC TON) if the conversion is to be bypassed

Method 1 - STL Conversion Sequence

The reference STL sequence below accepts a positive REAL in seconds, clamps it to the legal S5T# range, selects the correct time base, rounds the mantissa, converts to BCD with DTB, and OR-s the time-base marker. This mirrors the classic implementation originally posted in the SIMATIC support archives.

// Input: REAL_TimeValue  (seconds, >= 0)
// Output: S5_TimeValue   (WORD in S5T# format)
      L   #REAL_TimeValue
      ABS                         // Force positive mantissa
      L   9.990000e+003           // 9990 s = S5T# maximum
      >R
      SPB max                     // If input > 9990, jump to max clamp

      TAK                         // Restore REAL on ACCU1
      L   1.000000e+002           // Scale 100x: 0.01 s resolution
      *R
      RND                         // Round to DINT milliseconds
      L   999
      >D
      TAK
      SPB M01                     // <= 999 ms branch (10 ms base)

      DTB                         // Convert ACCU1-L to BCD
      SPA end

M01:  L   9990
      >D
      TAK
      SPB M10                     // 1000 - 9990 ms branch (0.1 s base)
      DTB
      SRD  4                      // Shift BCD right 4 bits = 0.1 s base
      L   W#16#1000
      OW
      SPA end

M10:  L   L#99900                 // 99900 centiseconds = 999 s
      >D
      TAK
      SPB M11                     // 10 - 999 s branch (1 s base)
      DTB
      SRD  8                      // Shift BCD right 8 bits = 1 s base
      L   W#16#2000
      OW
      SPA end

M11:  DTB
      SRD  12                     // Shift BCD right 12 bits = 10 s base
      L   W#16#3000
      OW
      SPA end

max:  L   W#16#3999               // Hard clamp at 9990 s
end:  T   #S5_TimeValue

Key points in the sequence:

  • ABS discards any sign; S5T# does not support negative intervals.
  • SPB max clamps the input to the highest legal S5T# value before any further arithmetic - this prevents overflow in the BCD conversion.
  • DTB (DINT-to-BCD) is the CPU built-in; it expects a 32-bit DINT and produces a packed BCD result in ACCU1-L.
  • Each SRD shift aligns the BCD nibbles into the lower 12 bits of the 16-bit word, leaving the top 4 bits (bits 15-12) free for the time-base marker.
  • OW with the appropriate W#16#1xxx/W#16#2xxx/W#16#3xxx constant OR-s the time-base nibble in.

Method 2 - SCL Implementation (S7-300/400)

The same logic in Structured Control Language is easier to read and maintain. Declare an FC with IN: t_req : REAL in seconds, OUT: s5t : WORD, and the following body:

FUNCTION FC100 : VOID
VAR_INPUT
  t_req : REAL;      // Requested time in seconds
END_VAR
VAR_OUTPUT
  s5t   : WORD;      // Result in S5T# format
END_VAR
VAR_TEMP
  ms    : DINT;      // Working value in milliseconds
  base  : WORD;      // Time-base marker
END_VAR
BEGIN
  ms := REAL_TO_DINT(t_req * 100.0);
  IF ms < 0 THEN ms := 0; END_IF;
  IF ms > 9990 THEN                                  // Hard clamp
    s5t := WORD#16#3999;
    RETURN;
  END_IF;
  IF ms <= 999 THEN                                  // 10 ms base
    s5t := DINT_TO_BCD_WORD(WORD#16#0000, ms);
  ELSIF ms <= 9990 THEN                              // 100 ms base
    ms  := ms / 10;
    base := WORD#16#1000;
    s5t := base OR DINT_TO_BCD_WORD(base, ms);
  ELSIF ms <= 99900 THEN                             // 1 s base
    ms  := ms / 100;
    base := WORD#16#2000;
    s5t := base OR DINT_TO_BCD_WORD(base, ms);
  ELSE                                                // 10 s base
    ms  := ms / 1000;
    base := WORD#16#3000;
    s5t := base OR DINT_TO_BCD_WORD(base, ms);
  END_IF;
END_FUNCTION
The SCL snippet uses DINT_TO_BCD_WORD as a placeholder for the BCD conversion. In STEP 7 V5.x SCL, the proper conversion is performed with the standard library function I_BCD (FC/FB from the IEC library) or by manual bit manipulation: bcd := (ms MOD 10) + ((ms / 10 MOD 10) * 16) + ((ms / 100 MOD 10) * 256) + ((ms / 1000 MOD 10) * 4096).

Alternative: Bypass the S5T# Encoding with SFB4

If the application is new or being refactored, the IEC timer SFBs accept a TIME value directly. This removes all of the BCD/time-base gymnastics above. SFB4 implements TP (pulse), SFB3 implements TON (on-delay), and SFB5 implements TOF (off-delay). Each takes the preset in milliseconds as a DINT, so the only conversion needed is from REAL seconds to DINT milliseconds:

      L   #REAL_TimeValue            // seconds
      L   1.000000e+003              // scale to ms
      *R
      RND                            // round to DINT ms
      T   #SFB4_TV                   // move to SFB4 input TV

      CALL SFB4, DB100               // IEC TP instance DB
       IN  := #Start_Pulse
       PT  := #SFB4_TV               // DINT milliseconds
       Q   := #Pulse_Output
       ET  := #Elapsed_Time

Time range for the IEC SFBs is T#0ms to T#24d20h31m23s647ms (24 days 20 h 31 min 23.647 s), which is far wider than S5T#'s 9990 s limit. This is the recommended approach for any new code on S7-300/400.

Scan Time Integration with OB1_PREV_CYCLE

To keep the conversion in step with the actual OB1 cycle time, copy OB1_PREV_CYCLE into a 16-bit INT global and use it wherever the timer block needs a task interval. The source's example FB shows this used as the timer's accumulator delta.

// In OB1, before calling the timer FB
      L   OB1_PREV_CYCLE             // INT, OB1 scan time in ms
      T   MW100                      // 16-bit global, used by FB

Note that OB1_PREV_CYCLE is updated by the operating system at the start of each OB1 cycle, so the value read in cycle N is the duration of cycle N-1. If the cycle time is longer than the requested timer preset, the timer will complete in a single cycle; if the cycle is short, the accumulator increments by the integer millisecond value of the previous scan.

Boundary Conditions and Clamping

Input (s) Rounded (ms) Time base BCD value Resulting WORD Effective time
0.0 0 10 ms 000 W#16#0000 S5T#0ms
0.5 50 10 ms 050 W#16#0050 S5T#500ms
5.0 500 10 ms 500 W#16#0500 S5T#5s
9.99 999 10 ms 999 W#16#0999 S5T#9s990ms
10.0 1000 100 ms 100 W#16#1100 S5T#10s
59.5 5950 100 ms 595 W#16#1595 S5T#59s500ms
99.9 9990 100 ms 999 W#16#1999 S5T#1m39s900ms
100 100000 1 s 100 W#16#2100 S5T#1m40s
500 500000 1 s 500 W#16#2500 S5T#8m20s
999 999000 1 s 999 W#16#2999 S5T#16m39s
1000 1000000 10 s 100 W#16#3100 S5T#16m40s
5000 5000000 10 s 500 W#16#3500 S5T#1h23m20s
9990 9990000 10 s 999 W#16#3999 S5T#2h46m30s
10000+ clamped 10 s 999 W#16#3999 S5T#2h46m30s (clamped)

Three clamp points must be honored to avoid the timer silently failing to start:

  1. Zero clamp: S5T#0s is valid; a negative input is forced to zero.
  2. Top clamp: anything above 9990 s must be forced to W#16#3999 - feeding the timer a higher BCD with a 10 s base would be decoded as a value exceeding the 16-bit BCD range and is rejected by the timer logic.
  3. Rounding behavior: RND rounds half-up; if symmetric rounding is required, swap to TRUNC + half-step correction.

Verification and Testing

  1. Force REAL_TimeValue to 0.5 in the VAT table; observe S5_TimeValue = W#16#0050.
  2. Force the input to 9.99; expect W#16#0999.
  3. Force the input to 9.999; the rounding brings it to 9990 ms, which is the boundary between the 10 ms and 100 ms time bases. The conversion must select the 100 ms base and produce W#16#1100 (100 × 100 ms = 10 s), not W#16#0999 (which would still decode correctly but loses resolution on the next increment).
  4. Force 10000 s; verify the output is W#16#3999.
  5. Wire the converted value into a S_PULSE/S_PEXT/S_ODT timer's TV input and start the timer in single-scan mode; confirm the Q output transitions after the expected interval using the PLC's online diagnostic buffer or a VAT trigger on a marker.

Troubleshooting Matrix

  • Initialize SFB4_TV := 0 on first scan; the IEC SFBs reject negative TV at the first call
  • Symptom Likely cause Remediation
    Timer never starts; Q stays FALSE Upper time-base bits not set; word is W#16#0000 with BCD=0 - decoded as S5T#0s Verify the OW with the time-base constant; check that the branch (M01/M10/M11) selects correctly
    Timer fires immediately BCD mantissa is non-zero but time base was set to 10 ms with a value intended for the 1 s base (e.g. 50 instead of 0.5) Confirm scaling factor (* 100.0 for ms) and that division by 10/100/1000 is applied per branch
    Time is 10× too long or too short Wrong branch selected (off-by-one between M01 and M10 boundaries) Add explicit boundary tests at 999, 9990, 99900 ms
    CPU goes to STOP on the conversion block BCD value > 999 with time base 10 ms (illegal BCD range) Verify the upper clamp at 9990 s; ensure no input above this reaches the conversion
    Output word contains hex digits A-F DTB was called on a value that was not a valid DINT, or BCD mantissa contains non-decimal digits because the input was not properly rounded Re-check that RND (or explicit DINT truncation) is applied before DTB
    Timer time drifts with scan time Using OB1_PREV_CYCLE as the timer delta but reading it before OB1 initializes it Move the read into a state where OB1 has run at least once; or use a fixed cycle OB (OB35) for a stable time base
    SFB4 instance reports "invalid TV" TV is negative DINT (e.g. uninitialized)

    Field-Proven Notes

    • Keep the conversion in its own FC and call it once per cycle. Calling it inside the timer's coil logic adds scan-time-dependent jitter to the preset.
    • If the S5T# target is in a DB, declare the target as WORD, not S5TIME. The S5TIME datatype on STEP 7 V5.x is a 16-bit WORD with an editor that enforces the BCD format - the user can monitor the value directly in the VAT without extra decoding, but the conversion logic must still produce a valid WORD first.
    • On S7-300 CPUs with firmware older than V2.0, the IEC SFBs are not available. Stay on S_PULSE/S_ODT/S_PEXT and use the S5T# conversion as documented.
    • On S7-1200 and S7-1500, the S5T# format is not supported at all. Migrate to TIME literals and the IEC TP/TON/TOF instructions.

    FAQ

    What is the maximum value an S5T# timer can hold on an S7-300?

    The maximum is S5T#9990s (2 h 46 min 30 s), encoded as W#16#3999. Any input above 9990 s must be clamped to this value, or the timer will not start.

    Why does the BCD mantissa need to be shifted (SRD) after the DTB conversion?

    DTB packs the integer value as BCD into the lower bytes of ACCU1-L. The shift SRD 4/SRD 8/SRD 12 aligns the BCD digits into the 12 mantissa bits of the S5T# word (bits 13-0), leaving the upper nibble (bits 15-12) free for the time-base marker inserted by OW.

    Can I skip the S5T# conversion and feed the REAL directly to a timer?

    On S7-300/400, no. The legacy S_PULSE/S_ODT/S_PEXT instructions require a WORD in S5T# format. The IEC SFBs (SFB3/SFB4/SFB5) require a DINT in milliseconds - you only need to scale the REAL to ms and round it.

    How do I migrate this code to an S7-1200 or S7-1500?

    Replace the S5T# conversion with the IEC TP/TON/TOF instructions in TIA Portal and pass the time as a TIME literal. The TIME type accepts up to 24 d 20 h 31 m 23 s 647 ms, so the time-base/BCD encoding is no longer required.

    What happens if I OR the time-base marker with a BCD mantissa that exceeds 999?

    The CPU does not flag this at conversion time; the timer simply does not start. A common cause is forgetting to scale the REAL by 100 before rounding - the mantissa reaches DTB in the thousands and produces illegal BCD digits. Always clamp to 9990 s (or to 999 ms per branch) before the BCD conversion.

    Back to blog