S7-1200 TONR Retentive Timer and CTU Counter: TIA Portal Setup

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

S7-1200 TONR Retentive Timer and CTU Counter: TIA Portal Setup

The SIMATIC S7-1200 CPU 1214C exposes the IEC 61131-3 timer and counter family (TON, TOF, TP, TONR, CTU, CTD, CTUD) as software blocks whose state lives inside an instance data block. The most common commissioning complaint is that a TONR placed inside a Function (FC) appears to reset itself every time the FC is called. The root cause is that an FC has no static memory; a local instance is reconstructed from its initial value on each call. This reference walks through the root cause, the three robust solutions, the TIA Portal retain configuration, code examples, diagnostic flows, and verification steps.

Retentive behavior on the S7-1200 is a property of the IEC instance data block (DB), not of the block type itself. A TON placed in a Retain-marked instance is just as retentive as a TONR. The Retain attribute must be set on the relevant instance tag (or on the DB, for non-optimized blocks) for the value to survive STOP→RUN transitions and power cycles.

1. IEC Timer and Counter Family on the CPU 1214C

The S7-1200 firmware library (refer to the S7-1200 System Manual, entry ID 109751784) provides the following blocks. The CPU does not reserve a hardware timer area; every timer is a software instance.

Block Function Reset Input Behavior at IN = 0 Retentive on Power Cycle?
TON (On-delay) Delays the rising edge of Q by PT none (auto at IN=0) Q = 0, ET = 0 Only if instance is Retain
TOF (Off-delay) Holds Q high for PT after IN falls none (auto at IN=0) Q = 1, ET held Only if instance is Retain
TP (Pulse) Generates a pulse of length PT none (auto at IN=0) Q = 0, ET = 0 Only if instance is Retain
TONR (Retentive on-delay) Accumulates elapsed time R (explicit reset required) ET preserved, Q held if ET ≥ PT Yes, by design when instance is Retain
CTU (Up counter) Counts rising edges on CU R (explicit reset) CV preserved Yes, when instance is Retain
CTD (Down counter) Counts down from PV LD (explicit load) CV preserved Yes, when instance is Retain
CTUD (Up/Down counter) Bidirectional count R, LD CV preserved Yes, when instance is Retain

TONR is the only block whose name implies retentive behavior, but every block above can be made retentive through the instance DB's Retain attribute.

1.1 CPU 1214C Relevant Specifications (firmware 4.4 and later)

Parameter Value
Number of IEC timers / counters Limited only by work memory and data memory
Maximum time value PT / ET T#24d20h31m23s647ms (32-bit signed ms)
Maximum count value CV ±2,147,483,647 (DINT)
Retentive memory (work memory backed up) 10 kB on CPU 1214C (6ES7214-1...)
Number of FB / FC / DB Up to 1024 FBs, 1024 FCs, 1024 DBs (firmware dependent)
Backup without power ~50–60 hours via maintenance-free super-capacitor

The 10 kB retentive memory is shared between all retain-marked instance DBs, bit memories (M), and data blocks marked as retentive. A typical TONR instance consumes 16–32 bytes; a CTU instance consumes ~20 bytes. For exact part numbers, refer to the S7-1200 Function Manual entry ID 109798671 and the product page at siemens.com/s7-1200.

2. Why a TONR Resets in an FC: Root Cause Analysis

The S7-1200 stores the working variables of an IEC timer in an instance. The instance is a copy of the block's input, output, in/out parameters plus the static (STAT) area. When you call a TONR block from inside a Function (FC) directly, TIA Portal creates a local instance that is held in the FC's TEMP area. The TEMP area is reused on every call, and any instance data that the FC owns is initialized to the IEC initial values at the start of every invocation. This is the "automatic reset" symptom most engineers observe.

