Scheduling Siemens S7 PLC Digital Outputs via SFC0 SFC1

David Krause18 min read
HMI ProgrammingSiemensTutorial / 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

Scheduled activation of digital outputs based on the PLC real-time clock is a recurring requirement in industrial automation: a beacon must come on at 06:00 sharp, a relay must energize at the end of a shift, a pre-cooling cycle must start at a programmed future date, or a sanitation rinse must trigger at 02:00 every Sunday. On the Siemens SIMATIC platform, two complementary blocks cover this use case across the entire S7 family:

  • SFC1 "READ_CLK" reads the current CPU date and time.
  • SFC0 "SET_CLK" writes a new date and time into the CPU.

For S7-300 (CPU 312 through CPU 319F) and S7-400 (CPU 412 through CPU 417), SFC0 and SFC1 are part of the standard library shipped with every STEP 7 V5.x installation and the TIA Portal "S7-300/400" option. For S7-200, the equivalent instructions are the subroutines READ_RTC and SET_RTC. For S7-1200 and S7-1500, the legacy SFC interface is replaced by the TIA Portal instructions RD_SYS_T and WR_SYS_T, which operate on the modern 12-byte DTL (Date_And_Time_Long) data type and support direct comparison without BCD conversion.

This article documents a complete, repeatable procedure to read the CPU clock, convert it from BCD to integer, compare it against a target date/time, and drive a digital output exactly when the wall clock reaches the scheduled instant. Edge cases (year boundary, DST, battery failure, single-trigger race), platform variants (S7-200, S7-300, S7-400, S7-1200, S7-1500), and a troubleshooting matrix are included.

Warning: Driving field actuators purely on PLC time without operator supervision is hazardous for any machine whose motion can cause injury or equipment damage. Add an enable interlock, an HMI acknowledge, and a watchdog timeout before deploying this pattern to production.

Prerequisites

  • Siemens S7-300 (CPU 312/314/315/316/317/319) or S7-400 (CPU 412/414/416/417) with STEP 7 V5.5 SPx or TIA Portal V13 SP1+ configured and online-capable.
  • Standard library installed (SFC0, SFC1, and the IEC function blocks are included in every STEP 7 install; verify under "Libraries → Standard Library → System Function Blocks").
  • For S7-1200/S7-1500: TIA Portal V13 or later with the extended "Date and Time" instructions.
  • Output module (e.g., SM322 DO16 or SM332) wired to the actuator; verify the wiring diagram and the process image address (e.g., Q4.0).
  • Functional backup battery in the CPU (3.6 V lithium, type 3AGM for S7-300); a missing battery causes the clock to revert to a default value on every power cycle.

Understanding DATE_AND_TIME (DT) Format

SFC0 and SFC1 exchange the date and time as an 8-byte DATE_AND_TIME (DT) structure. Every byte is BCD-encoded, which means each nibble stores one decimal digit. This format is preserved end-to-end from the CPU's hardware clock through the SFC interface into the application data block.

Byte Content BCD Range Meaning
0 Year (BCD) 90-99 or 00-89 1990-1999 or 2000-2089
1 Month (BCD) 01-12 January to December
2 Day (BCD) 01-31 Day of month
3 Hour (BCD) 00-23 24-hour clock
4 Minute (BCD) 00-59 Minute of hour
5 Second (BCD) 00-59 Second of minute
6 Weekday + ms (BCD) High nibble: 1-7, low nibble: 0-99 1=Sunday, 7=Saturday; low nibble = hundreds+tens of milliseconds
7 Milliseconds (BCD) 00-99 Tens+units of milliseconds

Because the year 2090 is the next century boundary, any logic that crosses 2089 → 2090 must be revisited. The Siemens recommendation is to migrate such logic to the S7-1500 DTL data type, which stores the year as a UINT in the range 1970-2554.

SFC1 READ_CLK - Reading the CPU Clock

