Learn PLCs free
Programming Examples28 min read5,591 words

Structured Text PLC Programming: Syntax and Examples

Learn IEC 61131-3 Structured Text with a complete state-machine example, scan-cycle model, function-block boundaries, portability checks and tests.

PPI
PLC Programming IO Editorial Team
Sourced guidance with documented review and correction standards

Structured Text (ST) is the textual PLC language in IEC 61131-3. It is well suited to state machines, calculations, arrays and reusable functions, but it still executes inside a configured PLC task. Correct ST therefore depends on scan order, persistent function-block state, bounded loops, explicit outputs and tests on the target runtime—not only on valid syntax.

IEC published IEC 61131-3:2025 Edition 4 on 22 May 2025. It defines the syntax and semantics of ST, LD and FBD, plus SFC elements and controller configuration concepts. The standard is a language baseline; it does not make vendor libraries, data layouts, task behavior or project files interchangeable.

Use Structured Text when the control problem becomes clearer as typed data, calculations, arrays, reusable blocks or an explicit state machine. Keep simple field permissives in Ladder when that is the language the maintenance team can safely diagnose. Mixed-language projects are normal; the engineering goal is one understandable behavior and one acceptance test, not loyalty to a syntax.

At a glance:

  • := assigns a value; = compares values in the common IEC-style syntax.
  • IF expresses priority decisions; CASE is usually clearer when one named state owns the outputs and transitions.
  • Timer, counter and edge instructions have persistent instance state and product-specific invocation rules.
  • A loop executes work inside one task invocation unless the programmer deliberately spreads it across scans.
  • A later assignment can overwrite an earlier one during the same routine execution.
  • Code is not portable until it compiles and passes the same edge-case matrix on the selected runtime.

Structured Text as a PLC programming language

ST is a standardized language inside a controller execution model

Structured Text is a high-level PLC programming language defined by IEC 61131-3. It uses textual statements, typed variables, expressions, decisions, loops, functions and function blocks to implement controller logic. The current IEC 61131-3:2025 Edition 4 record identifies ST alongside Ladder Diagram and Function Block Diagram, with Sequential Function Chart elements and controller configuration concepts also covered by the standard.

Calling ST a programming language does not make it a general-purpose desktop language. Its program organization units execute when the PLC runtime schedules them. Persistent function-block instances, task periods and priorities, input/output updates, retention, watchdogs, downloads and controller state all affect observable behavior. The same valid-looking algorithm can therefore behave differently after translation if those surrounding contracts change.

Language question Structured Text answer Target-specific evidence still required
What is the basic unit of execution? statements inside functions, function blocks and programs/other supported POUs task, program and routine invocation order
How are values assigned and compared? IEC-style ST commonly uses := for assignment and = for equality compiler syntax and extension reference
Does code retain state automatically? function-block instances and declared variables can carry state according to their class and scope initialization, retain/persistent and restart rules
Are loops allowed? FOR, WHILE and REPEAT constructs are part of common ST implementations compiler support, bounded workload and task-watchdog tests
Is the source portable? core concepts and much syntax transfer data types, declarations, libraries, timers, tasks and project format
Is ST inherently safer than Ladder? no language alone supplies the safety claim approved safety toolchain, architecture, verification and validation

Structured Text is not Pascal, C or “Ladder in words”

ST resembles Pascal in its block structure and looks familiar to conventional programmers, but resemblance is not source compatibility. It does not inherit the C memory model, C toolchain or operating-system process model. It also should not be treated as a mechanical line-by-line rewrite of Ladder: ST often expresses calculations, state ownership, arrays and reusable blocks more clearly, while Ladder can remain clearer for field permissives and maintenance diagnostics.

Choose the representation that makes the requirement, output ownership, scan behavior and negative tests easiest to review. A mixed-language project can keep device-facing permissives in Ladder, calculation/state logic in ST and reusable control behavior in function blocks. The acceptance matrix—not the number of languages—proves that the combined program behaves correctly.

Diagnostic answer map for search and AI-assisted implementation

“Structured Text program” can mean syntax reference, a complete machine example, a debugging question or a portable design pattern. Use this map to choose the right depth before copying a code block.

