Siemens S7 Sync_Time Function: SFC0/SFC1 L-Stack Reference

David Krause21 min read
S7-300SiemensTechnical Reference
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 the Sync_Time Pattern

The Sync_Time function is a recurring STEP 7 V5.x pattern for S7-300 and S7-400 CPUs that snaps the PLC real-time clock to a fixed time-of-day while preserving the current calendar date. The block reads the existing date and time with SFC1 (READ_CLK), overwrites only the hour/minute/second fields inside an 8-byte Date_And_Time buffer that lives in the L-Stack, and then writes the patched timestamp back to the CPU with SFC0 (SET_CLK). The three MOVE operations B#16#6 -> LB3, B#16#0 -> LB4, and B#16#0 -> LB5 produce a target clock value of 06:00:00 on the day the trigger fires, without disturbing the date or weekday fields.

Execution is gated by a single bit - typically a Merker (M) flag such as M2.7 driven from a WinCC HMI tag - so the function is fully dormant until an operator pushes the synchronization button. The block does not require an instance DB, has no global footprint other than the trigger bit, and runs from OB1 or any cyclic OB that supports SFC calls. The same skeleton is reused on S7-300 (CPU 312 through CPU 319) and S7-400 (CPU 412 through CPU 417) CPUs without code changes because SFC0 and SFC1 are part of the S7-300/400 standard library and have the same interface across all CPU firmware versions from V2.x through to the latest V3.x for S7-300 and V6.x for S7-400.

Engineers who first encounter the pattern often focus on the three MOVE instructions and miss the bigger picture: the program is not "setting the time to 6 AM" - it is reading the current clock, splicing the time-of-day to 06:00:00, and writing the spliced result back. The date, weekday, and millisecond fields survive the round-trip because only LB3, LB4, and LB5 are touched. This article documents the L-Stack layout, the BCD encoding, the trigger wiring, and the field verification procedure required to make the function reliable in production.

System Functions: SFC0 SET_CLK and SFC1 READ_CLK

The two SFCs that power the pattern are part of the standard IEC 61131-3 system function library that ships with every S7-300 and S7-400 CPU firmware. They live in the Standard Library > System Function Blocks tab of the STEP 7 SIMATIC Manager and are documented in the SIMATIC S7-300/400 Standard and System Functions reference manual, which is the canonical SFC0/SFC1 reference for STEP 7 V5.x projects. Both SFCs execute synchronously, take only a few microseconds on a typical CPU, and consume no instance data.

SFC1 READ_CLK - Read CPU Clock

SFC1 reads the current internal clock of the CPU and returns it as an 8-byte Date_And_Time value. The function is non-blocking and updates the destination buffer on every call, so the caller can call it once per OB1 cycle without affecting scan time. The return value RET_VAL is an INT (0 = OK, non-zero = error code). The only error path on a working CPU is a system-level fault; the function will not fail on valid input.

Parameter Declaration Data Type Memory Area Description
RET_VAL Output INT I, Q, M, D, L Error code; 0 = success
CDT Output Date_And_Time D, L Current date and time of the CPU

Note that the CDT output is restricted to data block (D) and local stack (L) destinations - the L-Stack is the natural target when the value is consumed within the calling block, which is exactly the use case in Sync_Time.

SFC0 SET_CLK - Set CPU Clock

SFC0 takes an 8-byte Date_And_Time input and writes it to the CPU's internal real-time clock. The function must be called only when the input value is valid; SFC0 performs a BCD validation check on every field before issuing the write, and any out-of-range field results in a non-zero RET_VAL and no clock update. The CPU clock is not partially written - either the entire 8-byte buffer is accepted or none of it is.

Parameter Declaration Data Type Memory Area Description
RET_VAL Output INT I, Q, M, D, L Error code; 0 = success
PDT Input Date_And_Time D, L, constant New date and time to load into CPU

Both SFCs run in OB1, OB35, OB100, and OB1-cyclic OBs without restriction. On S7-400H redundant systems the SFCs route to the active controller automatically; on S7-300 the function is identical on standard CPUs and on the safety CPUs (CPU 315F, CPU 317F) because SFC0/SFC1 are not safety-related functions.

Date_And_Time Data Type Structure

Date_And_Time (DTL in TIA Portal) is an 8-byte packed BCD value. Each nibble carries a decimal digit, with reserved or qualifier bits in the most significant bits of the last two bytes. The byte order is fixed and matches the table below; the layout has not changed since the introduction of the S7-300 in 1994 and is consistent with the IEC 61131-3 standard's DT data type.