Three mechanisms contribute to the apparent reset:

  1. Local instance lifecycle. The FC owns the timer; when the FC is called, the timer is reconstructed from its initial value (ET = 0, CV = 0).
  2. Conditional FC calls. If the FC is only called under certain conditions (for example, in an OB that is not the cyclic OB1, or behind an if-then that gates the call), the timer is processed only on those calls. Retentivity can only be applied to instance data that survives across CPU STOP/RUN transitions, which is impossible for a local FC instance.
  3. No Retain attribute. A standalone global DB created when a block is placed inside an FC is marked as non-retain by default. Even if TIA Portal creates a backing DB, that DB has no Retain attribute set.
Diagnostic tip: open the FC in TIA Portal and inspect the IEC block's instance path. If the path is %FC1.statRunTimer or a similar local-internal path, the instance is local. If the path is DB_Timers.statRunTimer, the instance is in a global DB.

3. Three Robust Solutions

3.1 Solution 1 — Multi-Instance Inside a Function Block (Recommended)

A Function Block owns a static instance data block whose values are preserved between calls. A multi-instance is a sub-instance declared inside another FB's STAT area.

Prerequisites:

  • STEP 7 Basic (TIA Portal) V11 SP2 or later. Retain selection in the block properties is available from V11; TIA Portal V13+ provides an improved user interface.
  • CPU 1214C with firmware 4.0 or higher (4.4 is current at the time of writing).
  • An existing project with OB1 cyclic main program.

Procedure:

  1. In the project tree, right-click Program blocks → Add new block → Function Block. Name it FB_MachineCycle, language LAD.
  2. Open FB_MachineCycle and drag a TONR block from the Timers folder into Network 1.
  3. Click on the TONR block header. In the Inspector Properties → General, the calling convention is Multi-instance by default in TIA Portal V14+. Rename the instance to statRunTimer.
  4. Wire the inputs:
    Network 1:
          "bStart"   "statRunTimer"        "bRun"
          ——TONR—————————
                IN      ET     Q     PT = T#30s
                |       |      |     R  = "bReset"
    
  5. Open the FB's Static tag table. TIA Portal exposes the new multi-instance as a static tag of type IEC_TIMER. Click on the column Retain and select Retain for that tag.
  6. Save and compile. From the right-click context menu of FB_MachineCycle, choose Generate instance DB automatically when prompted. A new DB, for example DB_MachineCycle, is generated.
  7. Right-click the new instance DB, choose Properties → Attributes and confirm that Retain is set on the relevant tags. The default retain attribute propagates from the FB's static definition.
  8. Call the FB from OB1: drag the FB into Network 1, assign a meaningful name such as DB_MachineCycle to the instance DB.
  9. Download to the CPU. The TONR will now retain its ET value across power cycles and across RUN→STOP→RUN transitions.

3.2 Solution 2 — Single Instance in a Global DB

If you must keep the calling block as an FC (for example, to call the same logic from multiple places without instantiating an FB), the TONR/CTU can be instantiated in a global DB.

  1. Add a new Global DB: Program blocks → Add new block → Data Block. Name it DB_Timers.
  2. In the new DB, declare a tag of type IEC_TIMER (or IEC_COUNTER, IEC_SCOUNTER, IEC_DCOUNTER, IEC_USCOUNTER). Example:
    DATA_BLOCK "DB_Timers"
    { S7_Optimized_Access := 'TRUE' }
    VERSION : 0.1
      STRUCT
        statCycleTimer : IEC_TIMER;     // ~16-32 bytes
        statPartCounter : IEC_COUNTER;   // ~20 bytes
      END_STRUCT;
    END_DATA_BLOCK
    
  3. Click the Retain column for both tags and set it to Retain.
  4. In the FC, place a TONR block, click the instance selector above the block, and choose DB_Timers.statCycleTimer as the instance.
  5. Compile and download.

This method is functionally equivalent to a multi-instance but is visible in the project tree as a separate DB. With TIA Portal V14+ and optimized block access (the default for new DBs), the retentive attribute is set per tag, not for the whole DB.

If the project is set to use absolute (non-optimized) block access, you must enable the retain attribute at the DB level in the DB properties (right-click DB → Properties → Attributes → IEC retain). With optimized access, retain is a per-tag attribute and overrides the DB-level setting.

3.3 Solution 3 — Keep the FC as a Local Instance but Force a Cyclic Call

