Overview: The Siemens S7 Block Model
Every Siemens S7-1200 and S7-1500 user program is built from four block types defined by the IEC 61131-3 standard: Organization Blocks (OB), Functions (FC), Function Blocks (FB), and Data Blocks (DB). Choosing the correct block type is not a stylistic preference; it determines whether the block carries persistent state, how parameters are passed, how the block is called, and how it behaves under program fault conditions. A wrong choice typically surfaces during commissioning as lost retentive data, duplicate tags, FBs that cannot be called multiple times, or "Instance DB required" compile errors.
Siemens publishes a dedicated S7-1200/S7-1500 Style Guide for PLC Programming as a primary reference. TIA Portal's block editors in V15.1 and later (current at the time of writing: V18/V19) and STEP 7 Professional use the same block model, so the rules below apply to both controller families unless explicitly noted.
Block Type Summary
| Block | Carries State | Own Data | Typical Use | Called By |
|---|---|---|---|---|
| OB - Organization Block | No | Temp data only | System interface, cyclic, interrupt, startup, error handling | Operating system |
| FC - Function | No (stateless) | Temp data only | Reusable math, conversion, multiplexing logic | OB, FC, FB |
| FB - Function Block | Yes (in instance DB) | Stored in instance DB | Devices, motors, valves, PID, any stateful object | OB, FC, FB |
| DB - Data Block | Yes | Yes | Global variables, instance memory, recipes, configuration | Read/write from any block |
Organization Blocks (OB): The System Interface
OBs are the only blocks the S7 CPU operating system calls directly. Each OB has a fixed priority class, a fixed triggering event, and a fixed set of local TEMP variables. Logic placed inside an OB executes once per trigger. OBs cannot be called from other code blocks; only the OS can start them.
OB Categories on S7-1200/1500
| OB Number | Name | Trigger | Typical Use |
|---|---|---|---|
| OB 1 | Main (cyclic) | End of previous cycle | Main scan, scans cyclically until PLC stop |
| OB 10..17 | Time-of-day | Configured date/time | Scheduled tasks, time-based batch steps |
| OB 20..23 | Time-delay | Delay expires | Delayed actuator command |
| OB 30..38 | Cyclic interrupt | Fixed period (e.g. 1 ms, 10 ms, 100 ms) | Closed-loop control, deterministic sampling |
| OB 40..47 | Hardware interrupt | Process or I/O event | Fast response to digital input rising edge |
| OB 55..58 | Status / diagnostic | DP/PROFINET diagnostic event | Fault-tolerant I/O handling |
| OB 80..87 | Time / I/O / CPU fault | Various fault conditions | Diagnostic reactions, fault OB |
| OB 100 | Warm restart | CPU goes RUN | Initialize non-retentive tags |
| OB 101 | Hot restart | Power restore (S7-1500) | Recover process state |
| OB 102 | Cold restart | Power-up, memory reset | Full initialization |
| OB 121 | Programming error | Block execution error | Local fault containment in block |
| OB 123 | I/O access error | Faulted I/O read/write | Substitute values for faulty I/O |
On S7-300/400 the cyclic scan was effectively limited to OB 1, which forced all logic into a single block. S7-1200 and S7-1500 remove that restriction: you can split the program across several OBs (e.g. a 10 ms cyclic OB for PID, a 100 ms cyclic OB for HMI update, OB 1 for sequencing) without having to nest everything in OB 1.
OB Local Variables
Each OB has a fixed interface table. For OB 1, the most-used locals are:
-
OB1_EV_CLASS- event class (B#16#11 = standard cyclic) -
OB1_PRIORITY- priority class (1 for OB 1) -
OB1_PREV_CYCLE- previous cycle time in ms -
OB1_MIN_CYCLE- minimum cycle time since start -
OB1_MAX_CYCLE- maximum cycle time since start
Use OB1_PREV_CYCLE for cycle-time monitoring and alarm generation. On S7-1500 the same information is exposed as system tags in the Diagnostics folder.
Functions (FC): Stateless Code Blocks
An FC is a subroutine that has no memory of its own. It holds its inputs, outputs, in-out tags, and a small TEMP area only while it is executing. When the FC exits, the TEMP data is gone. Inputs and outputs are passed by value (a copy is made at call time) - this is the default and it is also the source of the most common FC mistake.
Use an FC when:
- The logic is purely functional: input values produce output values with no internal state.
- Examples:
FC_LinearScale(),FC_Mux4to1(),FC_ASCIItoInt(),FC_ComputeChecksum(). - The block will be called from many places and you do not need per-call memory.
Do not put timers, edge flags, or step machine state in an FC. Without an instance DB, the FC cannot retain that data between scans, and a value that works in one scan will be lost the next.
FC Parameter Passing
| Section | Direction | Retained? | Notes |
|---|---|---|---|
| Input (IN) | Caller -> FC | No (copy) | Caller passes a value; FC can read it. |
| Output (OUT) | FC -> caller | No (copy) | FC writes a value; caller reads it after return. |
| InOut (IN_OUT) | Caller <-> FC | By reference (pointer) | Same memory cell is used in both blocks. |
| Temp (TEMP) | Local | No | Available only during the call. |
| Constant (CONSTANT) | Read-only | No | Hard-coded inside the block. |
| Return (RET_VAL) | FC -> caller | No | Function return value, typically a status code. |
Function Blocks (FB): Stateful Code Blocks
An FB is a code block that owns its instance DB. The instance DB holds all the FB's STAT (static) variables, so memory persists between scans. This is how Siemens implements a class-instance model: the FB is the type, the instance DB is the object.
Use an FB when the logic represents a real device or a stateful object:
- Motor, valve, cylinder, conveyor, drive, PID loop, recipe, alarm handler, modbus slave, HMI screen controller, sequential function chart, state machine.
Each call to the FB can be passed a different instance DB; the FB code is identical, but the state is separate. This is the primary reason the FB/DB pair is preferred over FC for any non-trivial automation code.
FB Parameter Passing
| Section | Direction | Persisted in Instance DB? |
|---|---|---|
| Input (IN) | Caller -> FB | Initial value stored; current value in caller |
| Output (OUT) | FB -> caller | Yes (last value retained between calls) |
| InOut (IN_OUT) | Caller <-> FB | No - tag itself holds the value (by reference) |
| Static (STAT) | Internal | Yes - this is the FB's own memory |
| Temp (TEMP) | Local | No |
The key difference vs. an FC: STAT variables. The instance DB is the FB's persistent memory. Timers instantiated inside the FB persist as part of that DB. Edge-flag bits, last-step numbers, runtime counters, and last-error codes are all STAT data and that is why an FB is the right block type to contain them.
Multi-Instance FBs
When one FB contains another FB call, the contained FB can share the parent's instance DB. This is called a multi-instance. It removes the proliferation of tiny DBs and keeps the call hierarchy clean. To enable, in the contained FB's call interface, set the instance selection to Multi-instance; the parent FB's instance DB will then hold both objects' static data.
Data Blocks (DB): The Three Subtypes
The DB is the storage block. It contains only data, no executable code (in user DBs). There are three kinds of DB on S7-1200/1500:
| Type | Created By | Used For |
|---|---|---|
| Global DB | User | Shared process tags, recipes, parameters; addressable from any block |
| Instance DB | Auto-generated when an FB is called | Persists STAT variables of the associated FB |
| System DB (SDB) | CPU at compile time | Hardware configuration, I/O, connections, diagnostic data; not user-editable |
Global DB Design Notes
- Group tags by function or by device rather than by data type.
- Use derived
PLC data types (UDTs)for any structure used in more than one place (e.g.UDT_MotorAxis,UDT_RecipeRow). - For retentive data, enable Setpoints under DB properties; in the S7-1500, use the Retain attribute on individual tags.
- Watch the size: large arrays of
REALin global DBs consume load memory. A 1000-elementREALarray is 4 KB in the S7-1500.
Optimized vs Non-Optimized Block Access (S7-1500)
On S7-1500 (default) and S7-1200 (V4.0 and later), every new block is optimized: the compiler assigns symbolic addresses, and tags are stored in a non-contiguous, symbolic layout that the firmware resolves by name. Legacy non-optimized (absolute) blocks store tags in fixed byte offsets that match the old S7-300/400 address model.
| Property | Optimized | Non-Optimized |
|---|---|---|
| Address assignment | Symbolic, compiler-managed | Fixed offset (e.g. DB5.DBX0.0) |
| Performance | Faster (no symbolic resolution at runtime) | Slower (pointer-based) |
| Know-how protection | Strong (only interface visible) | Weaker (offset hints leak structure) |
| Indirect addressing | Slice, AT, PEEK/POKE variants | Legacy POKE_BLK, POKE pointer |
| Compatibility | S7-1200 V4+ / S7-1500 only | Required when integrating legacy S7-300/400 blocks |
Block Selection Decision Matrix
| Situation | Choose | Why |
|---|---|---|
| Sequential scan of the machine | OB 1 | Cyclic main entry |
| High-rate control loop (1-10 ms) | Cyclic interrupt OB (OB 30-38) | Deterministic period independent of OB 1 |
| Pure conversion/scaling, no memory | FC | No state to persist |
| Real-world device with parameters and history | FB + instance DB | Persistent STAT data, multiple instances |
| Shared process tags | Global DB | Centralized, retentive if needed |
| Hardware fault reaction | OB 80-87 (error OB) | OS-driven fault handling |
| I/O substitution value | OB 123 (or OB 121) | Local fault containment |
| Startup initialization | OB 100/101/102 | Runs once on transition to RUN |
Programming Conventions and the Siemens Style Guide
The Siemens S7-1200/S7-1500 Style and Programming Guidelines document recommends:
- One FB per real-world device or per logical subsystem (e.g.
FB_Motor_3,FB_Heater_Bank2). - Use FCs for mathematical or conversion functions and library code that has no state.
- Place FB interface tags first, in/out tags second, static data last - this makes scan and review easier.
- Use parameter instances of standard timers/counters (TP, TON, TOF, CTU, CTD) as STAT inside FBs, not as global tags.
- Use UDT (user-defined data types) to group tags that travel together; declare input/output sections using UDTs when the structure is reused.
- Enable know-how protection with a password on finished library blocks; never on blocks that are still in development.
- Version library blocks in the TIA Portal project library; do not hand-edit blocks in deployed programs.
Calling Blocks: Cross-Block Mechanics
A call to an FC copies the parameters in at the start of the call and copies outputs back at the end. A call to an FB uses the instance DB as the working area. Calling an FB without an instance DB - or with the wrong one - is a compile error. TIA Portal will refuse to compile an FB call whose instance DB was deleted or renamed.
Calls in SCL/ST are direct:
// Calling a function
retVal := FC_LinearScale(IN := aiRaw, HI_LIM := 100.0, LO_LIM := 0.0, BIPOLAR := FALSE);
// Calling a function block with an instance DB
iDB_Motor_3(IN := iStart_3, OUT_STATUS => qStatus_3);
// Calling a multi-instance FB
iMotorLocal(IN := iStart, OUT_STATUS => qStatus);
Calls in LAD/FBD are inserted from the right-side toolbox as Call boxes; the instance DB dropdown is mandatory for FBs.
Common Pitfalls and Diagnostics
| Symptom | Typical Cause | Fix |
|---|---|---|
| "Instance DB required" compile error | FB call without selecting an instance DB | Pick or create the instance DB in the call properties |
| Timers reset every scan | Timer (TP/TON) used inside an FC | Move the block to an FB and declare the timer as STAT |
| Output from an FC reverts to old value mid-scan | Parameter declared as Output (copy) instead of InOut (reference) | Switch to InOut, or move the logic to an FB |
| Multiple device instances interfere with each other | Shared global tags used as the only memory for a class of device | Convert each device to an FB with its own instance DB |
| Retentive data lost after power cycle | DB or FB static tags not flagged as retentive | Set the Retain attribute on the tag, or mark the entire DB as retentive in the S7-1200 |
| Know-how protected block rejects modification | Password-protected block with no source | Maintain a project library copy; recompile from a master project |
| OB 1 cycle time alarm (OB 80) | OB 1 cycle exceeds configured maximum | Move time-critical logic to a faster cyclic interrupt OB, or raise the max cycle limit |
| Programming-error OB 121 not running | OB 121 not present in the program | Add OB 121 to contain the fault; otherwise the CPU goes STOP on the error |
Block Libraries, Versioning, and Reuse
Both the S7-1200/1500 program blocks and the user-defined types (UDTs) belong in the project library. A library type is a master copy in the Master copies folder; a library instance is a reference used in the project. Updates to the master copy can be propagated to all instances via the Update instances command. This is the equivalent of centralized code reuse in mainstream languages and the recommended way to maintain shared FB libraries across multiple PLCs.
For cross-CPU libraries, ensure that the library FB compiles on every target firmware. S7-1500 firmware V2.0 introduced the optimized-block access model; FBs compiled for V2.0 may not load on V1.8 controllers. Always check the Compatibility list in the library's properties before release.
Verification: Confirming a Healthy Block Architecture
After any program change, perform these checks before download:
- In the project tree, every FB call has an instance DB. TIA Portal reports orphan FBs in the Compile output.
- No global tags duplicate FB STAT content. Search the symbol table for tag names that exist in both a global DB and an instance DB.
- No timer or counter is used inside an FC. Use Cross-reference on TP/TON/TOF/CTU/CTD to find FC-resident instances.
- All error OBs (OB 80-87, OB 121, OB 123) that the program depends on are present. The PLC > Diagnostics > Module information lists missing OBs.
- OB 1 cycle time and cyclic interrupt OB cycle times are below 80% of their configured maximum. Read
OB1_PREV_CYCLEand the cyclic OB's cycle time tag under Diagnostics > Cycle time. - Library blocks are at the same version in the project and in the PLC. Compare the version stamp under Block properties > Information.
FAQ
What is the difference between an FC and an FB in S7-1200/1500?
An FC is a stateless subroutine: it has no persistent memory, its parameters are passed by value, and any TEMP data is lost when the FC exits. An FB is stateful: it is always paired with an instance DB that stores its STAT variables between scans, and its IN_OUT parameters are passed by reference. Use FBs for any block that represents a real device or holds timers, counters, or state.
When should I use a Function (FC) versus a Function Block (FB)?
Use an FC for pure functions with no internal state, such as scaling, conversion, math, or multiplexing. Use an FB when the block needs to remember data between calls, when the same logic must be reused for several independent devices (each with its own instance DB), or when the block contains timers, counters, or edge flags. The Siemens S7-1200/S7-1500 Style Guide recommends one FB per real-world device.
What is the role of an Organization Block (OB) in a Siemens PLC?
OBs are the interface between the CPU operating system and the user program. The OS calls OBs in response to events: cyclic scan (OB 1), time-of-day (OB 10-17), time-delay (OB 20-23), cyclic interrupt (OB 30-38), hardware interrupt (OB 40-47), diagnostic events (OB 55-58), faults (OB 80-87), startup (OB 100-102), and programming/I/O errors (OB 121/123). User code cannot call OBs directly; only the OS starts them.
What is the difference between a global DB and an instance DB?
A global DB holds shared tags that any block can read or write (process data, recipes, parameters). An instance DB is generated automatically when an FB is called, and it holds the FB's STAT (static) variables for that one call. Each call to the same FB can use a different instance DB, giving each call its own private memory while sharing the same code.
Why do my timer values reset every scan when I use an FC?
Timers, edge flags, and step-machine state need to persist between scans. An FC has no instance DB, so any TEMP data is cleared at block exit. Move the timer and the surrounding logic into an FB, declare the timer (TP, TON, TOF) and any latching flags as STAT, and pass a per-device instance DB on each call. The timer will then keep its state between scans.
Does block optimization matter on S7-1500, and when should I disable it?
Optimized blocks (the default in S7-1500 and S7-1200 V4.0+) give faster execution, stronger know-how protection, and symbolic-only access. Disable optimization only when you must integrate legacy S7-300/400 code that uses absolute addressing, when the block is exposed over a PN/PN coupler, or when a third-party GSD expects a fixed address layout. TIA Portal flags required non-optimized access in Properties > Attributes.