Byte Bit 7..4 Bit 3..0 Range Example
0 Year (BCD, 1990-2089) 00-99 B#16#13 = 2013
1 Month (BCD) 01-12 B#16#08 = August
2 Day (BCD) 01-31 B#16#05 = 5th
3 Hour (BCD, 24h) 00-23 B#16#06 = 06:00
4 Minute (BCD) 00-59 B#16#00 = :00
5 Second (BCD) 00-59 B#16#00 = :00
6 Milliseconds, two highest digits (BCD) 00-99 B#16#25 = 2500 ms
7 (4 MSB) Milliseconds, two lowest digits (BCD) 00-99 B#16#0 (or B#16#50 combined with byte 6)
7 (4 LSB) Day of week (1=Sun..7=Sat) 1-7 B#16#5 = Friday

Byte 7 packs the low two digits of the millisecond counter in the upper nibble (4 MSB of byte 7) and the day-of-week code in the lower nibble (4 LSB of byte 7). The millisecond counter across bytes 6 and 7 yields a 0..9999 range (a sub-second resolution of 0.1 ms). If the day-of-week nibble is 0, the CPU skips updating the weekday field and keeps the previous value, which is a useful shortcut when you want to splice the time-of-day without recalculating the day-of-week.

The B#16# notation in STEP 7 means "byte with hexadecimal value 16#06" - equivalent to a 1-byte constant 0x06. The numeric content of B#16#6 is therefore 6 (decimal), not 22 (which would be 0x16). This is a common source of confusion for new STEP 7 programmers who see the leading 16# and assume base conversion. A quick mental rule: in B#16# notation, the 16# marks the radix and the digit string that follows is the hexadecimal representation; each digit position is 4 bits.

BCD Encoding for Clock Values

Every byte written into the L-Stack for a clock field is BCD-encoded. The decimal digit 6 is encoded as 0x06, the decimal digit 12 is encoded as 0x12, the decimal 30 is encoded as 0x30. STEP 7 stores a single decimal digit per nibble, so each byte carries two decimal digits (e.g., 0x59 for 59 minutes). This is different from a binary 6 stored in a byte, which is also 0x06 but which would be ambiguous in a BCD decoder - the SFC0 validator only looks at the high nibble of each digit position to detect illegal values.

Decimal value BCD byte Hex notation in STEP 7 Decimal value BCD byte Hex notation in STEP 7
0 0000 0000 B#16#0 20 0010 0000 B#16#20
6 0000 0110 B#16#6 23 0010 0011 B#16#23
10 0001 0000 B#16#10 30 0011 0000 B#16#30
15 0001 0101 B#16#15 45 0100 0101 B#16#45
17 0001 0111 B#16#17 59 0101 1001 B#16#59

Any non-BCD bit pattern (such as 0x1A, 0xFF, or 0x3F) is rejected by SFC0 and the CPU clock is not updated. The same byte values are valid in Date_And_Time as in TOD (Time_Of_Day) and DT (Date_And_Time) declarations - the SFC and data type share the same BCD conventions. For the millisecond field, the CPU does not validate the day-of-week nibble in byte 7 LSB; a value of 0 is treated as "do not change" and a value of 1..7 sets the day-of-week explicitly.

Local Stack (L-Stack) Byte Addressing

Each block (OB, FB, FC) has its own private 256-byte local stack (L-Stack) for TEMP variables on the S7-300. The S7-400 has 512 bytes per priority class. The L-Stack is initialized to zero on every block entry, so any TEMP variable that is not explicitly assigned carries 0x00 until the block writes to it. The L-Stack is volatile: it is reused by every call to the same block and is lost the moment the block ends. This is why direct LB addressing is deterministic - the offsets do not change between block invocations.

When a TEMP variable of type Date_And_Time is declared, the compiler maps the variable to 8 consecutive L-Stack bytes. The starting address of the variable within the L-Stack is not symbolically accessible from inside the block - the L-Stack cannot be read by name from STL or LAD, only by LB0..LB255 (S7-300) or LB0..LB511 (S7-400). The compiler assigns offsets in the order TEMP variables are declared in the interface, with no reordering for size or alignment. As a result, the first TEMP declared occupies LB0..LB7, the second TEMP occupies LB8..LBn, and so on.

