S7-1200 PUT/GET Communication Setup for Shared Counter Totals

David Krause11 min read
S7-1200SiemensTutorial / 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

Overview

S7 communication between two SIMATIC S7-1200 CPUs (for example, CPU 1214C / DC/DC/DC or CPU 1214C / DC/DC/Rly) using the PUT and GET instructions is the fastest way to share process data without adding third-party hardware. In a typical counter-aggregation application, CPU 1 publishes its running total and CPU 2 publishes its running total; each side reads the other's value and computes a grand total. Because PUT/GET runs over the integrated PROFINET interface, you need only a switched Ethernet cable (or a shared switch) and two IP addresses in the same subnet.

This tutorial walks through every parameter required to make two CTUD-based counters visible across the link, including:

  • Hardware and firmware prerequisites
  • Project setup and CPU protection / security settings
  • Non-optimized versus optimized data blocks
  • Creating the S7 connection in the network view
  • Calling PUT and GET and mapping the REQ, ID, ADDR_1, SD_1 parameters
  • Adding the two CTUD values and verifying the result
Read the S7-1200 system manual before commissioning. PUT/GET and the access protection model changed with firmware V4.x and V5.x; later firmware versions require explicit "Permit access with PUT/GET" to be enabled for the partner.

Prerequisites

Item Requirement
Controller pair 2× SIMATIC S7-1200 CPU, any 1211C / 1212C / 1214C / 1215C / 1217C variant with PROFINET interface
Firmware V4.0 or later on both CPUs (V4.2+ recommended; V4.4 / V4.5 / V4.6 add granular access protection)
Engineering tool STEP 7 Basic / Professional V15.1 or later in TIA Portal
Ethernet Direct cable or common switch, both CPUs in the same IP subnet, e.g. 192.168.0.1 / 192.168.0.2, mask 255.255.255.0
Counter blocks At least one instance of IEC counter CTUD (IEC_Counter or IEC_Counter_0) in each CPU
Programmer access PG/PC connected to either CPU, online access password known (default-protected CPUs reject PUT/GET calls)

Step 1: Configure IP Addresses and Subnet

  1. Open the TIA Portal project containing both CPUs (or add the second CPU via Devices & networks > Add new device).
  2. Select each CPU in the device view and open Properties > PROFINET interface [X1] > Ethernet addresses.
  3. Assign:
    • CPU_1: IP 192.168.0.1, subnet mask 255.255.255.0
    • CPU_2: IP 192.168.0.2, subnet mask 255.255.255.0
  4. Tick Use router only if a router is present; for direct/subnet-local PUT/GET the router field stays empty.

Step 2: Enable PUT/GET Access on Both CPUs

Modern S7-1200 firmware ships with the connection mechanism blocked by default. Without enabling it, GET returns STATUS = 0x0001 (communication error) and PUT returns STATUS = 0x0001 as well.

  1. Select the CPU in the project tree.
  2. Open Properties > Protection & Security > Connection mechanisms.
  3. Tick Permit access with PUT/GET communication from remote partner (PLC, HMI, OPC, ...) on both CPUs.
  4. Compile and download to each controller.
On firmware V4.0 / V4.1 the toggle is in Properties > Protection under "Connection mechanisms". The wording is identical: "Permit access with PUT/GET from remote partner". If the option is greyed out, the CPU is in a higher protection level; lower the access level to "Full access incl. fail-safe" or supply the correct password.

Step 3: Create Non-Optimized Data Blocks

PUT/GET cannot dereference symbolic, fully-qualified optimized-block addresses. Each block that holds data exchanged over S7 communication must be created with Standard access (compatible with S7-300/400) — i.e. "Non-optimized".

  1. In the project tree, right-click Program blocks > Add new block > Data block (DB).
  2. In the block creation dialog, clear the tick on Optimized block access (Standard access is selected by default for new DBs but verify it).
  3. Declare at least one variable of type DInt (32-bit signed, range -2 147 483 648 to 2 147 483 647) to hold the running total. Use DInt for CTUD accumulation; Int rolls over at ±32 767.
DATA_BLOCK "DB_CounterShare"
TITLE = 'Counter share published to partner'
AUTHOR : 'AutoGen'
VERSION : 0.1
NON_RETAIN
VAR
   TotalCount : DInt;   // running total exposed to the partner CPU
END_VAR
BEGIN
END_DATA_BLOCK

Repeat the procedure on the second CPU. The DB number must be unique within each CPU. There is no requirement for the numbers to match between the two controllers — the partner's DB number is passed into the ADDR_1 parameter of GET/PUT.

Step 4: Program the CTUD Counters and the Total

Insert an IEC counter in each CPU. The IEC CTUD function block in TIA Portal is found in Instructions > Basic instructions > Counter operations > IEC counter > CTUD. In each CPU, on every scan cycle, copy CV (current value) into the published DB:

// OB1 - CPU_1
"CTUD_1"(CU := I0.0,        // count up input
         CD := I0.1,        // count down input
         R  := I0.2,        // reset
         LD := I0.3,        // load preset (PV)
         PV := 1000);

"DB_CounterShare".TotalCount := "CTUD_1".CV;   // DInt copy, non-optimized DB

Now add the math that adds the local count to the remote count. Wait until the remote count has been refreshed — call GET before the add block:

// OB1 - CPU_1 - call PUT/GET in OB1 or a cyclic OB
// Local total plus remote total
"DB_GrandTotal".GrandCount :=
    "DB_CounterShare".TotalCount + "DB_RemoteShare".RemoteCount;

Step 5: Create the S7 Connection in the Network View

  1. Open Devices & networks and select the Network view tab.
  2. Drag a line from CPU_1's PROFINET port to CPU_2's PROFINET port. TIA Portal will create an S7 connection automatically with the connection ID 1 on the local CPU and a corresponding partner ID on the remote.
  3. If you prefer to call PUT/GET with a manually managed ID, right-click the line and choose Properties > General > Connection ID — typical values are 100, 200, etc., to keep IDs stable across rebuilds.
  4. Confirm that the connection is established: the line in the network view turns solid green when online; an orange dashed line indicates "not yet downloaded / inconsistent".

Step 6: Call the GET and PUT Instructions

GET reads data from the partner into a local DB; PUT writes data to the partner. In TIA Portal, drop the GET and PUT instructions from Instructions > Communication > S7 communication into a cyclic OB (OB1 is acceptable for slow counters; OB30+ for deterministic 100 ms cycles).

Per the S7-1200 GET and PUT reference, the function block pinout is:

Pin Type Meaning
REQ Bool Trigger edge — rising edge starts the job
ID S7_CONNECTION Connection ID from the network view (e.g. 1 or 100)
NDR (GET) / DONE (PUT) Bool New data received / write completed
ERROR / STATUS Bool / Word Error flag and detailed status word
ADDR_1..ADDR_4 Variant / Remote Pointer to the partner's data area (DB, bit memory, process image)
SD_1..SD_4 (PUT only) Variant / Local Source data on the local CPU
RD_1..RD_4 (GET only) Variant / Local Destination on the local CPU

Calling GET to read the partner's counter share:

// OB1 - CPU_1 - read partner total into DB_RemoteShare
"GET_Remote"(REQ  := TRUE,                 // run continuously
             ID   := 1,                     // connection ID from network view
             ADDR_1 := P#DB2.DBX0.0 DINT 4, // partner DB2 starts at byte 0, length 4 bytes
             RD_1   := "DB_RemoteShare".RemoteCount);  // local destination

Calling PUT to send the local total to the partner:

// OB1 - CPU_1 - publish local total to partner DB3
"PUT_Local"(REQ   := TRUE,
            ID    := 1,
            SD_1  := "DB_CounterShare".TotalCount,  // local source
            ADDR_1 := P#DB3.DBX0.0 DINT 4);         // partner destination

The pointer syntax P#DB<n>.DBX<offset>.<type> <length> is mandatory on the ADDR_x pins of PUT/GET when communicating with S7-1200 partners. The compiler rejects symbolic / fully-qualified addresses for the partner side because the partner's DB numbers are only known at runtime.

Step 7: Add the Two Totals

After the GET call, DB_RemoteShare.RemoteCount holds the partner's DInt. The grand total is then a single ADD instruction:

// OB1 - CPU_1
"DB_GrandTotal".GrandCount :=
    DINT_TO_DINT("DB_CounterShare".TotalCount) +
    DINT_TO_DINT("DB_RemoteShare".RemoteCount);

Cast only if you have changed the source variable type. DInt + DInt is intrinsically safe and avoids implicit type warnings.

Step 8: Verification

  1. Download both CPU programs.
  2. Go online with both CPUs (each in its own TIA Portal instance or by switching the online target).
  3. Force CTUD_1.CU = TRUE on CPU_1 via the watch table and monitor DB_CounterShare.TotalCount on CPU_1 and DB_CounterShare.TotalCount on CPU_2 (after its PUT completes).
  4. Monitor DB_GrandTotal.GrandCount on both CPUs — both totals must match the sum of the two CTUD current values.
  5. Inspect GET_Remote.STATUS and PUT_Local.STATUS. A healthy job reports STATUS = 0x0000 on each completed call.

PUT/GET Status Word Reference

STATUS (hex) Meaning Typical fix
0x0000 Job complete, no error —
0x0001 Communication error (link / connection / protection) Check cable, IP, "Permit PUT/GET" flag, connection ID
0x0081 Remote CPU in STOP, or address invalid Place remote CPU in RUN, validate pointer
0x7000 No job in progress (REQ low or first scan) Set REQ TRUE; cycle the call
0x7001 First call / data accepted Informational
0x7002 Subsequent call / data accepted Informational
0x8090 Specified DB does not exist on the partner Create the partner DB, recompile and download
0x80A1 Access protection (PUT/GET not permitted) Enable the connection mechanism flag on partner CPU
0x80B0 Block is optimized and cannot be addressed Switch DB to "Standard access (non-optimized)"
0x80C0 Address area mismatch / overlap Match ADDR_1 length to RD_1 / SD_1 length
0x80D0 / 0x80D1 / 0x80D2 Length error / area error / number error Check pointer syntax and area limits

Troubleshooting Matrix

Symptom Likely cause Action
GET stays in STATUS = 0x7000 REQ never set TRUE, or call is in wrong OB Verify call in cyclic OB; force REQ = TRUE
GET reports 0x0001 / 0x80A1 PUT/GET not permitted on partner Enable "Permit access with PUT/GET" on the partner CPU
GET reports 0x80B0 Partner DB is optimized Recreate partner DB with non-optimized access
GET reports 0x8090 DB number on partner does not exist Verify ADDR_1 points at the correct partner DB number; download partner program
Totals drift / count lost DInt overflow (>2.1 billion counts) or wrong variable type Use DInt or LInt; add modulo logic if cyclic reset is intended
Counter on partner not updating PUT not called, or ADDR_1 points to wrong offset Check partner DB declaration order — the first DInt starts at byte 0; offsets in the pointer must match
Connection dashed orange Connection not downloaded Compile and download both CPUs; the line should turn green online
Compiler error "optimized block cannot be used as remote address" ADDR_1 references an optimized DB or its variable Use a non-optimized DB on the partner and pass the absolute pointer

Engineering Best Practices

  • Always create a dedicated non-optimized DB for S7 communication. Mixing communication variables with program variables in an optimized DB is the most common commissioning delay.
  • Use DInt for counters; reserve the sign for direction-of-counting (count-up positive, count-down negative) and let LInt handle roll-over for very long-running applications.
  • Trigger PUT/GET on a rising edge of a clock bit (e.g. Clock_1Hz or a custom slow timer) when continuous refresh is not required — this reduces PROFINET load on larger projects.
  • Use the same connection ID for all PUT/GET calls between the same pair of CPUs. Each S7 connection supports parallel PUT and GET operations.
  • Document the partner's IP address and DB numbers in the block header comment of the local GET/PUT call so future engineers can trace the data flow.
  • On firmware V4.4 and later, consider assigning a separate "S7 communication" user in Users & roles and a per-connection password to satisfy hardening policies. PUT/GET itself does not authenticate, but the partner CPU's access protection does.

Alternative Approaches

Mechanism When to choose it
PUT/GET over S7 communication Small data sets, no real-time determinism needed, simplest wiring, fewer CPUs (<8 partners)
Open User Communication (TSEND/TRCV / TCON) TCP/UDP partner is a non-Siemens device or a PC; ISO-on-TCP for S7-300/400 partners
PROFINET iDevice / iSlave Real-time cyclic data exchange with a higher-level controller; configuration effort justified only for motion or <1 ms update times
Modbus TCP (client/server blocks) Partner is a third-party PLC or a SCADA system that already speaks Modbus
OPC UA server (S7-1500 only) Modern, secure, model-based, browser/SCADA-friendly; not available on S7-1200

Frequently Asked Questions

Do both CPUs have to be the same firmware version for PUT/GET?

No. PUT/GET works between any combination of S7-1200 CPUs from V4.0 and S7-1500 CPUs from V1.5, provided both have "Permit access with PUT/GET" enabled. Mixed firmware V4.2 / V4.4 / V4.5 deployments are common in production.

Why does my GET return STATUS 0x80B0 even though the DB exists?

The DB exists but is configured with optimized access. PUT/GET requires absolute pointers such as P#DB2.DBX0.0 DINT 4, and optimized blocks hide their offsets behind symbolic names. Recreate the DB with "Standard access" (non-optimized) and recompile.

Can I trigger PUT/GET faster than once per OB1 scan?

Yes. Place the call in a cyclic interrupt OB (OB30 at 100 ms is typical) or trigger it on a clock-memory edge. Avoid running PUT/GET on every scan in a 1 ms OB — the partner's connection resources become the bottleneck long before the network does.

What is the maximum data size per PUT or GET call?

A single PUT or GET transfers up to 160 bytes; up to four address areas (ADDR_1..ADDR_4) can be combined per call. For larger blocks, use multiple PUT/GET instances in the same OB or switch to BSEND/BRCV (up to 64 KB per call).

Is PUT/GET encrypted?

No. S7 communication PUT/GET on S7-1200/1500 is unauthenticated and unencrypted on the wire. It is acceptable on trusted, physically controlled plant networks but should be replaced by OPC UA, S7-1500 secure communication, or a VPN when crossing IT/OT boundaries.

Back to blog