In rare applications where the FC is the most appropriate block type, you can keep the TONR as a local instance in the FC and ensure the FC is called every scan. The TONR will then retain its ET for the duration of one RUN session, but it will not survive STOP→RUN or power-down. Use this only when running-state retention is acceptable.

To force a cyclic call:

  1. Always call the FC from OB1 unconditionally.
  2. If you need to call it from an FB, do not gate the call with a conditional branch that becomes false.
  3. Do not place the FC in an OB that runs only on events (time-of-day OB, error OB, startup OB).

This is the most common source of the "TONR resets by itself" complaint: the FC is correctly written, but it is called from a conditional branch or from a cyclic interrupt that is not actually triggered every cycle.

4. TIA Portal Code Examples (SCL, LAD, FBD)

4.1 TONR with Retain in FB (SCL)

FUNCTION_BLOCK "FB_MachineCycle"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR RETAIN
  statRunTimer : IEC_TIMER;   // retentive
END_VAR
VAR
  bStart : BOOL;              // input
  bReset : BOOL;              // input
  bRun   : BOOL;              // output
END_VAR
BEGIN
  // TONR: accumulate time, reset only on bReset
  statRunTimer(IN := bStart,
               PT := T#30s,
               R  := bReset,
               Q  => bRun);
END_FUNCTION_BLOCK

4.2 CTU with Retain in FB (SCL)

FUNCTION_BLOCK "FB_PartCounter"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR RETAIN
  statCnt : IEC_COUNTER;     // retentive
END_VAR
VAR
  bPulse : BOOL;             // count edge
  bReset : BOOL;             // reset
  iCount : INT;              // output
  bDone  : BOOL;             // reached PV
END_VAR
BEGIN
  statCnt(CU := bPulse,
          R  := bReset,
          PV := 1000,
          CV => iCount,
          Q  => bDone);
END_FUNCTION_BLOCK

4.3 LAD Network (TONR in FB)

Network 1: Retentive run timer
  —————————
  |  "bStart"                "bRun"
  |  ——|
  |     |                    |
  |  ——TONR————( )——
  |     |    PT = T#30s
  |     |    R  = "bReset"
  —————————

4.4 FBD Network (CTU in FB)

Network 2: Retentive part counter
       "bPulse"
        ———|
               |
        ———| ——CTU————— "bDone"
               |   CU        |     Q
               |   R         |
               |   PV = 1000 |
               |             —— "iCount"
                                  CV
        "bReset"—————

5. Setting the Retain Attribute in TIA Portal

The path to set retain depends on the TIA Portal version. The following steps apply to TIA Portal V16/V17/V18 (current at the time of writing).

5.1 Retain for Multi-Instance Tags (FB static)

  1. Open the FB that contains the multi-instance.
  2. Click on the Static interface row for the IEC_TIMER/IEC_COUNTER tag.
  3. In the Inspector Properties → Retain, choose one of:
    • Non-retain: tag is reset to its initial value on STOP→RUN and on power-up.
    • Retain: tag is preserved across STOP→RUN, RUN→STOP, and power cycles, within the limits of the CPU's retentive memory.
    • Set in IDB: the actual setting is taken from the instance DB; allows the same FB to be used with different retain behaviors for different instances.
  4. For a TONR application, select Retain.

5.2 Retain for Tags in a Global Instance DB

  1. Open the global DB that owns the IEC_TIMER or IEC_COUNTER instance.
  2. Switch to the Data view.
  3. Click the Retain column of the relevant tag. A check mark indicates the tag will be retained.
  4. For a TONR application, the ET and the Q are part of the IEC_TIMER structure; selecting Retain on the parent tag is enough.

5.3 Retain for the Whole Instance DB (Non-Optimized Blocks)

  1. Right-click the instance DB in the project tree.
  2. Select Properties.
  3. Under Attributes, tick IEC retain. This is required only if the block access is set to "standard" (non-optimized). With optimized access, retain is a per-tag property.

6. CTU Counter Considerations and Counter Types

