Programming Siemens S7-1200: LAD, FBD, SCL, and C Conversion

David Krause16 min read
SiemensTIA PortalTutorial / How-to
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

S7-1200 Programming Languages: What STEP 7 Officially Supports

The SIMATIC S7-1200 compact controller is programmed exclusively through the Totally Integrated Automation (TIA) Portal. According to the official SIMATIC S7-1200 manual collection (entry ID 109759862) on Siemens Industry Online Support, STEP 7 provides a defined set of standard programming languages for the S7-1200, with LAD (Ladder Logic) defined as a graphical programming language. The same manual collection is mirrored on the TIA Siemens Cloud documentation portal.

The standard language set engineers can deploy on an S7-1200 today includes:

Language Type Notation Typical Use Case
LAD (Ladder Logic) Graphical Contacts / coils Boolean logic, interlocks, motor start/stop
FBD (Function Block Diagram) Graphical Function boxes with EN/ENO Arithmetic, signal processing
SCL (Structured Control Language) Textual, high-level Pascal-like syntax Data handling, loops, math, string operations
STL (Statement List) Textual, low-level Mnemonic Bit-level manipulation (STEP 7 Professional only, FW 4.2+)

GRAPH (sequential function chart) targets the S7-1500 family by default; it is not the recommended path on the S7-1200. C is not part of this language set. There is no C compiler, no C runtime, and no native C execution environment shipped on any S7-1200 CPU firmware image.

Engineers familiar with TIA Portal's full language set must also confirm the installed STEP 7 edition. STEP 7 Basic supports LAD and FBD only. STEP 7 Professional is required for SCL, STL, and any non-LAD language beyond basic FBD.

Why Direct C Execution Is Not Available on the S7-1200

The S7-1200 executes a compiled, cyclic, IEC 61131-3 firmware image. The CPU boots into a Siemens-proprietary runtime that interprets or executes pre-compiled STEP 7 blocks (OB, FB, FC, DB). The firmware is closed; the controller has no loader that would accept an arbitrary ELF, COFF, or PE object produced by gcc, clang, or IAR. There is no JTAG, no bootloader entry, and no engineering pathway to substitute user-supplied machine code.

Three architectural constraints make native C execution infeasible on the S7-1200:

  1. No memory model for a C heap. The work memory is partitioned into code, data, and retentive areas with fixed boundaries enforced at download time. There is no malloc/free subsystem exposed to user code.
  2. No standard C library linkage. libc, libm, and POSIX headers are not present. printf() must be replaced with Siemens-supplied system functions, HMI blocks, or serial-write blocks.
  3. No deterministic interrupt model for arbitrary C handlers. The S7-1200 OB priority model (OB1 cyclic, OB35 cyclic interrupt, OB82 diagnostic, OB121 programming error) is the only legal entry point for user code.
If you require deterministic C execution on Siemens hardware, the S7-1200 controller line is the wrong target. Use a PC-based controller instead (see WinAC RTX section below) or migrate logic into SCL.

SCL: The Closest High-Level Alternative to C

SCL (Structured Control Language) is the textual, Pascal-like language that ships with STEP 7 Professional and is the closest analog to C on the S7-1200. The syntax differs in three important ways C developers should understand:

Concept C SCL
Block delimiter { } curly braces BEGIN ... END_FUNCTION or END_IF
Assignment = := (Pascal assignment operator)
Equality test == =
Variable declaration type name = value; name : type := value;
Function block struct + function pointers FB with VAR_INPUT / VAR_OUTPUT / STAT
Loop constructs while / for / do-while WHILE / FOR / REPEAT ... UNTIL
Conditional if (cond) {} else {} IF cond THEN ... ELSIF ... ELSE ... END_IF;
CASE / switch switch/case/default CASE ... OF ... ELSE ... END_CASE;
Comment // or /* */ // single line only

A complete SCL function block that emulates a typical C state machine ported to ladder-style sequencing:

FUNCTION_BLOCK "FB_StateMachine"
VAR
    iState  : INT  := 0;
    iDelay  : INT;