Question Direct answer Evidence required
What is Structured Text? ST is the textual programming language defined within IEC 61131-3 for programmable-controller applications. Current standard record plus the target vendor's supported-language documentation
Is ST the same as Pascal or C? It resembles conventional structured languages, but it executes in a PLC task with IEC data, POUs and vendor libraries; it is not source-compatible Pascal or C. Compiler syntax, task configuration and library reference
What does a complete ST program need? A problem statement, named I/O, state/ownership model, declarations, executable logic, known initial/restart behavior and acceptance tests. I/O table, code, scan trace, edge cases and target result
Does ST run from top to bottom? Statements in an invoked routine execute in order; surrounding task, program/routine order and I/O updates determine the full cycle. Task schedule, routine order and online trace
Why did an output change unexpectedly? A later statement, another routine, an HMI/external writer or output mapping may own the final value. Cross-reference, single-writer review and scan-by-scan trace
Should a timer be called inside a state? Only if the exact platform's instance semantics and skipped-call behavior support the intended reset/retention. A consistently called timer with an explicit enable is easier to review. Vendor timer reference and state-entry/exit tests
Are ST examples portable between CODESYS, Siemens and Logix? The algorithm can transfer; declarations, timers, edges, libraries, tasks, data and project structure commonly need translation. Compile report and identical acceptance matrix on each target
Is a browser exercise enough for commissioning? No. It can validate logic behavior and edge cases; the selected PLC must verify dialect, task timing, I/O mapping, retentivity and safety boundaries. Graded browser result plus target-controller test record
Should “structured text program example” have another page? No. The syntax, complete program, scan trace and tests belong on this canonical owner; a keyword-swapped page would split intent and links. Permanent alias redirect and canonical metadata

Ownership boundary: the Structured Text glossary owns the concise definition. This page owns syntax, complete code, execution, vendor translation and test intent. The PLC programming practice exercises owns the broader multi-language exercise catalogue.

Automation engineer tracing sensor and actuator states on a generic PLC conveyor training bench with a blank monitor
Generated editorial photograph: a physical I/O review at a training bench. It does not imitate a vendor IDE or claim that the visible hardware executes the examples below.

Structured Text guide contents

  1. Execution model
  2. Scan-by-scan trace
  3. Syntax essentials
  4. Program and acceptance contract
  5. Complete state-machine example
  6. Functions and function blocks
  7. Additional program patterns
  8. Defensive programming
  9. Arrays and bounded loops
  10. Vendor differences
  11. Compile and runtime faults
  12. Testing checklist
  13. Frequently asked questions

For a language-level overview first, use the Structured Text glossary. For the broader PLC model—field I/O, scan scheduling and matched LD/FBD behavior—start with the PLC programming guide.

Structured Text execution model

An ST routine does not run continuously just because it looks like conventional source code. A controller executes it when the configured task invokes its program or routine. The observable result depends on:

  • when inputs are sampled or read;
  • where the ST routine sits in task/program order;
  • which variables persist between calls;
  • when output data reaches the physical module;
  • how long the task may run before a watchdog or scheduling fault; and
  • what happens during download, mode change, restart and communications loss.

Assignments run in statement order within the routine. That means a later statement can overwrite an earlier assignment in the same call. Make this intentional: assign safe defaults once, then apply the state-specific commands.

Structured Text task cycle from input read through ordered statements and persistent state to physical output update
Deterministic explainer: a generic cyclic task model. Direct I/O access, task scheduling and output update timing vary by controller and configuration.

Structured Text scan-by-scan execution trace

A trace should distinguish the state read at the start of a task invocation from a state value assigned during that invocation. In the example below, a StartEdge presented while State = STATE_IDLE writes STATE_STARTING. The starting branch does not execute retroactively; it is selected on the next invocation. That one-cycle boundary is often hidden by an online display that refreshes much more slowly than the PLC task.

Six-scan Structured Text trace separating sampled start and feedback inputs current state timer call CASE branch next state and motor output with a later-assignment warning
Conceptual trace: state written in one task invocation selects its branch on the next; displayed timer values are illustrative, not a claim about a controller's measured cycle time.
Invocation Sampled inputs State selecting CASE branch Key statements State after routine Ordinary motor command
0 No request; no feedback IDLE Defaults applied; no transition IDLE FALSE
1 StartEdge = TRUE; permissives healthy IDLE Writes STATE_STARTING STARTING FALSE because the starting branch has not run yet
2 Start edge cleared; no feedback STARTING Enables start timer; writes command STARTING TRUE
3 Feedback becomes true STARTING Command remains true; feedback transition wins before timeout branch RUNNING TRUE
4 Feedback remains true RUNNING Starting timer enable is false; running state owns output RUNNING TRUE
5 Stop request true RUNNING Writes STATE_STOPPING; default/branch removes command according to design STOPPING Defined by the selected stop behavior