The CTU counts rising edges on input CU. With TIA Portal V14+, the IEC_COUNTER type (32-bit signed) is the recommended choice for new applications. For HMI displays and arithmetic, the 32-bit counter is preferred. The legacy 16-bit S5-style counter (S_CU) is still available but is not part of IEC 61131-3.

Use case Type Size Retain strategy
Count machine cycles, retain across shifts IEC_COUNTER (CTU) 32-bit signed Retain on the instance
Track remaining cycles (count down from PM interval) CTD 32-bit signed Retain on the instance
Bidirectional buffer position CTUD 32-bit signed Retain on the instance
Short pulses counted per scan (less than 32k) IEC_SCOUNTER (CTU_S) 16-bit signed Retain optional
Large count up to 2^31-1 IEC_COUNTER 32-bit signed Retain required

CTUD counts up on the rising edge of CU and down on the rising edge of CD; if both CU and CD are true in the same scan, CD wins (down-count). The output QU fires when CV ≥ PV; the output QD fires when CV ≤ 0. Retention works identically to TONR: the CV value is held if the instance is marked retentive.

7. Diagnostic Matrix and Error Codes

Symptom Most Likely Cause Verification Step Fix
ET returns to 0 every scan TONR is a local instance in an FC Inspect call site: is the FC called every cycle from OB1? Move TONR into an FB as a multi-instance, or to a global DB instance
ET returns to 0 on STOP→RUN Instance DB or tag not marked Retain Check the FB static or DB tag retain attribute Set Retain on the IEC_TIMER tag
ET returns to 0 on power-down Retentive memory not configured for the data block Check PLC → Properties → Memory and Clock bits Increase "Retain" memory or set tag retain
ET counts to PT and Q goes high, but then Q goes low again IN signal is dropping to 0 between calls Use a status viewer to see the IN bit in real time Hold IN high; use a latching input with explicit R
Counter CV resets on a power cycle even though DB is retentive CPU retentive memory exhausted Check diagnostic buffer for "Retain memory error" or "Loss of retain data" Reduce number of retentive tags or upgrade to larger CPU
Compilation error "Instance cannot be multi-instance" Trying to declare a multi-instance in an FC static FCs do not have a static area Move to FB or use a global DB
TONR ignores the R (reset) input Reset signal is not a rising edge but a level Make R a one-shot (R_TRIG) Use a rising-edge R_TRIG ahead of the R input

7.1 Common Error Codes

Error Code (Hex) Origin Cause Remedy
0x0001 IEC block Generic internal error Reboot CPU; check firmware
0x0002 CTU/CTUD CV overflow Use 32-bit counter; reset before reaching limit
0x4302 CPU diagnostic buffer Loss of retain data Verify backup time, check retain attribute
0x4303 CPU diagnostic buffer Retain memory size mismatch Adjust retentive memory in CPU properties
0x4503 CPU Re-entrancy error: block called in OB that is not allowed Check that the FB/FC is not called in startup OB while still being initialized

8. Verification Procedure

8.1 Online Verification in TIA Portal

  1. Establish an online connection to the CPU 1214C and go online.
  2. Open the FB that contains the TONR multi-instance.
  3. Click Monitor all (the glasses icon). The ET field displays the current elapsed time in T# format.
  4. Force IN to TRUE. Watch ET increment each second. Force IN to FALSE. ET must hold.
  5. Force R to TRUE. ET must return to 0.
  6. Toggle the CPU to STOP, then back to RUN. ET must be preserved.
  7. Cycle power to the PLC. After power-up, force the same online view. ET must be preserved.

8.2 Programmatic Verification via HMI / Web Server

If a SIMATIC HMI is connected, expose the static tag of the FB instance (for example, DB_MachineCycle.statRunTimer.ET) as an HMI tag. The HMI will display the same value seen in the online monitor. For the S7-1200, the user-defined web server (activated in CPU properties) can also be used to display the value.

8.3 Diagnostic Buffer Inspection