END_VAR
BEGIN
    CASE iState OF
        0:  // Idle
            IF "iStartCmd" = TRUE THEN
                iState := 1;
                iDelay := 0;
            END_IF;
        1:  // Ramp up
            "qMotorSpeed" := "qMotorSpeed" + 10;
            iDelay := iDelay + 1;
            IF iDelay >= 50 THEN
                iState := 2;
            END_IF;
        2:  // Run
            IF "iStopCmd" = TRUE THEN
                iState := 3;
            END_IF;
        3:  // Ramp down
            "qMotorSpeed" := "qMotorSpeed" - 10;
            IF "qMotorSpeed" <= 0 THEN
                "qMotorSpeed" := 0;
                iState := 0;
            END_IF;
    ELSE
        iState := 0;
    END_CASE;
END_FUNCTION_BLOCK

Compile-time errors that SCL catches which pure LAD hides include type mismatches at I/O boundaries, uninitialized variable access, and array bound violations. This is the engineering reason to prefer SCL over LAD for any non-trivial data handling.

WinAC RTX: When You Need Real C Execution

For applications where genuine C execution is non-negotiable, Siemens offers the SIMATIC WinAC RTX product line. WinAC RTX is a software PLC that runs on a Windows PC (typically an industrial PC such as the SIMATIC IPC family) and combines the WinAC RTX real-time extension with the ability to load and execute C/C++ code via the SIMATIC ODK (Open Development Kit) interface.

Windows Industrial PC WinAC RTX Software PLC (STEP 7 / TIA Portal runtime) SIMATIC ODK C/C++ DLL (loaded as runtime extension) SIMATIC S7-1200 TIA Portal LAD/FBD/SCL (no native C path) PROFINET I/O Devices (S7-1200 retains I/O role) PROFINET

Key engineering constraints when sizing a WinAC RTX solution:

  • Hardware: SIMATIC IPC227G, IPC427G, IPC627, or equivalent industrial PC with deterministic Ethernet.
  • RTX layer: IntervalZero RTX extension handles the hard real-time partition; Windows handles HMI, logging, OPC UA.
  • ODK version: SIMATIC ODK supports C/C++ function calls from STEP 7 blocks; the DLL must be signed and loaded by the WinAC RTX service.
  • Latency budget: Typical PROFINET IRT cycle on a WinAC RTX system is 1 ms; the C DLL executes in a deterministic slot within the same cycle.
WinAC RTX requires STEP 7 Professional, an industrial PC license, and a separately licensed ODK developer kit. It is not a free path and is typically deployed for high-speed motion, vision, or advanced algorithms where the S7-1200 CPU is intentionally too slow.

C-to-LAD Conversion Tools: What Exists vs. What Does Not

The premise of automated C-to-LAD translation has been investigated by both Siemens and third parties, but no production-grade converter exists for the S7-1200 as of TIA Portal V19. The reasons are fundamental:

  1. Semantic gap: C permits pointer arithmetic, recursion, dynamic memory, and goto. LAD has no representation for any of these. Every C construct must be re-expressed as a state machine or call-tree, which is itself a manual engineering task.
  2. Type system gap: C's signed/unsigned, float/double, struct/union map poorly to the S7-1200's IEC 61131-3 type system (BOOL, INT, DINT, REAL, STRING, ARRAY, STRUCT).
  3. Library gap: printf, malloc, file I/O have no direct IEC equivalent; manual block libraries must be created.
  4. Verification gap: A translated LAD program would inherit the bugs of the C source. The compiler/translator cannot prove equivalence of two different language semantics.

Academic converters and IEC 61131-3 code-generation frameworks (such as those built around Eclipse 4DIAC) target FBD/ST export from IEC 61131-3 but do not advertise reliable C-to-LAD translation for the S7-1200 platform. Siemens does not provide a C-to-LAD converter in any current TIA Portal release.

Migration Strategy: From C Source to S7-1200 Logic

The recommended engineering workflow when porting C code to the S7-1200 is structured in five phases:

  1. Decompose the C application into a function call tree. List every C function, its inputs, outputs, side effects, and call frequency.
  2. Classify each function as one of: pure boolean (map to LAD), arithmetic / data handling (map to SCL), state machine (split into OB1 logic + FB instances), time-critical closed loop (consider S7-1500 or WinAC RTX).
  3. Define a tag dictionary that mirrors the C global variables and structs. Each C struct becomes an S7-1200 DB (data block) of type STRUCT; each scalar becomes a tag in the default tag table or a DB.
  4. Translate each C function block-by-block. Boolean-heavy functions become LAD networks; arithmetic becomes SCL functions; reuse becomes FBs with instance DBs.
  5. Commission and verify. Mirror the C unit tests as PLC watch tables and force tables. Trigger each input combination and confirm output parity with the C reference build.