SFC1 is the standard way to obtain the current date and time inside the user program. The function is stateless and can be called from OB1, OB35, OB82, OB100, or any cyclic organization block.

Parameter Declaration Type Description
RET_VAL OUTPUT INT Error code. 0 = success.
CDT OUTPUT DATE_AND_TIME 8-byte BCD-encoded current date/time.

Standard call pattern in STL:

CALL "READ_CLK"
     RET_VAL := MW100
     CDT     := DB101.CurrentTime

On success, MW100 contains 0 and DB101.CurrentTime is populated with the current values. On a CPU without a working battery that has never had SFC0 executed, SFC1 may return RET_VAL = W#16#8081 ("clock not set"); subsequent bytes may also be invalid. Always check RET_VAL before consuming the date/time in your scheduling logic.

SFC0 SET_CLK - Writing the CPU Clock

SFC0 accepts a properly populated DATE_AND_TIME input and writes it to the CPU's hardware real-time clock. Typical use cases are:

  • Initial time set after battery replacement.
  • Time broadcast from an HMI acting as the time master.
  • Programmatic resync after NTP time arrives at the CPU.
Parameter Declaration Type Description
RET_VAL OUTPUT INT Error code. 0 = success.
PDT INPUT DATE_AND_TIME Target date/time to write (8-byte BCD).

STL example, where the target time has been pre-formatted in DB102:

CALL "SET_CLK"
     RET_VAL := MW102
     PDT     := DB102.NewTime

S7-200 Variant - READ_RTC and SET_RTC

The S7-200 (CPU 21x, 22x, 224, 224XP, 226) does not expose SFC0/SFC1; instead, the Clock Instructions library ships with two reusable subroutines (SBR_RTC and SB_RTC, commonly named READ_RTC and SET_RTC). Each subroutine uses 8 bytes of V memory to hold year/month/day/hour/minute/second + reserved byte + error code in BCD. The start address is supplied on input T.

SBR Number Name V-Memory Map Description
SBR 0 (default READ_RTC) Read real-time clock T..T+7 = year/month/day/hour/minute/second + reserved Reads the S7-200 clock to V memory
SBR 1 (default SET_RTC) Set real-time clock T..T+7 = target BCD values Writes V memory back to the S7-200 clock

Call sequence in the S7-200 main program (OB1):

NETWORK 1 // Read the clock
      CALL SBR 0, VB100

Each V memory byte is then available as a separate BCD byte and can be compared with BCD comparison instructions such as =B, >B, <B.

S7-1200 and S7-1500 Variant - RD_SYS_T / WR_SYS_T

The legacy SFC interface was retired for S7-1200 and S7-1500. The replacement is a pair of extended instructions in TIA Portal:

Instruction Path in TIA Portal Function Return Type
RD_SYS_T Extended Instructions → Date and Time → Read system time Returns current local date/time DTL (12 bytes)
WR_SYS_T Extended Instructions → Date and Time → Set system time Writes a DTL to the CPU clock RET_VAL (Int)
T_CONV Extended Instructions → Date and Time → Convert time Converts DTL ↔ DATE/TIME/TOD Various
GeT100ms Time-of-day → Acquire 100 ms counter Provides the 100 ms tick from the CPU TIME / LWORD

DTL Structure

Byte Content Range
0-1 Year (UINT) 1970-2554
2 Month (USINT) 1-12
3 Day (USINT) 1-31
4 Weekday (USINT) 1-7 (1 = Sunday)
5 Hour (USINT) 0-23
6 Minute (USINT) 0-59
7 Second (USINT) 0-59
8-11 Nanoseconds (UDINT) 0-999,999,999

Procedure - Activate a Digital Output at a Future Time on S7-300/400

Step 1 - Create the Schedule Data Block

Open the S7 project in STEP 7 and create a new shared DB (e.g., DB100). Define a structure that holds the target date/time in BCD, an "already triggered" latch, and the output status. The BCD initialization is critical: each value must be a valid BCD byte, meaning each nibble is in the range 0-9.