If the variable is the first TEMP declared in the block's interface, the mapping starts at LB0. The byte offsets within the Date_And_Time data type are deterministic:

Field L-Stack Offset (first TEMP Date_And_Time)
Year LB0
Month LB1
Day LB2
Hour LB3
Minute LB4
Second LB5
Milliseconds (high) LB6
Milliseconds (low) + Day-of-week LB7

This is exactly why the original program addresses LB3, LB4, and LB5 - those are the Hour, Minute, and Second fields of the first Date_And_Time TEMP variable. If additional TEMP variables precede the Date_And_Time variable, the offsets shift accordingly. The fact that the L-Stack offset of a TEMP variable is not directly visible in the editor is precisely the reason that the program does not look up the symbolic address - it relies on the compile-time fixed mapping and the convention of declaring the Date_And_Time variable first.

Important: Direct LB access only works when the Date_And_Time variable is declared as TEMP (not as IN/OUT/INOUT parameter of an FC) and is the first 8-byte TEMP in the block's declaration table. If additional variables are declared first, recompute the offsets before changing the code. The safest practice is to always declare the Date_And_Time variable as the very first TEMP and to add a comment showing the L-Stack layout in the program header.

On the S7-400 with multi-instance FBs and large TEMP blocks the same rules apply but the L-Stack is larger. On S7-300 the maximum block-local TEMP area is 256 bytes; on S7-400 it is 512 bytes per priority class. The S7-400 also has separate L-Stack areas per execution level (one per OB priority), so the offsets within an FC are not affected by which OB calls the FC, but a TEMP variable in OB1 occupies a different L-Stack area than a TEMP variable in OB35.

Program Walkthrough: Network by Network

The canonical Sync_Time block contains three networks. The LAD/FBD representation is shown below; equivalent STL is provided for engineers who prefer text mnemonics. The same logic in SCL (Structured Control Language) is shown as a reference implementation.

Network 1: Read current date/time

NETWORK 1
// Read current CPU date and time into temp Current_DateTime
CALL SFC1
  RET_VAL := #ret_val            // local INT for error code
  CDT      := #Current_DateTime  // 8-byte Date_And_Time buffer

After Network 1 the L-Stack buffer at LB0..LB7 holds the live clock value (e.g., 2024-05-08 12:34:56.789, weekday 3). The L-Stack was zero-initialized on block entry; SFC1 overwrites all 8 bytes atomically with the current CPU clock.

Network 2: Patch hour, minute, second

NETWORK 2
// Force 06:00:00, leave date and weekday untouched
      L   B#16#6
      T   LB3
      L   B#16#0
      T   LB4
      L   B#16#0
      T   LB5

Each L (Load) and T (Transfer) pair executes a byte MOVE. The Hour becomes 6, Minute becomes 0, Second becomes 0. Bytes 0 (Year), 1 (Month), 2 (Day), 6 (Millisecond high), and 7 (Millisecond low + Day-of-week) keep the values written by SFC1. The result is the original date with the time-of-day forced to 06:00:00.000.

Network 3: Write modified timestamp back to CPU

NETWORK 3
// Write patched timestamp to CPU clock on trigger
      A   M2.7
      JCN END0
CALL SFC0
  RET_VAL := #ret_val
  PDT     := #Current_DateTime
END0: NOP 0

The SFC0 call is only reached when M2.7 is TRUE. The JCN (Jump if RLO = 0) skips the call on every cycle where the operator has not pressed the sync button, keeping the CPU clock untouched. When the trigger is high, SFC0 validates the BCD buffer and writes the new clock to the CPU hardware.

Equivalent SCL Implementation

FUNCTION "Sync_Time" : VOID
VAR_TEMP
  Current_DateTime : DATE_AND_TIME;
  ret_val : INT;
END_VAR
BEGIN
  // Read current clock
  ret_val := READ_CLK(CDT := Current_DateTime);
  // Patch time-of-day fields (structured access hides LB offsets)
  Current_DateTime.HOUR   := 6;
  Current_DateTime.MINUTE := 0;
  Current_DateTime.SECOND := 0;
  // Write back when triggered
  IF "M2.7" THEN
    ret_val := SET_CLK(PDT := Current_DateTime);
  END_IF;
END_FUNCTION