If retention is lost on power-up, open Online & Diagnostics → Diagnostic buffer and look for events such as:

  • Loss of retain data (event ID 0x4302): the retentive memory contents were lost. Indicates either a power-down exceeding the CPU's backup capacitor time, or that the backup was explicitly disabled.
  • Retain memory error (event ID 0x4303): the configured retentive memory size is inconsistent with the actual data that needs to be retained.

The CPU 1214C has no battery; retain is maintained by a maintenance-free super-capacitor that holds the data for typically 50 to 60 hours after power removal. If the panel has been unpowered longer than this, the retentive data is lost regardless of the software configuration. For applications requiring longer backup, install the optional SIMATIC Memory Card (SMC) and set the data block property Store in load memory to true.

9. Best Practices, Edge Cases, and Migration Notes

9.1 Best Practices Checklist

  • Always instantiate a TONR (or any IEC timer that must accumulate) in an FB as a multi-instance, or in a global DB. Never in an FC.
  • Set the Retain attribute on the IEC_TIMER/IEC_COUNTER tag, not on the entire DB (with optimized block access).
  • Use TIA Portal V16+ where possible; the optimized block access model is the default and yields clearer retain behavior.
  • Group all retentive tags of an FB under a VAR RETAIN block in SCL for readability.
  • Avoid the S5-style counters (S_CU, S_CD) for new applications. The IEC_COUNTER types are clearer and portable to S7-1500.
  • Always wire the R input of TONR/CTU with a defined reset condition. An un-wired R is a common source of "the timer never resets" confusion.
  • Document the meaning of the Retain attribute in the block header comment of the FB, especially if "Set in IDB" is used.

9.2 Field-Proven Edge Cases

  • Reset timing. The R input of TONR/CTU is level-sensitive. If R is held high, the timer/counter never starts counting. For a one-shot reset, pulse R with an R_TRIG block.
  • Very long times. PT can be up to T#24d20h31m23s647ms, but the implementation uses 32-bit signed milliseconds. Do not pass a negative TIME value; the runtime behavior is undefined.
  • PT in DBs. When PT is read from a DB tag rather than a literal, the IEC block re-reads the value every scan. If you change PT during operation, the new value takes effect on the next scan. For TONR, ET is not reset by changing PT.
  • Multiple assignment of the same instance. A frequent error is to assign the same multi-instance tag to two FBs. TIA Portal will compile but the behavior is undefined. Always create one multi-instance per FB that needs it.
  • Implicit reset on download. Downloading a new program to the CPU does not reset the retain memory by default. The behavior is governed by Reset retain memory on download in the online menu, which is off by default. If you want a clean state after a download, toggle this option once.

9.3 Migration Notes (S7-300/400 → S7-1200)

  • The legacy S5-style timers S_ODT, S_PULSE, etc. are not available on the S7-1200. Replace with TONR, TP, TOF as appropriate.
  • The S7-300/400 had a fixed hardware-based timer area (T0..T255 on an S7-300). The S7-1200 has no such area; every timer is a software instance.
  • The S5-style counter (C0..C255) does not exist on the S7-1200. Replace with CTU, CTD, or CTUD.
  • The "Retentive on power failure" property of legacy timers/counters is replaced by the Retain attribute on the instance data block.

The migration tool in TIA Portal warns about unsupported timer/counter references. After migration, verify that the generated FB has the Retain attribute set on the IEC_TIMER/IEC_COUNTER multi-instance tags.

9.4 Performance Considerations

Each IEC timer/counter call consumes a small but measurable amount of CPU time. Typical figures for the CPU 1214C:

Block Approximate Execution Time (μs)
TON, TOF, TP 2 – 4
TONR 3 – 5
CTU, CTD, CTUD 2 – 4

For applications with thousands of timers (for example, batch tracking of thousands of positions), the aggregate cost can add up. If the scan time is critical, gate the timer call with the input condition so that the IEC block is only executed when its IN transitions from 0 to 1.

9.5 Connection to HMI and OPC UA

When a retentive timer is used as the runtime counter of a machine, the ET and CV values are typically exposed to the operator panel. With optimized block access (default in TIA Portal V14+), the HMI tag is created by browsing the DB and selecting the relevant member:

  • Path: DB_MachineCycle.statRunTimer.ET for the elapsed time
  • Path: DB_PartCounter.statCnt.CV for the count value