DATA_BLOCK DB100
TITLE = 'Scheduled Output Trigger'
STRUCT
  Target_Year    : BYTE := B#16#25;    // 2025 (BCD 25h)
  Target_Month   : BYTE := B#16#12;    // December (BCD 12h)
  Target_Day     : BYTE := B#16#31;    // 31 (BCD 31h)
  Target_Hour    : BYTE := B#16#23;    // 23
  Target_Minute  : BYTE := B#16#59;    // 59
  Target_Second  : BYTE := B#16#00;    // 00
  Triggered      : BOOL := FALSE;
  OutputActive   : BOOL := FALSE;
END_STRUCT
END_DATA_BLOCK

Step 2 - Create the Clock Buffer DB

The clock buffer stores the raw DATE_AND_TIME output of SFC1. Declare a separate DB (e.g., DB101) with a single DT field:

DATA_BLOCK DB101
STRUCT
  CurrentTime : DATE_AND_TIME;
END_STRUCT
END_DATA_BLOCK

Step 3 - Call SFC1 from OB1

NETWORK 1  // Read CPU clock
      CALL "READ_CLK"
           RET_VAL := MW100
           CDT     := DB101.CurrentTime

Step 4 - Convert BCD Bytes to Integer

SFC1 returns BCD-encoded bytes. STEP 7 comparison operators such as >=I operate on integers, so each BCD byte must be converted. Siemens provides FC 21 "BCD_TO_INT" (also known as I_BCD or implemented inline as BTD 1 IWx). Use it for each field, or write a single FC that converts all eight bytes.

NETWORK 2 // Convert year, month, day
      CALL "BCD_TO_INT"
           BCD     := DB101.CurrentTime.YEAR
           RET_VAL := MW102       // integer year
      CALL "BCD_TO_INT"
           BCD     := DB101.CurrentTime.MONTH
           RET_VAL := MW104       // integer month
      CALL "BCD_TO_INT"
           BCD     := DB101.CurrentTime.DAY
           RET_VAL := MW106       // integer day

NETWORK 3 // Convert hour, minute, second
      CALL "BCD_TO_INT"
           BCD     := DB101.CurrentTime.HOUR
           RET_VAL := MW108
      CALL "BCD_TO_INT"
           BCD     := DB101.CurrentTime.MINUTE
           RET_VAL := MW110
      CALL "BCD_TO_INT"
           BCD     := DB101.CurrentTime.SECOND
           RET_VAL := MW112

Step 5 - Implement the Comparison Logic

The output should be set when the current time has reached (or passed) the target. Use a chained ladder network where each subsequent comparison only fires if the previous one passed. This correctly handles months, days of month, and leap years.

NETWORK 4 // Year comparison
      L     MW102
      L     DB100.Target_Year_INT     // pre-converted target
      >=I
      JCN   YEAR_LOW

NETWORK 5 // Month
      L     MW104
      L     DB100.Target_Month_INT
      >=I
      JCN   YEAR_LOW

NETWORK 6 // Day
      L     MW106
      L     DB100.Target_Day_INT
      >=I
      JCN   YEAR_LOW

NETWORK 7 // Hour
      L     MW108
      L     DB100.Target_Hour_INT
      >=I
      JCN   YEAR_LOW

NETWORK 8 // Minute
      L     MW110
      L     DB100.Target_Minute_INT
      >=I
      JCN   YEAR_LOW

NETWORK 9 // Second
      L     MW112
      L     DB100.Target_Second_INT
      >=I
      JCN   YEAR_LOW

NETWORK 10 // All conditions met, set output
      S     DB100.OutputActive
      S     DB100.Triggered
YEAR_LOW: NOP 0

Equivalent representation in LAD/FBD:

|  --[ >=I  MW102  DB100.Target_Year_INT  ]--
|  --[ >=I  MW104  DB100.Target_Month_INT ]--
|  --[ >=I  MW106  DB100.Target_Day_INT   ]--
|  --[ >=I  MW108  DB100.Target_Hour_INT  ]--
|  --[ >=I  MW110  DB100.Target_Minute_INT]--
|  --[ >=I  MW112  DB100.Target_Second_INT]--( S DB100.OutputActive )

Step 6 - Drive the Digital Output

NETWORK 11 // Output to process image
      A     DB100.OutputActive
      =     Q 4.0      // first channel of SM322 DO16

Step 7 - Reset the Latch

Once the scheduled action has been acknowledged, clear the OutputActive and Triggered flags from an HMI input or a push-button input:

NETWORK 12 // Operator reset
      A     I 0.5
      R     DB100.OutputActive
      R     DB100.Triggered

Procedure - Activate a Digital Output at a Future Time on S7-1200/1500

On S7-1200 (FW 4.0+) and S7-1500, the implementation collapses because DTL is a directly comparable data type. The full SCL implementation in TIA Portal V18 is:

// Read current time
#currentTime := RD_SYS_T();

// Build target time once (e.g., in OB100)
IF #firstScan THEN
    #targetTime.YEAR   := 2025;
    #targetTime.MONTH  := 12;
    #targetTime.DAY    := 31;
    #targetTime.HOUR   := 23;
    #targetTime.MINUTE := 59;
    #targetTime.SECOND := 0;
    #alreadyTriggered  := FALSE;
END_IF;

