You can organise reusable control logic in an FC or an FB. Compare the two block types, find the built-in instructions, and follow each interface declaration through to the pin you connect when you call the block.
Use these two block types for reusable logic in TIA Portal. Both have a code section and an interface; the difference covered here is their instance memory. A Function has no instance DB of its own. A Function Block has one and remembers its instance data between calls. That storage lets each instance keep its own state while sharing the block's code.
Pass inputs to the function and receive its result, as with sqrt(x). It runs and returns its result, keeping no instance data of its own. You can call it repeatedly without creating an instance DB for each use.
Behaviour plus a private instance DB. Its Static variables survive scan-to-scan, so it can hold a timer, a counter, a step number, a whole state machine.
β instance DB keeps data between scansSame idea you'll meet again as OB / FC / FB / DB in Blocks & Reuse. This lesson examines the two reusable types you write code in.
The instruction browser also contains Siemens-supplied blocks: some built-in instructions use an FC or FB interface. A TON timer is a system FB; MOVE is a function. They sit in the Instructions task card, ready to drag in. The blocks you author live in Program blocks. You can inspect both sources in the browser below. Search by block or pin name, filter to just FBs or just FCs, and click any block to read its description and every pin it brings with it. Arrow keys walk the list.
Check two things when choosing a block: who supplied it and whether it needs instance memory. A built-in block and a block you write can each use the FC or FB model. The author and the memory model are separate choices.
Open any block and the top pane is its interface: declarations grouped into named sections. LAD, FBD and SCL use those sections to define the block's interface and the pins available at a call. Switch between FC and FB and watch which sections appear; click a section to learn exactly what it does.
The sections that distinguish these FC and FB interfaces are Static (FB only, for instance memory) and Return (FC only, for the result). The other five sections appear in both.
| Section | FC | FB | What it is for |
|---|---|---|---|
| Input | β | β | Values handed in by the caller, meant to be read, not written, inside. Pins on the left. |
| Output | β | β | Results written back out. Pins on the right. |
| InOut | β | β | Passed by reference and edited in place without a copy. Shown on both sides. |
| Static | β | β | The memory. Lives in the instance DB and survives every scan. |
| Temp | β | β | Temporary working data for the current call. Initialization depends on block access; assign the value before relying on it. |
| Constant | β | β | Named literals local to the block. Fixed at compile time. |
| Return | β | β | The Functionβs single result value, like sqrt() β Real. |
A block in this view has three main parts: a header of properties, an interface of declarations, and a code section. The editor places declarations in the top pane and logic below. For an FB instance, the generated instance DB provides storage for its data. Compare the two examples below to follow the declarations, calculation and storage.
// # = block-local tag, "β¦" = global #span := #hi - #lo; #FC_Scale := #lo + #span * INT_TO_REAL(#raw) / #RAW_MAX;
#span is temporary working data for the current call. In this example, the calculated answer leaves through Return.CASE #step OF 0: IF #open THEN #step := 10; END_IF; 10: #tmr(IN := TRUE, PT := #tOpen); IF #tmr.Q THEN #step := 20; END_IF; 20: #done := TRUE; END_CASE;
"Valve_1". #step and the whole nested #tmr are stored there, so next scan the CASE picks up exactly where it left off.βͺ Header & properties
Name, number (FC1, FB5), language (LAD / FBD / SCL / STL / GRAPH) and Optimized block access. Choose the language per block; an SCL FB can call a LAD FC.
β Interface
The seven declaration sections define the call interface. If you change a pin, update and recompile the affected callers so that their connections match it.
β‘ Code section
One or more networks in LAD/FBD, or plain statements in SCL. Local tags are written #name; global tags and block names go in "quotes".
β’ Instance DB (FB only)
Generated for you the first time you call the FB. Its layout is the interface: Input, Output, InOut and Static laid out as real bytes you can watch online.
Follow the same sequence in either example: read the interface declarations, follow the code, then check where the result is stored. The FB's instance DB also holds the values that its next call will need.
When you drop a block into your network, its Input and InOut declarations appear as pins on the left, its Output and InOut pins on the right. Data flows in β the left and β out the right. In SCL the two directions even get different operators: := feeds a value in, => pulls a result out. Compare the three calls below. Each FB call identifies its instance, while the FC call needs no instance name.
An InOut pin is special: it's passed by reference, allowing the block to read and write the supplied variable in place without a copy. This is useful when passing a large UDT or array. In the displayed box, the connection appears on both sides of the box.
Check how the block's instance, temporary data and interface behave before reusing it across the project:
π§ Single- vs multi-instance
Call an FB and you must name its instance DB. Declare that instance as a Static var inside another FB to create a nested multi-instance. One TON living inside your FB needs no separate DB; its memory rides along in your instance DB.
β FCs can have outputs too
An FC can provide more than its Return value. It can also declare Output and InOut pins for results and data passed by the caller. It still has no Static section or instance DB of its own.
β Check how temporary data is initialized
A Temp variable is working data for the current call. Initialization depends on the block access setting; do not assume every temporary variable starts at 0. Assign the value before using it. The #1 check here is whether the code writes the value before any read depends on it.
π Passing structures with InOut
Passing a large UDT or array by Input can copy the whole thing on every call. Pass it as InOut to pass it by reference and let the block edit it in place. For FBs, this also lets blocks share the same data record.
π Optimized vs standard access
With Optimized block access enabled (the S7-1200/1500 default), the compiler chooses the byte layout and you use symbolic addresses. Standard access keeps fixed offsets for legacy pointer access or absolute addressing.
β οΈ Change a pin, break the callers
The interface is a contract. Add or rename a parameter and every existing call goes red as inconsistent. An FB's instance DBs also need regenerating to match its interface. Settle the interface before writing 30 calls so that you do not have to reconnect all of them afterwards.
π·οΈ One block, many instances
The code of an FB is downloaded once, however many times you call it. The instances keep their own data. Thirty valves use thirty small DBs and one code block to maintain, so a change to the shared block applies to each valve.
You're writing a reusable valve controller that holds a TON timer and a step number, and you'll call it for 30 valves. Which block, and what does each call need?