LAD Programming Quick Reference for C Developers

LAD is read left-to-right, top-to-bottom, with power flow representing logical TRUE. The basic primitives map to C control flow as follows:

LAD Element C Equivalent Notes
NO contact (—| |—) if (var == TRUE) Passes power if the tag is TRUE
NC contact (—|/|—) if (var == FALSE) Passes power if the tag is FALSE
Coil (—( )—) out = TRUE; Sets the tag to TRUE while energized
Negated coil (—(/)—) out = FALSE; Sets the tag to FALSE while energized
Set coil (—(S)—) out = TRUE; (latched) Set/Reset pair forms an SR flip-flop
Reset coil (—(R)—) out = FALSE; (latched) Reset dominates Set
TON timer delay(T, t) On-delay, PT in ms
TOF timer off-delay Off-delay, PT in ms
CTU counter ++counter; if >= PV... Up counter
CTD counter --counter; if <= 0... Down counter

A typical motor start/stop rung with overload protection in LAD notation:

Network 1: Motor seal-in
    [ StopPB_NC ] [ Overload_OK ] [ SealIn_NO ] ----( Motor_Run )----[/Fault_Latch/]
Network 2: Fault latch (set/reset flip-flop)
    [ Overload_Trip ] ------------------------------( S Fault_Latch )--
    [ Fault_Ack ] ---------------------------------( R Fault_Latch )--

SCL Programming Quick Reference for C Developers

The most common SCL block types engineers porting from C will create are:

  • FB (Function Block) - C struct with attached methods; instances are reusable via instance DBs.
  • FC (Function) - C pure function; multiple return values via VAR_OUTPUT.
  • OB (Organization Block) - C main(); cyclic OB1 is the default entry point.
  • DB (Data Block) - C global or struct; instance DBs are auto-created per FB instance.

Sample SCL function that ports a typical C clamping macro:

FUNCTION "FC_Clamp" : INT
VAR_INPUT
    iValue : INT;
    iMin   : INT;
    iMax   : INT;
END_VAR
VAR_TEMP
    iResult : INT;
END_VAR
BEGIN
    IF iValue < iMin THEN
        iResult := iMin;
    ELSIF iValue > iMax THEN
        iResult := iMax;
    ELSE
        iResult := iValue;
    END_IF;
    "FC_Clamp" := iResult;
END_FUNCTION

Called from LAD as a box: EN input wired, ENO passed through, iValue/iMin/iMax wired from tag names. SCL supports RETURN for early exit, similar to a C return statement.

Data Type Mapping: C Types to S7-1200 Types

The type-system translation between C and the S7-1200 IEC 61131-3 type set is a frequent source of porting bugs. Use this table as the canonical mapping:

C Type S7-1200 Type Size (bytes) Notes
bool / _Bool BOOL 1 Single bit when in optimized block; byte in non-optimized
char (signed/unsigned) CHAR / BYTE 1 BYTE = unsigned 0..255; CHAR = ASCII printable
unsigned char BYTE 1 Use WORD for 16-bit unsigned
short INT 2 Signed -32768..32767
unsigned short WORD 2 Bit-level operations: AND, OR, XOR
int (typically 32-bit) DINT 4 Signed -2^31..2^31-1
unsigned int DWORD 4 0..2^32-1
long long LINT 8 Signed 64-bit
float REAL 4 IEEE 754 single precision
double LREAL 8 IEEE 754 double precision
char[N] STRING[N+2] N+2 Each STRING has 2-byte header
struct STRUCT in DB Sum of members STRICT alignment; no padding
enum INT + named constants 2 or 4 No native enum; use named integer constants
union Not supported n/a Use separate DBs or bit-level access via AT overlay

The AT overlay construct is the S7-1200 mechanism for viewing the same memory region as different types, similar in spirit to a C union. Example: declaring a DWORD and overlaying four BOOLs to access individual bits.

TIA Portal Version and Firmware Requirements