The SCL version is structurally identical to the LAD version, with two improvements: structured access (Current_DateTime.HOUR) is self-documenting, and SCL hides the LB offsets from the developer. On STEP 7 V5.4+ SCL is available as a separate add-on, and on TIA Portal SCL is the default text language for new code.

Trigger Integration with WinCC HMI

In the original program the trigger is a single Merker bit, M2.7. The wiring path is straightforward: an HMI button on a WinCC screen is connected to a WinCC tag of type Binary Tag, which is mapped to the PLC address M2.7. When the operator clicks the button, WinCC sets the tag TRUE; STEP 7 detects M2.7 = 1 in the next OB1 cycle and executes SFC0.

Layer Address / Tag Data Type Direction Notes
WinCC tag (internal) Sync_Time_Trigger Bool Operator -> PLC Tag name in WinCC project
WinCC tag (PLC address) M2.7 Bool (one bit of MW2) WinCC write Address in the PLC merker area
STEP 7 logic JCN at M2.7 Bit Gates SFC0 call Static or edge-detected
CPU clock Time-of-day Date_And_Time SFC0 sets to 06:00:00 On trigger assertion

Because the bit is never reset by the PLC, it stays high until the operator toggles the button again, which can cause SFC0 to be called on every OB1 cycle. To avoid the overhead, add a reset rung:

NETWORK 4
// Reset trigger after one execution
      A   M2.7
      R   M2.7

Better still, replace the static read with a rising-edge evaluation so the SFC0 call fires exactly once per button press:

NETWORK 2
// Edge detection (one-shot per press)
      A   M2.7
      FP  M2.7_old
      =   #go_sync

NETWORK 3
      A   #go_sync
      JCN END0
CALL SFC0
  RET_VAL := #ret_val
  PDT     := #Current_DateTime
END0: NOP 0

On the WinCC side, configure the button as a momentary-contact input (release-after-press) with the Toggle property cleared. The internal WinCC tag should use the Acquire continuously acquisition cycle (default 1 s) for a snappy feel, or the On change cycle to minimize network traffic. If the operator is allowed to abort an in-progress sync, expose the trigger bit to the HMI as a visible status indicator (lamp).

For redundant WinCC pairs, define the same tag in both projects and use the WinCC redundancy control to keep the trigger consistent. For multi-client installations, do not share the trigger bit across HMI servers - use a dedicated M bit per server or a coordinated trigger exchange via the PLC.

Step-by-Step Implementation in STEP 7 V5.x

  1. Open SIMATIC Manager and load the S7-300/S7-400 project. Add a new FC (e.g., FC50 "Sync_Time") under the S7 program sources.
  2. Open the FC interface and declare Current_DateTime as a TEMP variable of data type Date_And_Time. Place it as the first TEMP entry, with no other TEMP variables preceding it.
  3. Add a second TEMP ret_val of type INT for the SFC error code.
  4. Insert Network 1 with the SFC1 call. Wire RET_VAL to ret_val and CDT to Current_DateTime.
  5. Insert Network 2 with three MOVE boxes: B#16#6 → LB3, B#16#0 → LB4, B#16#0 → LB5. If you use STL, code the L/T pairs as shown above. In FBD, use three MOVE boxes with the same source/destination pairs.
  6. Insert Network 3 with the SFC0 call. Place a conditional jump (JCN) so the SFC is only called when the trigger bit M2.7 is set.
  7. Call FC50 from OB1 unconditionally. The block is short enough that the unconditional call is acceptable; the trigger gate inside FC50 keeps SFC0 from running unless needed.
  8. In HW Config, reserve the M area so M2.7 is in the merker flag area (default on S7-300 is MB0..MB2047 unless the M area is restricted in the CPU properties dialog).
  9. Compile the program and download to the CPU. Use a full download if the merker area overlaps with retentive memory; a delta download is sufficient when only the FC changed.
  10. Configure the WinCC tag with the same address (M2.7) and test from the runtime screen.

For S7-400 the same procedure applies; the only difference is the larger L-Stack and the additional priority-class organization. For S7-300 with a CPU 312/313 (which have a smaller L-Stack) the Date_And_Time variable still fits because it occupies only 8 bytes.

Verification Procedure