In WinCC (TIA Portal) or on a SIMATIC Comfort Panel, the HMI tag points directly at the optimized DB member. The data is exchanged via the S7 communication protocol; the operator panel does not need to know that the value is retentive.

If the CPU 1214C is configured as an OPC UA server (firmware 4.4+ with the OPC UA license), the same data is exposed over OPC UA. A SCADA system can subscribe to the value and display it on a dashboard. The OPC UA subscription continues to receive updates during power cycles because the next published value is the retained value.

10. Diagrams: Topology and State Machines

10.1 Topology

CPU 1214C – Retentive TONR & CTU Topology DI8 (Inputs) Start, Reset, PartPulse FB100 Multi-Instance statRunTimer (Retain) FB101 Multi-Instance statPartCounter (Retain) Retain 10 kB backup OB1 (cyclic, ~10 ms) → FB100 / FB101 → Instance DB (retentive). All TONR/CTU sit in FBs, never in FCs.

10.2 TONR State Diagram

TONR (Retentive On-Delay) State Diagram Idle (ET=0, Q=0) Accumulating (ET held) Expired (Q=1) IN = 1 (R=0) ET ≥ PT R = 1 → ET=0, Q=0 IN=0 holds ET

The key behavioral difference between TON and TONR is visible: in TON, IN = 0 returns the timer to Idle immediately; in TONR, IN = 0 holds the current ET value and only R = 1 resets it.

10.3 Internal Memory Layout of IEC_TIMER

TIA Portal exposes the internal data structure of these system-defined types. Knowing the layout is useful for advanced diagnostics.

TYPE IEC_TIMER
  STRUCT
    IN     : BOOL;    // input: enable counting
    PT     : TIME;    // preset time
    Q      : BOOL;    // output: ET >= PT
    ET     : TIME;    // elapsed time
    STATE  : BYTE;    // internal state (running, expired, etc.)
    STIME  : TIME;    // start time stamp (relative)
  END_STRUCT;
END_TYPE

The STATE byte of IEC_TIMER is internal and should not be modified from user code. Modifying it is a common cause of "the timer behaves inconsistently" support calls.

11. Frequently Asked Questions

Why does my TONR reset when the FC is called?

Because a local instance inside a Function (FC) is reconstructed every time the FC is called. The TONR's elapsed time is not stored in a retained instance DB, so it is initialized to zero on each call. Move the TONR into a Function Block (FB) as a multi-instance, or instantiate it in a global DB, and set the Retain attribute on the tag.

Do I need to use TONR, or is a TON with retain also valid?

A TON with a Retain-marked instance is functionally equivalent to a TONR when the input is held high. The practical difference is that TON resets its ET to 0 automatically when IN returns to 0, while TONR holds the accumulated ET and only resets when R is asserted. For accumulating run-time across process interruptions, use TONR.

How long does the CPU 1214C keep retain data without power?

Typically 50 to 60 hours, supported by an internal maintenance-free super-capacitor. For longer backup, the optional SIMATIC Memory Card can be used to store retentive data to load memory on shutdown. Verify the diagnostic buffer entry if the CPU reports loss of retain data.

Can I have more than one TONR in the same FB?

Yes. Declare each as a separate multi-instance tag in the FB's Static interface. Avoid declaring the same IEC_TIMER tag in two different FBs, which would create two separate instances that do not share state.

Why does my counter reset on STOP→RUN but a TONR with the same settings does not?

Both behaviors depend on the Retain attribute of the instance. If only the TONR is marked Retain and the CTU is not, the CTU will be reset to its initial value on every STOP→RUN transition. Mark both tags as Retain for consistent behavior.

Is the IEC_TIMER a system data type or a UDT?

IEC_TIMER is a system-defined data type (SDT) provided by the S7-1200 system library. It is a structure containing inputs (IN, PT, R), outputs (Q, ET), and internal static fields. It is portable between S7-1200, S7-1500, and S7-300/400 with minor differences.

Back to blog