Three review lessons follow:

  1. Transition order is priority. If feedback and timeout are true on the same invocation, the first satisfied IF / ELSIF branch wins. Write and test that priority deliberately.
  2. Assignment order is ownership. Two assignments to MotorCommand in one routine are legal; the later executed assignment determines the value leaving that routine. Across routines or tasks, ownership can become harder to see.
  3. Online animation is not a scan trace. A human interface refreshing every few hundred milliseconds can skip many PLC cycles. Use a controller trace, sequence log or captured variables when the one-scan order matters.

Structured Text syntax essentials

The common core includes assignments, expressions, conditional statements, CASE, and bounded loops. Variables are strongly typed, but the exact available types and implicit conversion rules still need the target compiler's documentation.

VAR
    StartRequest        : BOOL;
    StopRequest         : BOOL;
    ProtectionHealthy   : BOOL;
    SpeedSetpointPct    : REAL;
    SpeedCommandPct     : REAL;
END_VAR

IF StopRequest OR NOT ProtectionHealthy THEN
    SpeedCommandPct := 0.0;
ELSIF StartRequest THEN
    SpeedCommandPct := LIMIT(0.0, SpeedSetpointPct, 100.0);
END_IF;

Three details matter:

  1. := is assignment; = is equality comparison in the IEC-style syntax.
  2. Boolean names should describe the state being true. ProtectionHealthy is easier to review than an ambiguous Overload.
  3. Library signatures can differ. Confirm the exact LIMIT, timer, conversion and string functions supplied by the target platform.

Choosing between IF and CASE

Use IF / ELSIF / ELSE for a small priority decision. Use CASE when one named machine state should own the outputs and legal transitions. Deeply nested IF statements often hide priority and recovery paths.

Timer instances

Timers are function blocks with internal state. Declare an instance, call it every relevant scan, and read its outputs. Do not assume a timer behaves like a stateless function.

VAR
    StartTimeout : TON;
END_VAR