After download, the operator can verify the function from the PG (programming device) or the HMI. The recommended sequence is:

  1. Open the STEP 7 Monitor/Modify view (or WinCC tag list) and watch M2.7 toggle to TRUE when the button is pressed. Confirm the bit returns to FALSE on the next cycle if you added the reset rung.
  2. Open PLC > Online > Set Time of Day in SIMATIC Manager and note the current CPU clock value. The dialog shows the same Date_And_Time buffer that SFC1 would read.
  3. Press the WinCC sync button. Re-open Set Time of Day; the time should now read 06:00:00 with the original date preserved. If the time did not change, check the SFC0 RET_VAL in the Monitor view.
  4. Add a temporary Message (ALARM_S / SFC17) in the block to announce the sync to the operator log so that the event is recorded in the diagnostic buffer with a timestamp from before the sync.
  5. Cycle power to the CPU and confirm the new time is retained (battery is installed and time-of-day retention is enabled in the CPU properties).
  6. Repeat the test at 23:59:55 to verify the time-of-day transition (i.e., that the second-precise setting holds across the midnight rollover).

For shop-floor sign-off, capture a screenshot of the time-of-day dialog before and after, and a log entry from the ALARM_S message. The diagnostic buffer on the CPU also records the last SFC0 call with its return code; export the buffer to a CSV file using PLC > Save to Text File for audit purposes.

Common Errors and Diagnostics