The S7-1200 firmware family evolved significantly across TIA Portal versions. The mapping below covers the production-relevant combinations:

TIA Portal Version S7-1200 FW Range STEP 7 Edition Required
V13 / V13 SP1 FW 4.0 - 4.1 STEP 7 Basic V13
V14 / V14 SP1 FW 4.2 STEP 7 Basic V14 or Professional V14
V15 / V15.1 FW 4.3 - 4.4 STEP 7 Basic V15 or Professional V15
V16 FW 4.5 STEP 7 Basic V16 or Professional V16
V17 FW 4.6 STEP 7 Basic V17 or Professional V17
V18 FW 4.7 STEP 7 Basic V18 or Professional V18
V19 FW 4.7 (latest) STEP 7 Basic V19 or Professional V19

For SCL on the S7-1200, the minimum combination is TIA Portal V14 SP1 with FW 4.2 on the CPU. Earlier combinations allow LAD/FBD only. STL support requires STEP 7 Professional and FW 4.2 or higher.

Performance and Memory Constraints When Porting from C

The S7-1200 CPU family has fixed memory budgets. Engineers porting C code must respect these limits or the download fails:

CPU Work Memory (Code) Work Memory (Data) Retentive Memory Bit Memory
CPU 1211C 30 KB 50 KB 10 KB 4096 bytes
CPU 1212C 50 KB 75 KB 10 KB 4096 bytes
CPU 1214C 100 KB 150 KB 10 KB 8192 bytes
CPU 1215C 150 KB 250 KB 10 KB 8192 bytes
CPU 1217C 250 KB 400 KB 10 KB 8192 bytes

C porting caveats driven by these limits:

  • String handling: C char[] maps to S7-1200 STRING type. Each STRING consumes (max_len + 2) bytes. Concatenation in SCL is more expensive than C strcat(); pre-allocate.
  • Recursive functions: Not supported. Convert to iterative form using WHILE/FOR.
  • Pointer arithmetic: Replace with indexed ARRAY access; out-of-bounds triggers OB121 and CPU stop if not caught.
  • Floating point: REAL is 32-bit IEEE 754 single precision, matching C float. LREAL is 64-bit double. Mixing requires explicit ROUND/TRUNC.
  • 64-bit integers: Use DINT (32-bit) or LINT (64-bit signed) explicitly; do not assume int == 32 bits as in C.
  • Stack depth: OB1 + nested FB calls must fit in the cyclic time budget. Default OB1 cycle on a CPU 1214C is 1-10 ms; long call chains exceed this and trigger OB80 time error.

OB Execution Model vs. C main() / Interrupt Service Routines

C engineers porting to the S7-1200 must internalize the Organization Block (OB) execution model, which replaces both the C main() function and the interrupt service routine (ISR) concept:

S7-1200 OB Priority C Analog Use
OB1 (Main cyclic) 1 while(1) main loop All cyclic user logic
OB10 (Time-of-day) 2 RTC alarm ISR Scheduled daily/weekly triggers
OB35 (Cyclic interrupt) 12 Timer ISR Deterministic 1-1000 ms period tasks
OB40 (Hardware interrupt) 16 Edge-triggered ISR Fast reaction to digital input edges
OB82 (Diagnostic interrupt) 26 Error ISR I/O module fault detection
OB121 (Programming error) Same as OB1 SIGFPE/SIGSEGV handler Recover from bad index access

The key behavioral difference: when OB35 fires, OB1 is interrupted. State held in instance DBs remains consistent because the S7-1200 runtime serializes access. Do not assume atomic multi-variable updates across OBs without explicit synchronization patterns.

Libraries: Reusable Code Containers

C developers commonly organize reusable code into static or shared libraries. The S7-1200 equivalent is the TIA Portal Library:

  • Type DB (UDT) - C typedef equivalent. Define once, reuse as a template for instance DBs.
  • FB with multi-instance capability - C class with member functions; instance DBs are the C objects.
  • Global Library (.al14 file) - Shared archive between projects. Reusable across stations.
  • Project Library - In-project reusable components, automatically versioned.

Master copies in a global library behave like static libraries; changes propagate to all consumers and may require recompilation of dependent blocks. Type changes in UDTs cascade through every instance DB in the project.