StartTimeout(IN := State = STATE_STARTING, PT := T#3s);

IF StartTimeout.Q AND NOT MotorFeedback THEN
    FaultCode := FAULT_START_TIMEOUT;
    State := STATE_FAULTED;
END_IF;

The generic example shows intent. Timer type names, input/output names, reset behavior and retentivity must be checked on the selected runtime.

Structured Text program example contract

Code is only “complete” relative to a stated problem. This example controls the ordinary start, run, stop and fault sequence of one conveyor motor. It does not implement the safety-related stop, starter/VFD power circuit or physical I/O mapping. Those boundaries are independently designed and verified.

Problem statement and assumptions

When the conveyor is idle, a one-scan start request may begin a start attempt if all ordinary permissives are healthy. The PLC commands the motor and waits for running feedback. Missing feedback within the allowed start time causes a latched fault. A stop request or lost permissive removes the run command and enters a stopping state; feedback must disappear within the allowed stop time. Reset is accepted only while feedback is off and permissives are healthy.

Assumptions for the platform-neutral listing:

  • StartEdge and ResetEdge are already one-invocation pulses created by a reviewed edge detector.
  • MotorFeedback = TRUE means the ordinary running-status signal is present; it is not proof of safe standstill.
  • PermissivesHealthy combines ordinary process permissives, not the certified safety function.
  • Timer instances use the common IEC-style TON(IN, PT) interface shown. Translate to the target library rather than renaming blindly.
  • All variables shown as persistent program variables retain their value from one invocation to the next while the program runs. Power-cycle retentivity is a separate configuration decision.

I/O and internal-state list

Name Direction/type Physical or logical meaning Testable states
StartEdge Input BOOL One accepted ordinary start request No pulse, one pulse, held button converted to one pulse
StopRequest Input BOOL Ordinary stop request False, true during starting, true during running
ResetEdge Input BOOL One accepted fault-reset request No pulse, pulse while unsafe to reset, valid pulse
PermissivesHealthy Input BOOL Combined ordinary process permission Healthy at start, lost during start/run, restored
MotorFeedback Input BOOL Contactor/drive/motor running status selected by design Off, delayed on, lost while running, stuck on while stopping
MotorCommand Output BOOL Ordinary motor run request Off in idle/fault; on during valid starting/running
FaultActive Output BOOL Sequence is in fault state False outside fault; true in STATE_FAULTED
FaultCode Output UINT First actionable sequence diagnosis None, start timeout, feedback lost, stop timeout, invalid state
State Internal enum Exclusive sequence owner Idle, starting, running, stopping, faulted
Timer instances Internal FBs Start/stop supervision state Disabled/reset, timing, done

Acceptance cases before code review closes

Case Initial state Stimulus Expected state/output Failure the case exposes
Normal start Idle, permissives healthy, feedback off One StartEdge, then feedback before timeout Starting then Running; command remains on Missing transition or command gap
Held start Idle Physical button held but edge logic emits one pulse One start attempt only Level-sensitive repeated start/restart
Start timeout Starting Feedback remains off until timeout Faulted; command off; start-timeout code Endless starting state
Stop during start Starting StopRequest = TRUE Stopping; command off Stop priority below start completion
Lost permissive Running PermissivesHealthy = FALSE Stopping; command off Permissive checked only at initial start
Feedback lost Running Feedback false without a stop request Faulted with feedback-lost code Silent run-status loss
Stop timeout Stopping Feedback remains true Faulted with stop-timeout code False assumption that command-off equals stopped
Reset rejected Faulted, feedback true Reset edge Remains faulted Reset permits unintended restart/uncleared motion
Invalid state Approved isolated test Inject out-of-range state representation if platform permits Faulted with unknown-state code Unhandled enum/data corruption
Controlled restart Defined stopped setup Runtime power/mode cycle Documented state and outputs; no automatic motion Unreviewed initialization/retentivity

Complete Structured Text state-machine example

The example below controls an ordinary conveyor sequence. It is not safety logic. A safety-rated system must independently remove or prevent hazardous motion according to the validated design.

TYPE ConveyorState :
(
    STATE_IDLE,
    STATE_STARTING,
    STATE_RUNNING,
    STATE_STOPPING,
    STATE_FAULTED
);
END_TYPE

VAR
    State               : ConveyorState := STATE_IDLE;
    StartEdge           : BOOL;
    StopRequest         : BOOL;
    ResetEdge           : BOOL;
    PermissivesHealthy  : BOOL;
    MotorFeedback       : BOOL;
    MotorCommand        : BOOL;
    FaultActive         : BOOL;
    FaultCode           : UINT;
    StartTimeout        : TON;
    StopTimeout         : TON;
END_VAR

(* Safe ordinary-control defaults for this scan. *)
MotorCommand := FALSE;
FaultActive := FALSE;

StartTimeout(IN := State = STATE_STARTING, PT := T#3s);
StopTimeout(IN := State = STATE_STOPPING, PT := T#5s);

CASE State OF
    STATE_IDLE:
        IF StartEdge AND PermissivesHealthy THEN
            State := STATE_STARTING;
        END_IF;

    STATE_STARTING:
        MotorCommand := PermissivesHealthy;

        IF StopRequest OR NOT PermissivesHealthy THEN
            State := STATE_STOPPING;
        ELSIF MotorFeedback THEN
            State := STATE_RUNNING;
        ELSIF StartTimeout.Q THEN
            FaultCode := 1; (* Start feedback timeout *)
            State := STATE_FAULTED;
        END_IF;

    STATE_RUNNING:
        MotorCommand := PermissivesHealthy;

        IF StopRequest OR NOT PermissivesHealthy THEN
            State := STATE_STOPPING;
        ELSIF NOT MotorFeedback THEN
            FaultCode := 2; (* Feedback lost while commanded *)
            State := STATE_FAULTED;
        END_IF;

    STATE_STOPPING:
        IF NOT MotorFeedback THEN
            State := STATE_IDLE;
        ELSIF StopTimeout.Q THEN
            FaultCode := 3; (* Stop feedback timeout *)
            State := STATE_FAULTED;
        END_IF;

    STATE_FAULTED:
        FaultActive := TRUE;

        IF ResetEdge AND NOT MotorFeedback AND PermissivesHealthy THEN
            FaultCode := 0;
            State := STATE_IDLE;
        END_IF;

ELSE
    FaultCode := 999; (* Unknown-state recovery *)
    State := STATE_FAULTED;
END_CASE;
Structured Text conveyor state sequence from Idle through Starting and Running to a defined Faulted recovery state
Deterministic explainer: the principal sequence states. The code also includes a controlled stopping state, timeouts and unknown-state recovery.

Download the complete ST example and its acceptance-test CSV. Treat the file as platform-neutral teaching code: import or translate it only after checking the target compiler and I/O mapping.

Why the example is structured this way

  • Outputs receive explicit defaults before the state logic.
  • Every transition has a readable condition.
  • A start command is different from running feedback.
  • Starting and stopping have separate timeouts.
  • Reset is accepted only from a known stopped condition.
  • The ELSE branch catches an invalid state value.
  • The example avoids hidden retained run bits.

Run the Structured Text sequence and edge cases in the browser before translating it to a target controller. PLC Programming IO and PLC Simulation Software share ownership. The browser lab helps prove logic behavior; it does not validate wiring, safety, target timing, retentivity or firmware-specific behavior.

Structured Text exercise workflow from conveyor problem and I/O list through state model code run trace test matrix grading and target PLC verification
A runnable result closes the logic layer; compiler dialect, task timing, real I/O and safety remain target-system acceptance boundaries.

Functions and function blocks

Program organization unit State between calls? Typical use
Function Normally no instance state Conversion or calculation with a returned value
Function block Yes, per instance Timer, valve object, motor object or sequence module
Program Runtime/project dependent organization Scheduled application logic and coordination

A function block is useful when a machine object needs state, but its interface should stay small and diagnosable. Prefer explicit request, permissive, feedback and reset inputs over dozens of global tags.

Structured Text function-block interface separating commands and equipment feedback from command, state and diagnostic outputs
Deterministic explainer: a reviewable function-block boundary. Exact parameter syntax, instance declarations and method support differ by vendor.

Function-block review questions

  • Is each instance called exactly where the task design expects?
  • Are outputs assigned for disabled and faulted states?
  • Can an HMI command bypass a permissive?
  • Are retained and non-retained fields documented?
  • Does the diagnostic distinguish command, feedback, timeout and configuration faults?
  • Can the block be tested without energizing real outputs?

Structured Text program examples by control task

Examples should teach a transferable pattern and expose the condition that breaks it. These short listings use common IEC-style notation; declarations, instruction names, parameter order and restart behavior still belong to the target environment.

Control task Useful ST pattern Required edge case Better home elsewhere when…
Stop-dominant run memory Priority IF / ELSIF plus one writer Start and stop true together; permissive lost Certified safety behavior is required
Analog scaling Typed conversion, span validation and clamping Zero span, overrange, underrange and bad quality A supported vendor scaling block owns diagnostics
One-shot request Persistent edge-detector instance Held input, restart while high and skipped call Hardware capture is needed for a shorter-than-task pulse
Exclusive machine sequence Enum plus CASE and explicit transition timeouts Simultaneous transition conditions and invalid state A platform sequence/SFC tool is clearer to the team
Repeated channel calculation Bounded FOR loop over declared array bounds Index at both ends and task worst case Work cannot finish within the task budget
Reusable equipment object Function block with request, feedback, state and diagnostics Multiple independent instances and disabled calls Hidden globals or uncontrolled methods would dominate behavior

Stop-dominant motor run memory

The order makes the intended priority obvious: stop or lost permission clears memory before a start edge can set it. This is ordinary process control, not a safety circuit.

IF StopRequest OR NOT PermissivesHealthy THEN
    RunMemory := FALSE;
ELSIF StartEdge THEN
    RunMemory := TRUE;
END_IF;

MotorCommand := RunMemory AND PermissivesHealthy;

Test start and stop true together, a held start, a permission that drops for one task, download/mode change and power restart. Decide explicitly whether RunMemory initializes, retains or reconstructs from a machine state. Never let an HMI write the internal memory and the routine write it too without defined arbitration.

Analog scaling with a valid configuration boundary

This example demonstrates the calculation structure, not a universal raw range. It rejects a zero/negative span before division and reports whether the raw value lies inside the configured measurement endpoints.

RawSpan := RawHigh - RawLow;
ScaleConfigured := RawSpan > 0;

IF ScaleConfigured THEN
    RawAsReal := DINT_TO_REAL(RawInput);
    EngineeringValue := EngLow
        + ((RawAsReal - DINT_TO_REAL(RawLow))
        / DINT_TO_REAL(RawSpan))
        * (EngHigh - EngLow);

    SignalInRange := (RawInput >= RawLow) AND (RawInput <= RawHigh);
ELSE
    EngineeringValue := EngLow;
    SignalInRange := FALSE;
END_IF;

The code deliberately keeps configuration validity separate from signal plausibility. A calculation can succeed while the input is overrange. Decide whether to clamp the displayed value, preserve the diagnostic value, substitute a fallback or inhibit control according to the process requirements. The exact conversion functions and overflow behavior vary by compiler.

One-shot request with a persistent edge instance

Many PLC instructions execute every time they are scanned. Rockwell's Structured Text instruction guidance specifically warns that an instruction inside IF tag_xic THEN executes on every scan while the condition is true unless the programmer supplies edge conditioning.

VAR
    StartRise : R_TRIG;
END_VAR

StartRise(CLK := StartPushbutton);
StartEdge := StartRise.Q;

Call the instance consistently so it observes both low and high states. Test power-up while the physical input is already high, a one-task pulse, a held input and repeated low/high changes. For Logix, Siemens or another platform, use the supported edge instruction/pattern and document its prescan/restart behavior.

Single-writer output composition

Instead of assigning the physical output from multiple branches, calculate requests and compose the final command once near the interface boundary:

SequenceRunRequest := (State = STATE_STARTING) OR (State = STATE_RUNNING);
MaintenanceRunRequest := MaintenanceMode AND JogHeld;

MotorCommand := PermissivesHealthy
    AND NOT OrdinaryStopRequest
    AND (SequenceRunRequest OR MaintenanceRunRequest);

This does not solve arbitration automatically, but it creates one inspectable writer. The design still needs to define which modes are mutually exclusive, whether a transition can leave both requests true, and how safety-rated control acts independently of this ordinary output expression.

Defensive Structured Text patterns

PLC code must remain predictable when values are bad, feedback is late or a sequence enters an unexpected state.

Defensive Structured Text checklist for explicit output defaults, bound checks, transition timeouts and unknown-state recovery
Deterministic explainer: four practical review controls for ordinary PLC logic. Safety-related software follows the certified platform process and applicable functional-safety lifecycle.

Use these patterns:

  1. Default then override. Clear ordinary commands before the state-specific branch.
  2. Range-check indices. Never trust recipe or HMI indices before array access.
  3. Bound loops. A PLC task cannot tolerate open-ended work hidden inside a loop.
  4. Time out handshakes. Define what happens when the next device never responds.
  5. Separate validation from conversion. A successful type conversion does not mean the source value is plausible.
  6. Detect stale data. Communications status, sequence numbers or timestamps may be needed at integration boundaries.
  7. Handle the unknown state. A CASE ... ELSE branch provides a defined recovery path.

Do not describe ordinary defensive ST as safety-rated simply because it drives an output to false. Functional-safety logic requires the selected certified platform, safety requirements, verification and validation process.

Arrays and bounded loops

Arrays make repeated calculations compact, but the task still performs every iteration. Measure the worst case on the target CPU and task.

VAR
    Samples      : ARRAY[0..9] OF REAL;
    Sum          : REAL;
    Average      : REAL;
    Index        : INT;
END_VAR

Sum := 0.0;

FOR Index := 0 TO 9 DO
    Sum := Sum + Samples[Index];
END_FOR;

Average := Sum / 10.0;

Check the declared bounds, counter type and loop limit. CODESYS explicitly documents a counter-overflow pitfall when the loop end equals the maximum value of a small integer type. Do not assume every compiler handles overflow, CONTINUE, or malformed bounds the same way.

For larger data sets, distribute the work across scans, use a bounded index state, or move non-control analytics to an appropriate external service. Whether that is necessary depends on the task period, controller load and required response—not on a generic line-count rule.

Structured Text vendor differences

Structured Text portability matrix comparing compiler conversions, runtime tasks and function-block library behavior
Deterministic explainer: portability must be proven at compiler, runtime and library boundaries; common IEC syntax alone is not acceptance evidence.

Siemens SCL

Siemens calls its Structured Text implementation Structured Control Language (SCL). TIA Portal supports SCL blocks on applicable SIMATIC controllers. Confirm the target CPU, firmware and STEP 7 version because supported instructions and block behavior vary.

Rockwell Logix Structured Text

Studio 5000 Logix Designer provides Structured Text routines and documents its syntax, data types and instruction behavior in versioned online help. Rockwell's implementation is not a drop-in CODESYS project: tags, routines, Add-On Instructions, task structure and controller instruction support belong to the Logix environment.

CODESYS ST and ExST

CODESYS documents both ST and its Extended Structured Text (ExST) additions. An extension supported in one CODESYS target or compiler version should not be assumed portable to another toolchain. Build, download and test on the selected device description and runtime.

Boundary What may differ
Data types Supported widths, strings, aliases, layouts and conversions
Task model Priority, period, watchdog, event tasks and I/O update
Libraries Timer behavior, string functions, motion, communications and diagnostics
Retentivity Declaration, memory region, download and restart behavior
Project structure Program, routine, block and namespace organization
Online changes What can be edited, tested, accepted or rolled back

Vendor translation checklist

Boundary CODESYS-family question Siemens SCL question Rockwell Logix ST question
Declarations Which POU, scope, namespace and compiler extensions are enabled? Is the value local, static, temporary, input/output or in an instance/global DB? Is it a controller/program tag, routine parameter, UDT or instruction control structure?
Timer/counter Which standard/library FB instance and call semantics apply? Which IEC timer instance form and block storage are supported on this CPU/project? Which timer/counter instruction is available in ST for this controller/version and what structure does it use?
Rising edge Is R_TRIG from the selected library called every required cycle? Is the edge memory stored in a persistent block location with defined restart behavior? Is a supported one-shot instruction/control tag used and prescan behavior understood?
Data conversion Are implicit/explicit conversions and target-native intermediate widths acceptable? Do optimized blocks, typed constants and conversion functions match the interface? Do tag types and instruction operands match the versioned Logix reference?
Task/runtime Which task calls the program, with what interval, priority and watchdog? Which organization block/cyclic task calls the block, and when is I/O updated? Which task/program/routine calls the ST routine and what are its period/priority/watchdog?
Restart/change What initializes or retains after reset, download and online change? What is remanent, initialized or re-created in the data block? What do prescan, program-mode transition and download do to tags/instructions?

The current CODESYS CASE reference documents labels, ranges and ELSE; Rockwell's Logix ST programming manual documents its own constructs; Siemens publishes both an S7-1200/1500 programming guideline and a TIA Portal programming style guide. Use those product sources to translate the pattern, then run the same cases.

Common Structured Text compile and runtime faults

Symptom Likely cause Evidence to inspect Corrective direction
Compile error at END_IF or next line Missing semicolon, wrong terminator or dialect mismatch earlier First compiler diagnostic and preceding statement Fix the earliest error; confirm target syntax rather than adding punctuation randomly
Value changes back within one task Later assignment or second writer Cross-reference, write breakpoints/trace and routine order Establish one owner or explicit arbitration
Timer never finishes Instance not called consistently, enable resets, wrong time literal or dialect Instance IN/Q/ET, call path and exact timer manual Use explicit enable and tested call/reset behavior
Action repeats while button is held Level condition used where an edge was required Input, edge memory and action counter scan trace Add a supported one-shot pattern and restart test
Array logic faults only at last element Inclusive bound/index mismatch or typed counter overflow Declaration bounds, loop start/end and runtime exception Derive/test bounds and choose a counter type that can exit
Analog result jumps or saturates Integer division, conversion/overflow or invalid span Operand types, intermediate values and quality flags Convert deliberately; validate span and range before use
Behavior differs after restart Initial/retained values or prescan behavior not defined Power/mode-cycle trace and memory configuration Specify initialization and retentivity as requirements
Watchdog/task overrun Unbounded loop, variable work, blocking library or excessive processing Worst execution time, task diagnostics and loop count Bound/distribute work or change architecture after measurement
Browser result passes, target fails Dialect, timer, task, I/O or retained-state difference Compiler report and side-by-side acceptance record Translate the boundary and repeat cases on the selected target
Code stops motion but safety claim is unsupported Ordinary logic confused with certified safety function Risk assessment, safety requirements and certified platform docs Keep ordinary sequence and safety lifecycle separate

Structured Text vs Ladder Logic

Choose the language from the task and maintainers rather than calling one language universally better.

Requirement Usually favors ST Usually favors Ladder
Array or recipe processing Yes No
State-machine transitions Often Sometimes
Dense calculations Yes No
Simple permissive chain Sometimes Often
Online electrical-style tracing No Often
Reusable text-based algorithm Yes Sometimes

Mixed-language projects are normal where the platform supports them. The important part is a shared tag model, reviewable interfaces and matched acceptance tests.

Structured Text test and commissioning checklist

Run the example with the physical output isolated or in an approved test environment.

Test Action Expected evidence
Normal start Start edge with all permissives Starting then Running after feedback
Start timeout Hold feedback false Fault code 1 and command removed
Stop request Stop while running Command removed and Stopping entered
Stop timeout Hold feedback true Fault code 3 and Faulted state
Lost permissive Remove a permissive while running Command removed; recovery path recorded
Invalid state Force only in an approved test ELSE branch moves to Faulted
Held start Keep request true through recovery No unintended restart if edge logic is required
Controller restart Controlled mode/power cycle Defined state and outputs, no unintended movement

Record:

  • controller, firmware and engineering-tool versions;
  • task period, priority and watchdog;
  • project checksum or version identifier;
  • initial and retained values;
  • test inputs, observed transitions and timestamps;
  • any differences between simulator and target runtime; and
  • reviewer approval plus unresolved deviations.

Frequently asked questions

What is Structured Text PLC programming?

Structured Text (ST) is the textual programming language defined within IEC 61131-3 for programmable-controller applications. It expresses typed assignments, conditions, loops, functions and function-block calls inside a PLC task. The standard provides a baseline; the selected vendor determines the engineering project, task configuration, libraries, instruction availability and target behavior.

What is a simple Structured Text program example?

A stop-dominant motor request is a useful first example: clear run memory when stop is requested or permissives are unhealthy, set it on a one-scan start edge, then compose the ordinary motor command once. Even this small program needs tests for simultaneous start/stop, held start, lost permissive and restart state.

Does Structured Text execute from top to bottom?

Statements in an invoked routine execute in order, so a later executed assignment can overwrite an earlier one. The complete behavior also depends on the PLC task, program/routine order, conditional calls, I/O update and other writers. Use a scan trace and cross-reference when order affects the result.

Should I use IF or CASE in Structured Text?

Use IF / ELSIF / ELSE for a small prioritized decision. Use CASE when one enumerated machine state should own outputs and legal transitions. Add an ELSE or equivalent unknown-state policy where the target compiler and state representation make that appropriate, and test simultaneous transition conditions.

How do timers work in Structured Text?

Timers are stateful instructions or function blocks whose exact call, reset, time base, fields and skipped-call behavior vary by platform. Declare the required instance/control data, call it as the vendor documents, expose its enable/done/elapsed evidence and test state entry, exit, timeout, reset and restart.

How do I make a one-shot in Structured Text?

Use the target platform's supported rising-edge instruction or a reviewed previous-state pattern. The edge detector needs persistent memory and consistent invocation. Test a one-task pulse, held input, repeated low/high cycles, and restart while the physical input is already high.

Are Structured Text examples portable between PLC brands?

Algorithms and state models can be portable, but source is not automatically drop-in. Declarations, timers, edge instructions, conversions, namespaces/data blocks, tasks, retentivity and libraries differ among CODESYS, Siemens SCL, Rockwell Logix ST and other environments. Compile and run the same acceptance matrix on each target.

How do I prevent a Structured Text loop from overrunning the PLC task?

Prefer a bounded FOR loop over declared array bounds, choose a counter type that can pass the terminal value, and measure worst-case execution in the configured task. Put an explicit iteration guard around condition-based loops. If the work cannot fit with margin, distribute it across scans or move it outside the control task.

How should I test a Structured Text state machine?

Test every normal transition, every timeout, simultaneous conditions, held requests, lost feedback/permissives, invalid state handling, reset rejection and controlled restart. Record current state, next state, timers, commands, feedback, fault code and task timestamps. Run logic tests first, then repeat target-specific cases with I/O isolated or under an approved commissioning plan.

Where can I run Structured Text code without a PLC?

Use a browser learning simulator or a vendor-supported simulator/runtime appropriate to the goal. The runnable Structured Text learning path can grade logic examples without hardware. It shares ownership with this site and is not a firmware-exact substitute for the selected PLC, engineering tool, field I/O or safety validation.

Sources, review scope, and limitations

This owner was reviewed on 29 August 2026 against the current standard record and primary vendor documentation. Direct links let readers and AI answer systems distinguish common IEC-style patterns from product-specific behavior.

  1. IEC 61131-3:2025 Edition 4 publication record
  2. PLCopen-hosted IEC 61131-3:2025 table of contents
  3. PLCopen coding guidelines for IEC 61131-3
  4. CODESYS Structured Text editor
  5. CODESYS ST IF statement
  6. CODESYS ST CASE statement
  7. CODESYS ST FOR statement and overflow caution
  8. CODESYS Extended ST CONTINUE statement
  9. Rockwell Automation Logix Designer Structured Text syntax
  10. Rockwell Automation Structured Text instruction execution
  11. Rockwell Automation Logix 5000 Structured Text programming manual
  12. Rockwell Automation timer and counter instruction availability
  13. Siemens programming guideline for S7-1200/1500
  14. Siemens programming style guide for TIA Portal
  15. Beckhoff TwinCAT 3 PLC quickstart and IEC language support
  16. Beckhoff TwinCAT programming languages and editors
  17. Beckhoff state-machine, timer and trigger sample
  18. Beckhoff task configuration and watchdog settings
  19. Beckhoff ST operators and target-dependent overflow note
  20. Schneider Electric Machine Expert Structured Text code development

Limitations: the examples are vendor-neutral teaching patterns and were not compiled unchanged on every listed platform. The article does not define a safety lifecycle, certify scan time, validate physical I/O or replace the selected controller's versioned manuals. Preserve the problem statement and acceptance cases when translating; record every dialect/runtime deviation rather than silently changing the intended behavior.

Continue with the PLC programming languages guide, state-machine glossary, PLC scan-cycle guide and practical PLC examples.

#StructuredText#STProgramming#PLCProgramming#IEC61131-3#StateMachine
Share this article:

Related Articles