Symptom Likely Cause Fix
SFC0 RET_VAL = W#16#8080 (hour out of range) Byte 3 contains > 23 or non-BCD nibble Reload LB3 with a valid BCD hour (0x00..0x23)
SFC0 RET_VAL = W#16#8081 (minute out of range) Byte 4 > 59 or non-BCD Reload LB4 with valid BCD minute (0x00..0x59)
SFC0 RET_VAL = W#16#8082 (second out of range) Byte 5 > 59 or non-BCD Reload LB5 with valid BCD second (0x00..0x59)
Clock not updating despite button press M2.7 is in a non-mapped M area or used by the OS Check CPU properties, M area reservation, and process image configuration
Time of day reverts to default after power cycle CPU has no battery and the time is not retentive Install a backup battery or enable time-of-day retention in CPU properties
Date resets to 1990-01-01 Year byte (LB0) was not loaded by SFC1 because the L-Stack was zero-initialized before call Confirm SFC1 is called before the MOVE block and that the L-Stack is large enough
SFC0 call blocked by SFC36-39 in priority class OB is higher than OB1 priority and is non-interruptible Move sync call to OB1 or a low-priority cyclic OB
MOVE writes wrong offset Other TEMP variables declared before Current_DateTime shift the offsets Reorder TEMP declarations to put Date_And_Time first, or recompute the offsets
CPU goes into STOP after SFC0 call SFC0 reports a fatal system error (ret_val = W#16#80A1) Check CPU diagnostic buffer; usually indicates hardware fault or missing battery
Date displays correctly but time is wrong by 1 hour Daylight saving time transition not handled; CPU time is local time Decide whether the CPU should follow DST (configurable in CPU properties for newer firmware)

Diagnostic buffer entries on the CPU can be cross-referenced against the S7-300/400 CPU manual error code list, as documented in the Standard and System Functions reference. The most common SFC0 error codes include W#16#8080 (hour), W#16#8081 (minute), W#16#8082 (second), W#16#8083 (millisecond), W#16#8084 (year), W#16#8085 (month), W#16#8086 (day), and W#16#8090 (illegal day-of-week). Note that error codes W#16#80xx in SFC0 only signal range/BCD errors; a zero return value confirms a clean write.

Modern Alternatives: TIA Portal, NTP, and PTP

On S7-1200 and S7-1500 the SFC0/SFC1 mechanism is replaced by the DTL data type and the system blocks RD_SYS_T (Read System Time) and WR_SYS_T (Write System Time). TIA Portal does not expose an L-Stack to the user; the program reads into a DTL tag, modifies the hour/minute/second with structured access, and writes back through WR_SYS_T.

"DB_Time".TimeStruct.Hour := 6;
"DB_Time".TimeStruct.Minute := 0;
"DB_Time".TimeStruct.Second := 0;
WR_SYS_T(TIME := "DB_Time");

For factory-wide time-of-day distribution the S7-1500 supports NTP via the PROFINET interface, and S7-300/400 with CP343/CP443 communications processors can act as NTP clients. PTP (Precision Time Protocol, IEEE 1588) is supported on selected S7-1500 CPUs and PROFINET switches, and is the recommended way to distribute a sub-millisecond clock across a plant. PROFINET devices can be configured as PTP slaves for transparent time distribution from the controller.

For new designs, prefer the DTL approach with structured access and a single NTP-synchronised source. Reserve the SFC0/SFC1 L-Stack pattern for legacy STEP 7 V5.x maintenance and migration projects where the existing code base is fixed. When migrating, use the LAD-to-SCL converter in TIA Portal to convert the SFC0/SFC1 calls to RD_SYS_T/WR_SYS_T and to migrate the Date_And_Time buffers to DTL tags. Verify the conversion in the TIA Portal cross-reference tool to ensure no offsets or merker bits are left behind.

Operational and Safety Notes

The Sync_Time pattern is a maintenance convenience, not a safety function. If the CPU clock is part of a safety chain (e.g., timestamping of safety events, time-window interlocks, or SIL-rated alarm acknowledgement), do not rely on the operator's button press alone to keep the clock accurate - the clock will drift between syncs. Use a hardware NTP source or a GPS receiver for safety-critical timestamps.

If the operator is allowed to set the time to any arbitrary value, consider adding a confirmation prompt on the HMI to prevent accidental time jumps that could trigger a batch alarm or invalidate a timestamped audit trail. The dialog should display the current time, the proposed time, and the time delta, and require a separate confirmation to proceed.

For plants subject to FDA 21 CFR Part 11, time jumps greater than 1 second must be logged with a reason; the ALARM_S message can be extended to capture the operator's user ID and a free-text reason. The same log should be retained for the lifetime of the affected batch record.

Frequently Asked Questions

Why does the program use B#16#6 instead of just 6?

B#16#6 is a STEP 7 byte constant (1 byte long, value 0x06). The Date_And_Time data type stores every clock field as a single byte in BCD, so a 1-byte constant is the only way to write a single field without disturbing the neighboring bytes. Loading a 16-bit integer 6 with the L instruction would clobber two consecutive L-Stack bytes and corrupt the next field in the Date_And_Time buffer.

How do I know that LB3 is the Hour field?

Date_And_Time has a fixed 8-byte structure: Year at byte 0, Month at byte 1, Day at byte 2, Hour at byte 3, Minute at byte 4, Second at byte 5, Milliseconds at bytes 6 and 7. When the variable is declared as the first TEMP in the block, the compiler maps it starting at LB0, so Hour lands on LB3. The mapping is identical on S7-300 and S7-400.

Can the Date_And_Time variable be declared as IN/OUT instead of TEMP?

Yes, but in that case the L-Stack offsets are not LB0..LB7 - they are the parameter area for the FC (the FC parameter interface is laid out in front of the L-Stack). For portable code, keep the variable as TEMP and reorder the TEMP declarations so the Date_And_Time variable is always first, or move the patch logic to SCL where structured access hides the offsets entirely.

What happens if the CPU has no battery and the time is not retentive?

SFC0 sets the time to the supplied value, but a power cycle resets the internal clock to the default (1990-01-01 00:00:00) on CPU types without a battery or with retentive clock disabled in HW Config. Enable the backup battery, set the time via NTP after every power-up, or use an FB that calls SET_CLK from OB100 startup with a saved or NTP-supplied value.

Can I set the date as well, not just the time?

Yes - the same pattern works. Add MOVE operations for LB0 (Year), LB1 (Month), and LB2 (Day) in BCD, e.g., B#16#24 to LB0 for year 2024 and B#16#07 to LB1 for July. Make sure the day-of-week field at LB7 lower nibble is updated, or set it to 0 to let the CPU keep the previous weekday. For complex date logic, call the standard FC6/FC8 DATE and DAY_OF_WEEK functions to derive the weekday from the target date, then write it to LB7 LSB.

Is there a risk of damaging the CPU or losing program data with SFC0?

No. SFC0 only writes the real-time clock; it does not touch the program, data blocks, or system memory. Invalid BCD values are rejected with a non-zero RET_VAL and the clock is not updated. The function is safe to call repeatedly from any OB, and on S7-400H the call is automatically routed to the active controller.

How do I convert the pattern to SCL for an S7-1500 migration?

Replace SFC1 with RD_SYS_T and SFC0 with WR_SYS_T. Replace the Date_And_Time TEMP variable with a DTL tag in a global DB. Use structured assignment (tag.HOUR := 6) instead of L/T byte access. Remove the LB arithmetic entirely; the S7-1500 does not expose an L-Stack to the user program. The trigger logic and edge detection remain identical.

Back to blog