Commissioning and Verification Procedure

After translating the C source, follow this verification procedure to catch porting defects before deployment:

  1. Compile the project in TIA Portal (Project > Compile > All). Resolve all warnings before continuing.
  2. Download to the target CPU 1211C/1212C/1214C/1215C/1217C and switch to RUN mode.
  3. Open a watch table covering all I/O and intermediate tags from the migrated code.
  4. Run the original C build on a PC with a test harness that emits the same input stimulus sequence.
  5. Force inputs and capture outputs in the watch table; compare against the C reference output on a per-cycle basis.
  6. Use trace functionality (CPU 1214C FW 4.2+ and higher) to record cyclic values at sub-millisecond resolution.
  7. Stress-test edge cases: overflow, empty arrays, divide-by-zero, simultaneous interrupts from OB35 and OB40.

Troubleshooting Matrix

Symptom Likely Cause Diagnostic Fix
Download rejected: "Not enough memory" C port produced oversized blocks TIA Portal > Project tree > Program blocks > right-click > Resources Split into smaller FBs, enable block optimization, upgrade CPU
SCL compiler error: "Identifier already declared" Variable name collision across DBs Cross-reference tool (Ctrl+Shift+F) Rename to fully qualified tag-qualified form
OB121 programming error during scan Array index out of bounds Online > Diagnostics > Buffer Add limit check before index access
STL editor unavailable in TIA Portal STEP 7 Basic only; STL requires Professional Help > About > Installed products Upgrade license to STEP 7 Professional
SCL block download fails on CPU 1211C/1212C SCL not enabled or insufficient work memory CPU properties > Programming > SCL support Enable SCL or use CPU 1214C or higher
C-like ternary operator (cond ? a : b) unavailable SCL has no ternary; only IF/ELSIF Source review Refactor to IF ... THEN ... ELSE ... END_IF;
Watch table value does not update Tag in optimized DB; absolute addressing disabled DB properties > Attributes > Optimized block access Disable optimization or use symbolic name in watch table
Timer/dialog FB counts twice per cycle FB called from OB1 and from interrupt OB Cross-reference call hierarchy Move logic to single OB or use instance DB partitioning
REAL value differs from C float output Implicit DINT-to-REAL conversion dropped precision Watch table on both representations Use explicit REAL casts in SCL
STRING concatenation exceeds max length C strcat unbounded; SCL STRING is fixed Diagnostic buffer OB121 Pre-allocate STRING with sufficient length; truncate manually

FAQ

Can I program the Siemens S7-1200 directly in C?

No. The S7-1200 firmware executes STEP 7 blocks (LAD, FBD, SCL, STL) only. There is no C compiler, no C runtime, and no loader for C object files on any S7-1200 CPU. To execute native C code on Siemens hardware, use a SIMATIC WinAC RTX software PLC on an industrial PC with the SIMATIC ODK.

Is there an automatic C-to-LAD converter for the S7-1200?

No production-grade converter exists. The semantic gap between C (pointers, recursion, dynamic memory) and LAD (graphical, no recursion, fixed memory) makes reliable automated translation infeasible. Engineers porting C must manually re-express logic in LAD, FBD, or SCL within TIA Portal.

What is the closest Siemens high-level language to C on the S7-1200?

SCL (Structured Control Language) is the closest. It uses Pascal-style syntax with := for assignment, BEGIN/END block delimiters, and supports IF, CASE, WHILE, FOR, and REPEAT. SCL requires STEP 7 Professional and a CPU with firmware V4.2 or higher (such as CPU 1214C, 1215C, or 1217C).

Which TIA Portal version do I need to program an S7-1200?

STEP 7 Basic V13 or higher is required for any S7-1200 programming. For SCL and advanced language features, use STEP 7 Professional V14 SP1 or higher paired with CPU firmware V4.2 or higher. Always match the TIA Portal version to the installed CPU firmware before downloading to avoid incompatibility errors.

How do I port an existing C application to the S7-1200?

Decompose the C program into a function tree, classify each function (boolean into LAD, arithmetic into SCL, state machine into FB), build a tag dictionary that mirrors C globals/structs as DBs, translate block-by-block, then commission using watch tables and force tables to verify parity with the C reference build on a per-input basis.

Back to blog