Problem Description
An S7-1200 CPU is paired with a KTP700 Comfort HMI in TIA Portal V16 or later. The PLC logic uses M0.3 as a normally-open start tag and M0.2 as a normally-closed stop tag. Two physical buttons on the KTP700 are wired to those tags through HMI tag connections. After downloading the project and starting the simulation, the NC stop tag (M0.2) toggles on its own at a fixed cadence. The operator cannot hold the stop command in the closed state, and the controlled load cycles randomly. The start tag M0.3 appears to behave erratically as well, but with a longer interval between unwanted transitions.
This symptom is almost always caused by one of two configuration problems: clock memory bits are enabled in the CPU hardware configuration at the default address MB0, or the project is built around raw memory addresses rather than symbolic tags. In many field cases both conditions are present, and the cure is the same: remove user logic from the clock memory address range and refactor the project to use a tag table plus a global data block.
Root Cause Analysis
The S7-1200 CPU exposes a configurable clock memory byte that toggles each bit at a fixed, known frequency. When the CPU properties are left at their defaults, the byte is mapped to MB0 and the bits become "free" oscillators for use as blink flags, clock generators, or periodic triggers. The drawback is that every bit from M0.0 to M0.7 is therefore unusable for any application that needs a stable, writable state. If a developer writes start/stop logic into M0.2 and M0.3, those bits are driven by the clock generator, not by the HMI or the program.
Confirmation path: open the PLC online with TIA Portal, attach a watch table or trace, and monitor M0.0 through M0.7. Any bit that toggles at a fixed period with no program assignment is a clock memory bit. The HMI button press is irrelevant because the CPU overwrites the bit at scan time before the user's logic can latch a value. The S7-1200 system manual documents this behavior under the System and clock memory section of the device configuration; see the Siemens Industry Online Support portal at support.industry.siemens.com for the latest firmware-specific note.
S7-1200 Clock Memory Architecture and Default Periods
Clock memory is configured under CPU Properties > System and clock memory in the device configuration. When enabled, an address (default MB0) is reserved and every bit inside that byte is forced by the operating system. The period of each bit follows a binary cascade; bit n has a period 2^n times the base period. The default base period is 100 ms, which produces the following default mapping for an S7-1200:
| Bit | Default Period | Default Frequency | Duty Cycle |
|---|---|---|---|
M0.0 |
0.1 s | 10 Hz | 50% (50 ms high / 50 ms low) |
M0.1 |
0.2 s | 5 Hz | 50% (100 ms high / 100 ms low) |
M0.2 |
0.4 s | 2.5 Hz | 50% (200 ms high / 200 ms low) |
M0.3 |
0.8 s | 1.25 Hz | 50% (400 ms high / 400 ms low) |
M0.4 |
1.6 s | 0.625 Hz | 50% (800 ms high / 800 ms low) |
M0.5 |
3.2 s | 0.3125 Hz | 50% (1600 ms high / 1600 ms low) |
M0.6 |
6.4 s | 0.156 Hz | 50% (3200 ms high / 3200 ms low) |
M0.7 |
12.8 s | 0.078 Hz | 50% (6400 ms high / 6400 ms low) |
The reported symptom matches M0.2 at the 2.5 Hz default: every 200 ms the bit transitions to 1, and 200 ms later it falls back to 0. The HMI button cannot override this because the clock memory write happens at the start of every OB1 cycle. The start tag M0.3 at 1.25 Hz is also unstable and would manifest as a delayed, irregular latch.
Why Raw Memory Addresses Are a Maintenance Trap
Memory bits are physical addresses with no semantic meaning. There is no compile-time check that two unrelated program blocks are using M0.2 for different purposes, no remapping when the CPU is upgraded, and no relationship to the HMI tag database beyond a manual cross-reference. The TIA Portal tag system exists specifically to remove this hazard: a symbolic tag of type BOOL compiles to an M-area address only at the final stage, and the compiler can enforce uniqueness, retention, and access direction.
Four failure modes follow from direct memory address use:
-
Collision with system bytes.
MB0throughMB31are commonly consumed by clock memory, process image partition flags, and certain diagnostics. The S7-1200 system manual reserves specific ranges for these uses. -
Multiple writers. Two FBs may each contain
SET "M0.2"in different branches of the program. The compiler will not warn; the second writer wins. -
HMI alias drift. The KTP700 area pointer must reference a tag name, not a raw
Maddress, otherwise the connection will silently break when the project is consolidated. -
Library portability. A library block that hard-codes
M0.2cannot be reused in a project whereM0.2is reserved for clock memory or a different function. Symbolic tags make the block instance-portable.
M-Area vs Global DB: Architectural Comparison
| Aspect | M-Area Memory Bit | Global Data Block Tag |
|---|---|---|
| Address allocation | Manual by developer | Automatic by compiler |
| Conflict detection | None at compile time | Compile-time error if duplicate |
| HMI access | Area pointer required | Direct symbolic access |
| Retain attribute | Set in tag table | Set per DB member |
| Snapshot on download | No | Yes (DB start values) |
| Multi-instance reuse | Not possible | Yes via FB instance DB |
| Vulnerable to clock memory | Yes if address matches | No (lives in DB memory) |
Diagnostic Procedure (Triage in Under 60 Seconds)
- Open the project in TIA Portal and expand PLC_1 > Device configuration > Properties > System and clock memory. Note whether Enable clock memory is checked and what address is assigned.
- Open an online watch table on
MW0. Trigger a value read once per second for 10 s. If any bit transitions on its own, clock memory is active at that address. - Search the entire project for occurrences of
M0.using Project tree > Find > Search in code. Every hit is at risk of being overwritten. - Open the KTP700 HMI tag table and inspect the connection of the Stop button. Confirm the tag is symbolic and points to the same DB instance as the PLC logic.
- Force
M0.2to TRUE from the watch table. If the value reverts within 200 ms, the clock memory generator is the writer. - Open Project tree > Cross-references, filter to
MB0, and verify whether the only reference is the clock memory system data or whether user code also writes the byte.
Solution 1: Disable or Relocate the Clock Memory Byte
The fastest cure is to take the clock memory byte away from MB0. Two options are available.
Option A: Disable clock memory entirely
If no part of the project uses M0.0–M0.7 as a periodic source, clear the Enable clock memory checkbox in the CPU properties and download the hardware configuration. After the next warm restart, MB0 is fully writable. This is the cleanest fix when clock memory is not actually needed.
Option B: Move the clock memory byte to a safe area
Open CPU Properties > System and clock memory and change the address from MB0 to a byte that the rest of the project does not touch, for example MB200. Recompile, then perform a full download of hardware and software. The download must be a full download (not a delta) so that the system data block containing the clock memory pointer is overwritten on the CPU. A partial download leaves the original MB0 pointer in place until the next STOP-RUN transition.
Solution 2: Adopt Symbolic Tags Project-Wide
Symbolic tags eliminate the address-collision class of bugs by handing the address allocation to the compiler. The recommended procedure in TIA Portal is:
- Open PLC tags > Default tag table. Delete every entry except physical I/O tags (%I, %Q) that come from the device configuration.
- For each new tag, declare it directly in the program code. Type a name (
Start_PB,Stop_PB,Motor_Run) on the operand position in the ladder or FBD, then right-click and select Define tag. TIA Portal picks the lowest freeMbit that fits the data type. - Alternatively, create a separate tag table per functional area (e.g. Tags_Motors, Tags_Valves) and assign tags by category. Each table can be exported as text for documentation.
- After defining the symbolic tags, rebuild the hardware and download the entire project. Confirm via cross-reference that the new tags compile to addresses outside the clock memory range.
Once the project is symbolic, the clock memory byte can sit at MB0 indefinitely because no user logic will be placed at those addresses.
Solution 3: Use a Global Data Block for Project State
Putting all program state inside a global DB has four engineering benefits over scattering bits in M-area:
- The DB has a downloadable snapshot. A download to the CPU initializes all DB tags to their start values, eliminating stale state from previous runs.
- Symbolic access is enforced everywhere. The compiler rejects an attempt to write a tag declared Read-only from outside the owning FB.
- HMI area pointers reference the DB symbolically. The KTP700 tag database pulls directly from
"Tags_DB".Stop_PB, so any rename is propagated. - The DB is independent of the clock memory address range. Clock memory only ever touches
MBaddresses, never DB members.
Create the DB as follows:
- Project tree > PLC_1 > Program blocks > Add new block > Data block. Choose Global DB, name it
Tags_DB. - Set Optimized block access = enabled (recommended for S7-1200 firmware V4.0 and later).
- Add the start, stop, latch, and any auxiliary flags as BOOL members of the DB:
SECTION
Start_PB : BOOL; // NO start from HMI
Stop_PB : BOOL; // NC stop from HMI
Motor_Run : BOOL; // Latched run output
END_SECTION
- In the user program, address
"Tags_DB".Stop_PBinstead ofM0.2. Repeat for the start tag and any other bit that participates in the start/stop logic. - Download hardware and software to the CPU, then cycle power or perform STOP-RUN to commit the new DB structure.
- In the KTP700 HMI tag table, right-click and select Import from PLC > Tags_DB. The tags appear with their symbolic names; bind the Stop button to
Tags_DB.Stop_PBand the Start button toTags_DB.Start_PB.
Solution 4: Local Tags Inside FBs and FCs
Local tags declared inside an FB's Static section or an FC's Temp section are scoped to the block. They cannot collide with memory bits, they cannot be read by the HMI directly (which is desirable for internal state), and they survive across scans until the block is exited. For reusable logic, FB instances with multi-instance capability keep the per-instance state isolated.
Pattern for a motor FB:
FUNCTION_BLOCK Motor
VAR
Start : BOOL; // Input parameter
Stop : BOOL; // Input parameter
Run : BOOL; // Static latched output
END_VAR
BEGIN
IF Stop THEN
Run := FALSE;
ELSIF Start THEN
Run := TRUE;
END_IF;
END_FUNCTION_BLOCK
Each call to Motor_DB gets its own Start, Stop, and Run. The instance DB lives in the load memory, not in MB, so clock memory cannot touch it.
KTP700 Button Configuration Best Practices
The KTP700 Comfort panel ties an HMI tag to the button event. Three configuration points determine whether the stop command reaches the PLC cleanly:
- Tag type. Use HMI tag with connection S7-1200 / S7-1500, not a raw area pointer. The tag must be defined in the PLC's default tag table or in a DB, and imported into the HMI tag table via PLC tags > Show in HMI.
- Acquisition mode. For an NC stop, set Acquisition mode = Cyclic continuous with a 100 ms cycle. The button's "1" state is held while pressed; releasing the button writes "0".
- Event wiring. On the Press event of the Stop button, configure Invert bit if the HMI expects an active-high write. On the Release event, write the cleared bit back. This guarantees the NC contact is closed the instant the button is released.
- Connection diagnostics. Open Connections > HMI_Connection_1 > Diagnostics in the KTP700 project node. Confirm the partner (PLC) is online and that no "connection interrupted" status is reported. A broken connection manifests as tags holding their last value, which is easy to confuse with a clock memory fault.
Wire the start and stop tags into the motor logic through symbolic references only. Verify in the KTP700 runtime simulation that the tag indicators on the button faceplate change state in response to the simulated press.
Verification Procedure
- Open the watch table and pin
"Tags_DB".Start_PBand"Tags_DB".Stop_PBat a 100 ms update rate. Confirm both are stable at 0 when no HMI input is active. - Toggle the HMI button from the KTP700 runtime. The start tag should go to 1 within 100 ms and stay at 1 while held; the stop tag should go to 0 only while the button is pressed (NC behavior inverted on the panel).
- Force
"Tags_DB".Stop_PBto TRUE from the watch table. The motor should de-energize and stay de-energized as long as the force is held. Release the force and confirm the motor does not re-start on its own. - Open the project cross-reference (Project tree > Cross-references) and confirm that
MB0throughMB0do not appear in any user code block. Only the system data block reference for clock memory should be listed. - Run the project for at least 5 minutes under no operator input. Confirm that no tag flips state without an HMI event or a deliberate program instruction.
- Trigger a STOP-RUN transition on the CPU. The
Tags_DBmembers that are not flagged as retain should reset to their start values; retain flags should persist. Confirm that no unexpected re-start of the motor occurs after the transition.
Troubleshooting Matrix
| Observed Symptom | Likely Cause | Diagnostic | Fix |
|---|---|---|---|
M0.2 toggles at ~0.4 s |
Clock memory active at MB0 | Watch table MW0 | Disable or move clock memory byte |
M0.2 random, not periodic |
Other FB writing M0.2 from a different branch | Cross-reference search | Refactor to symbolic tags / DB |
| HMI button does not reach PLC | Tag defined in PLC only, not in HMI tag table | HMI tag table filter | Import PLC tag to HMI |
| Start works once, then stuck on | No latching logic, M0.3 was reset by clock memory | Trace recording | Replace memory bits with SR flip-flop on DB tag |
| Behavior different after STOP-RUN | Retain / non-retain mismatch | DB properties > Retain | Set retain bits correctly |
| Compile warning about duplicate operand | Two blocks writing same M address | Compiler output | Adopt unique tag names |
| HMI button changes status but PLC does not respond | Area pointer mismatch | Connection diagnostics | Re-create HMI connection with correct rack/slot |
| Fault only after firmware update | Default address changed for clock memory in new FW | CPU properties after update | Re-verify clock memory assignment |
| Tag visible on HMI but reads always 0 | DB optimized access not compatible with absolute address on older FW | DB properties > Optimized access | Disable optimized access or upgrade firmware |
Safety Implications of M-Bit Misuse
An unstable stop tag is not a cosmetic bug. In a motor control context, an S7-1200 driving a contactor through a stop tag that flips at 2.5 Hz will chatter the contactor coil, leading to contact welding, coil overheating, and possible phase-to-phase fault. In a process valve context, an unstable close command can oscillate a pneumatic actuator and damage the seat. Always treat a clock memory overlap on a safety-relevant tag as a near-miss and re-validate the affected E-stop circuit before resuming production.
Related Edge Cases
Firmware differences. S7-1200 CPUs from firmware V4.2 onward support optimized DB access with symbolic-only debugging. Earlier firmware (V4.0–V4.1) requires that tags have an absolute address in the DB. Either way, no part of the user program should ever address clock memory bits directly.
Retain behavior. When clock memory is moved to MB200 and a global DB is added for project state, mark only the truly retentive tags (e.g. Motor_Run, counter setpoints) as retain. Start_PB and Stop_PB are operator inputs and must not be retain, otherwise a power cycle with the button held will re-start the motor without operator action.
Multi-station projects. If the project is replicated across multiple S7-1200 stations, ensure that the clock memory address is identical on every CPU. A station with the clock memory at MB0 and another at MB100 will produce inconsistent behavior when the same library block is instantiated on both. Centralize the address choice in the master project and propagate via the library mechanism.
HMIs other than KTP700. The same fault pattern appears with TP700, TP900, KTP900, KTP1200, and the Comfort/Advanced ranges. The fix is identical: tag-based HMI configuration and symbolic PLC tags. The diagnosis path is the same as well.
S7-1500 reference. S7-1500 CPUs use the same clock memory mechanism but the default address is usually MB0 as well, and the period cascade is identical. Projects migrated from S7-1200 to S7-1500 inherit the same fix.
LOGO! migration. Older projects that were ported from LOGO! or S7-200 often carry the habit of using M0.0–M0.7 as scratch bits. After migration to S7-1200, those same addresses collide with clock memory. The cross-reference search at the start of any migration is the cheapest insurance against post-migration flicker.
Commissioning Checklist
- Clock memory byte configured and located at a non-conflicting address, or disabled.
- All user memory references replaced with symbolic tags.
- Global DB created with start, stop, and latched run bits.
- HMI tag table imports DB tags directly, no raw area pointer.
- Cross-reference shows zero hits for
M0.0–M0.7in user code. - Watch table confirms tags are stable with no operator input.
- Force/release test on stop tag demonstrates the motor holds the OFF state.
- Five-minute no-input run shows no spontaneous state changes.
- STOP-RUN test confirms retain attributes are configured correctly.
- Safety circuit (if any) re-validated after any operand change.
Further Field Notes
On commissioning laptops where TIA Portal opens the project offline, the clock memory byte will show the configured address even when the CPU is disconnected. Verify the live CPU by going online and reading CPU Properties > System and clock memory; what is on the disk is not always what is running.
When the HMI shows the start and stop buttons with animated colors driven by the same tags used in the logic, a flicker in the button face color is a visual confirmation that the underlying bit is unstable. Treat this as a diagnostic hint, not as a separate fault.
If the project was generated from a template that automatically creates MB0-based tags, fix the template before fixing the project. Otherwise the next station commissioned from the template will exhibit the same fault.
Why does M0.2 flicker at exactly 2.5 Hz in my S7-1200 project?
M0.2 is the third bit of the S7-1200 clock memory byte, which by default starts at MB0 and uses a 100 ms base period. M0.2 therefore has a 0.4 s period (2.5 Hz) with a 50% duty cycle. The CPU overwrites the bit at the start of every OB1 cycle, so any HMI write to M0.2 is lost. Disable clock memory in the CPU properties or move it to a different address to free M0.2.
How do I find which memory bits are being driven by the clock memory?
Open the watch table online and monitor MW0 with a 100 ms refresh. Any bit that flips at a fixed period without a write from your program is a clock memory bit. The address of the clock memory byte is shown in PLC Device configuration > Properties > System and clock memory.
Can I keep clock memory enabled and just avoid M0.0 to M0.7 in my logic?
Yes. Clock memory only consumes the byte you assign in the CPU properties. If you change the clock memory byte to, for example, MB200, then M0.0 to M0.7 become ordinary memory bits and you can use them freely. Do not forget to perform a full download of hardware and software so that the system data block containing the new pointer is updated on the CPU.
Should I use a global DB or a tags table for start and stop bits?
Use a global DB for any tag that represents physical process state and that the HMI must read or write. Use the default tag table for internal helper flags that the HMI does not touch. Keeping the HMI-visible bits inside one global DB makes the HMI tag import single-step and makes future renaming safe.
Do I still need clock memory if I use a global DB?
Not necessarily. A blinking flag for an indicator light can be generated from a TON timer in the program and stored as a DB tag. Clock memory is convenient for fixed-frequency flags, but if you have a global DB and a few timers, you can reproduce the same behavior and remove the clock memory dependency entirely.
Will changing the clock memory address affect other parts of my S7-1200 program?
Only if other blocks reference those exact M addresses. After relocating the clock memory byte, run a project-wide cross-reference on the new address range to confirm no unintended overlap, then download the full hardware and software configuration to the CPU.