Code inside a program organization unit (POU) - References - SIMATIC AX - Support documentation - ST Style Guide, Cheat sheet

Structured Text Style guide

Portfolio
SIMATIC AX
Product
SIMATIC AX
Software version
2510
Edition
02/2026
Language
English (original)
Package Name
@ax/st-styleguide

Rule:

Use constants for numerical values other than 0 and -1. This ensures, that the value can be changed at a central position and has a clear meaning.

Recommendation:

If possible, only use local constants inside a POU

TIP

Constants are text replacements for numerical values exchanged by the preprocessor. Using constants in the CPU neither causes a performance loss, nor does the memory consumption increase in the data memory. Only the memory consumption in the load memory of the CPU increases due to the increasing number of characters in the block sources.

//Correct --> Working with constants
IF Velocity > MAX_VELOCITY THEN
  Velocity := MAX_VELOCITY;
ELSIF Velocity < 0 THEN
  Velocity := -1.0 * MAX_VELOCITY;
ELSE
  MotorSetpointSpeed := Velocity;
END_IF;
//Wrong --> Working with numerical values
IF (Velocity > 10.0) THEN
  Velocity := 10.0;
ELSIF Velocity < 0 THEN
  Velocity := -10.0;
ELSE
  MotorSetpointSpeed := Velocity;
END_IF;

Recommendation:

Array limits start with 0 and end with a constant for the upper limit of the array (e. g. DiagBuffer[0..DIAG_BUFFER_UPPER_LIM]) or "CONSTANT – 1" (e.g. Drives[0..NUMBER_OF_DRIVES - 1]).

Rule:

A CASE instruction must always have an ELSE branch to be able to report the errors occurring during runtime.

CASE Select OF
    1: //Comment
        ; //Statement
    4: //Comment
        ; //Statement
    2..5: //Comment
        ; //Statement
ELSE
    ; //Generate error message
END_CASE;

Recommendation:

If possible, a CASE instruction shall be used instead of an IF instruction with several ELSIF branches. This makes the program clearer.

Recommendation:

Use only symbolic constants or ENUM values inside a CASE instruction.

CASE MyStepCase OF
    CONST_STEP_A:
        ;
    CONST_STEP_B:
        ;
    CONST_STEP_C:
        ;
    ELSE
        ;
END_CASE

Rule:

Organize your POUs inside namespaces.

Recommendation:

The folder structure should match your namespace structure.

Recommendation:

Use only one namespace in each file.

//Bad: Multiple namespaces in one file
NAMESPACE a
    ; //your code in namespace a
END_NAMESPACE
NAMESPACE b
    ; //your code in namespace b, same file
END_NAMESPACE

Recommendation:

Sort your USING alphabetically.

Recommendation:

Provide data as read-only if possible.

CLASS MyClass
    //Bad: Data can be written from outside without notice
    VAR_PUBLIC
        MyPublicValue : INT;
    END_VAR

    //Good: Keep data private and provide a public method for read-only access
    VAR_PRIVATE
        MyPublicReadOnlyValue : INT;
    END_VAR
    METHOD PUBLIC GetMyReadOnlyValue : INT;
        GetMyPublicReadOnlyValue := MyPublicReadOnlyValue;
    END_METHOD
END_CLASS

Rule:

If POUs provide error codes, then these must always be evaluated.

Rule:

If only one output parameter is used in a function, the return value is used instead of VAR_OUTPUT.

//Correct: Using return value
FUNCTION MyFunc : INT
    ; //functionality
END_FUNCTION

//Wrong: Using VAR_OUTPUT section
FUNCTION MyFunc
    VAR_OUTPUT
        ReturnValue : INT;
    END_VAR
    ; //functionality
END_FUNCTION

Recommendation:

The name of a method should explain the type of actions inside a class. For this, a keyword does help significantly.

Access Example keywords
Write Set, Write, Modify
Read-only Read, Get, Is, Has, Can
//A method that returns a value. It is recommend to use the return value
METHOD PUBLIC GetFillLevel : REAL
    GetFillLevel := FillLevelSensorValue * SCALE_FACTOR;
END_METHOD

//A method that sets an internal parameter in a class. Here you can check if the input value is valid,
//then return some information if the value has been set successfully
METHOD PUBLIC SetTimeout : BOOL
    VAR_INPUT
        value : TIME;
    END_VAR
    IF value > T#0s THEN
        InternalTimeout := value;
        SetTimeout := TRUE;
    END_IF;
END_METHOD

Rule:

Keep your POUs (functions, function blocks, methods) short, split them into independent units if necessary. This avoids complicated tests.