// Compare and latch
IF (#currentTime >= #targetTime) AND NOT #alreadyTriggered THEN
    "Output_Active"   := TRUE;
    #alreadyTriggered := TRUE;
END_IF;

No BCD conversion, no DT structure parsing, and no manual chaining of comparison operators are required. The same code style works for any scheduling granularity from 1 second up to 1 year, limited only by the precision of the DTL type (nanosecond resolution on S7-1500, millisecond on S7-1200).

Output Module Wiring Reference

Output Module Order Number Channel Address Voltage / Current
SM322 DO16 (relay) 6ES7322-1HH01-0AA0 Q 4.0 - Q 5.7 24 VDC / 2 A or 230 VAC / 2 A per relay
SM322 DO16 (transistor) 6ES7322-1BH01-0AA0 Q 4.0 - Q 5.7 24 VDC / 0.5 A per channel
SM322 DO32 6ES7322-1BL00-0AA0 Q 4.0 - Q 7.7 24 VDC / 0.5 A per channel
SM332 DO8 (analog) 6ES7332-5HF00-0AB0 Output channels +/-10 V or 0/4-20 mA
S7-1500 DQ16 6ES7522-1BH00-0AB0 Q 0.0 - Q 1.7 24 VDC / 0.5 A per channel

Confirm the channel address in your hardware configuration before commissioning. STEP 7 → HW Config → slot → Properties shows the start address used by the process image.

Date/Time Arithmetic: Adding Hours to a Target

For repeating schedules (every Monday at 06:00), use the IEC function blocks SB_DT_T (subtract TIME from DT), AD_DT_T (add TIME to DT), SB_T_DT, and AD_T_DT from the standard library. They correctly handle month and year roll-overs:

// Compute next-run time = previous-run time + 24h
CALL "AD_DT_T"
     T1    := DB101.LastTriggerTime
     T2    := T#24h
     D     := DB101.NextTriggerTime

Combined with a self-resetting latch and a cyclic OB, this yields a 24-hour repeating schedule without operator intervention. For weekly or monthly cycles, multiply the time interval accordingly (T#168h for weekly, T#720h for 30-day averages).

Periodic Scheduling with OB35

To reduce CPU load, place the scheduling logic in a cyclic interrupt OB (OB35 default 100 ms) instead of OB1. Adjust OB35 execution time under Hardware → Properties → CPU → Cyclic Interrupts. Avoid setting OB35 below 10 ms on S7-300/400 because SFC1's call itself takes several hundred microseconds.

Clock Synchronization Patterns

NTP (S7-1200/1500 only)

S7-1500 (FW 2.0+) and S7-1200 (FW 4.4+) accept NTP directly. In TIA Portal, configure PROFINET interface → Time-of-day synchronization → "Synchronize via NTP" and supply up to four NTP server addresses. The CPU updates its internal clock every poll interval (default 10 s). Drift is bounded by the network latency to the time server.

HMI as Time Master

For S7-300/400, configure the WinCC Unified or WinCC Comfort/Advanced panel as the time master via "Connections → Date/Time pointer". The HMI writes its local clock to the PLC at a configurable interval (1-60 s). This compensates for battery drift on the PLC side.

SCADA Time Broadcast

SCADA systems (WinCC, Ignition, FactoryTalk View) can broadcast the time to multiple PLCs simultaneously. On Allen-Bradley ControlLogix/CompactLogix platforms used alongside Siemens, the GSV (Get System Value) instruction reads the WALL_CLOCK_TIME attribute, and SSV writes it. Cross-vendor time sync is typically implemented with NTP rather than vendor-specific protocols.

Diagnostic OBs for Clock and Battery

OB Trigger Action
OB81 Battery failure / backup voltage lost Trigger maintenance alarm; log timestamp; halt scheduled actions until battery replaced
OB82 Diagnostic interrupt (I/O fault) Indicate faulty SM; do not allow scheduled output if DO module is faulted
OB100 Warm restart Re-read SFC1 to refresh DB101; reinitialize trigger latch
OB101 Hot restart Same as OB100 on S7-400
OB102 Cold restart Full reinit; battery-backed DBs preserved

Troubleshooting Matrix

Symptom Likely Cause Resolution
MW100 returns 8081h after SFC1 call Clock not initialized; battery missing or recently replaced Execute SFC0 with a known valid DT; replace battery if OB81 is firing
SFC1 returns 8082h CPU in STOP, or hardware fault on the clock IC Check CPU diagnostic buffer with STEP 7 → PLC → Diagnostic Buffer
Output fires immediately on every scan Triggered latch was never initialized to FALSE; remanent DB retained old state Initialize DB100 with Triggered = FALSE in OB100; or use non-remanent variables
Output never fires Target DT not entered; BCD conversion producing garbage integer Monitor MW102-MW112 online; confirm target DB100 contents in BCD
Output fires at wrong moment Comparison chain misordered (e.g., minute compared before hour) Verify the ladder sequence; second must be the innermost comparison
Output repeats every cycle after target reached Latch not set; or reset coil placed before the comparison Confirm OutputActive is set (S) and not toggled (=); reset only on operator input
Year logic fails after 2089 BCD year interpretation: 90-99 means 1990s, 00-89 means 2000s Add century offset to integer year (see "Edge Cases" below)
Q4.0 has no voltage even when OutputActive is TRUE Output module missing, fuse blown, or wiring fault Verify module in HW Config; check module OK LED; measure terminal voltage
Time drifts by minutes per day Battery near end-of-life; quartz oscillator drift; CPU temperature high Replace battery; verify ambient temperature within spec (0-60°C)
OB81 fires at startup Battery not installed or polarity reversed Install correct battery (3.6 V lithium, 3AGM); clear diagnostic buffer

Edge Cases and Field Notes

Century Boundary in BCD

SFC0/SFC1 use BCD year encoding where 90-99 represents 1990-1999, while 00-89 represents 2000-2089. A naive integer comparison "MW102 >= 25" fires both in 2025 (BCD 25h) and in 1925 (BCD 25h interpreted as 1925). The recommended correction:

NETWORK // Century correction for year
      L     MW102         // integer year (post-BCD-to-int)
      L     90
      <I                 // if MW102 < 90, treat as 2000s
      JC    ADD_2000
      L     1900
      +I
      JU    STORE_Y
ADD_2000: L 2000
          +I
STORE_Y:  T MW120        // correct integer year

Daylight Saving Time

S7-300/400 do not natively handle DST. The clock value reflects whatever was last written via SFC0 or set from the HMI/NTP master. For installations that observe DST, the time master (WinCC, NTP server, or SCADA) is responsible for pushing the adjusted wall-clock value via SFC0/WR_SYS_T.

Leap Years and Invalid Dates

SFC0 silently accepts BCD values such as "February 30" and writes them into the clock; the CPU does not validate calendar correctness. Always pre-validate the target DT before calling SFC0, and document the assumed rules (Gregorian, proleptic Gregorian, etc.).

Single-Trigger Race Condition

After the target time passes, every subsequent scan continues to satisfy the comparison chain. The latch flag (Triggered) prevents repeated transitions of the digital output and is the canonical pattern. Always reset Triggered from a controlled operator input, not from the same comparison logic.

Output Held Past Intended Duration

Combine the time-based trigger with a watchdog timer to release the output after a defined period. Recommended pattern:

// After OutputActive is set, start a 30-minute on-delay timer
A     DB100.OutputActive
L     S5T#30m          // 30 minutes (S5 time format)
SD    T50
A     T50
=     Q 4.0            // output held only while timer running

When the scheduled time arrives, OutputActive is set, timer T50 starts, and Q4.0 is energized for 30 minutes. The timer auto-resets when OutputActive is reset by the operator.

Multi-Event Scheduling

For plants with dozens of scheduled events, define an array DB and loop through it in OB35. Each entry contains a target DT, an output bit address, and the latched flag.

DATA_BLOCK DB200
TITLE = 'Weekly Schedule'
STRUCT
  Event : ARRAY[1..50] OF STRUCT
    TargetDT : DATE_AND_TIME;
    OutputBitAddr : BYTE;       // 0 = Q0.0, 1 = Q0.1, etc.
    OutputBitMask : BYTE;
    Latched : BOOL;
    Enabled : BOOL;
  END_STRUCT;
END_STRUCT
END_DATA_BLOCK

A loop in OB1 compares each entry against the current time and sets the corresponding output bit. For 50 entries called once per OB1 cycle, total scan time overhead is typically under 5 ms on a CPU 315-2 PN/DP.

Platform Comparison

Feature S7-200 (READ_RTC/SET_RTC) S7-300/400 (SFC0/SFC1) S7-1200/1500 (RD/WR_SYS_T)
Data format BCD bytes in V memory BCD DATE_AND_TIME (8 bytes) Binary DTL (12 bytes)
BCD conversion needed Yes Yes No
Year range 2000-2099 (typical) 1990-2089 1970-2554
Sub-second precision No 1 ms 1 ns
NTP support No No Yes (S7-1200 FW 4.4+, S7-1500 FW 2.0+)
Direct DTL comparison N/A N/A Yes
Recommendation Legacy micro PLC Existing STEP 7 V5.x projects New development on TIA Portal

Cross-Platform Reference: AB Logix Equivalent

Engineers maintaining mixed fleets can map this pattern to Allen-Bradley ControlLogix/CompactLogix:

// Read the Logix WALL_CLOCK_TIME
GSV   WallClockTime Year   YearInt
GSV   WallClockTime Month  MonthInt
GSV   WallClockTime Day    DayInt
GSV   WallClockTime Hour   HourInt
GSV   WallClockTime Minute MinuteInt
GSV   WallClockTime Second SecondInt

// Compare and set output
GRT   YearInt   Target_Year  Year_OK
GRT   MonthInt  Target_Month Month_OK
GRT   DayInt    Target_Day   Day_OK
GRT   HourInt   Target_Hour  Hour_OK
GRT   MinuteInt Target_Min Min_OK
GRT   SecondInt Target_Sec  Sec_OK
AND   Year_OK  Month_OK  Day_OK  Hour_OK  Min_OK  Sec_OK  OTE  OutputActive

The Logix GSV/SSV pattern returns binary integers and avoids the BCD conversion step entirely, mirroring the S7-1500 DTL simplification.

Verification Checklist

  • [ ] SFC1 reads valid time (DB101.CurrentTime populated, MW100 = 0).
  • [ ] Each BCD byte converts to a sensible integer (MW102-MW112 in range).
  • [ ] DB100 target fields entered in valid BCD (no letter characters, no nibble > 9).
  • [ ] Output Q4.0 energizes at the scheduled second (multimeter reads 24 VDC).
  • [ ] Triggered latch holds the output after target time; not re-triggered on subsequent cycles.
  • [ ] Operator reset clears OutputActive and Triggered flags.
  • [ ] OB81 does not fire (battery healthy).
  • [ ] Watchdog timer releases Q4.0 after the intended duration.
  • [ ] NTP or HMI master sync is active; drift < 1 second per hour observed over 24 hours.
  • [ ] HMI displays the current CPU time and confirms the scheduled trigger.

Best Practices Summary

  1. Always check the RET_VAL of SFC0 and SFC1. A non-zero return means the clock operation failed.
  2. Pre-validate calendar correctness before calling SFC0 to avoid writing Feb 30.
  3. Use the century-offset fix for any year-sensitive scheduling, or migrate to S7-1500 DTL.
  4. Add a watchdog timer to release the output after a safe duration.
  5. Log every scheduled action to a ring-buffer DB for forensic review.
  6. Initialize the Triggered latch from OB100 on every restart to prevent stale state.
  7. Synchronize the PLC clock via NTP or HMI master to avoid drift.
  8. Add an enable interlock on the output rung; never drive field actuators from time alone.

Frequently Asked Questions

How do I read the Siemens S7-300 CPU clock inside a user program?

Call SFC1 "READ_CLK" in OB1 or a cyclic OB. The RET_VAL output goes to an INT word (e.g., MW100) and the CDT output goes to a DATE_AND_TIME variable (e.g., DB101.CurrentTime). The 8-byte DT contains BCD-encoded year, month, day, hour, minute, second, millisecond, and weekday. Verify RET_VAL = 0 before consuming the values.

How do I set the Siemens S7-400 CPU clock?

Use SFC0 "SET_CLK" with the input PDT bound to a properly formatted DATE_AND_TIME value and RET_VAL bound to an INT word. Call from OB1, OB100 (warm restart), or OB101 (hot restart) whenever the CPU clock needs to be corrected. After a battery replacement with a cold restart, the PLC clock reverts to a default value; call SFC0 once to restore the correct time.

Why does my comparison logic fire at the wrong year?

SFC0/SFC1 use BCD year encoding where 90-99 represents 1990-1999 and 00-89 represents 2000-2089. A naive integer comparison "MW102 >= 25" fires both in 2025 and in 1925. Add a century offset: if the integer year is < 90, add 2000; otherwise add 1900. The cleanest fix is to migrate the application to S7-1200/S7-1500 where the DTL year is a UINT in the range 1970-2554.

Can I use SFC0 and SFC1 on S7-1200 or S7-1500?

No. The SFC interface is not available on S7-1200/S7-1500. Use the TIA Portal extended instructions RD_SYS_T and WR_SYS_T instead. They operate on the 12-byte DTL data type which stores year as UINT (1970-2554) and supports direct comparison without BCD conversion. Place them in the OB1, OB35, or any cyclic OB.

How do I keep the PLC clock synchronized with a WinCC HMI or NTP server?

For S7-1200/1500, enable NTP in the CPU properties (PROFINET interface → Time-of-day synchronization). For S7-300/400, configure the WinCC panel as the time master via the Date/Time area pointer. The HMI writes its current time to the PLC at intervals from 1 to 60 seconds, automatically correcting battery-induced drift. SCADA systems such as Ignition or FactoryTalk View can broadcast time to multiple PLCs simultaneously.

Back to blog