1. Problem Overview and Engineering Use Case
Many S7-300 deployments use identical program files across multiple CPUs that differ only in their MPI address (station number). Examples include:
- Machine series with 4 to 32 identical cells, each with its own CPU 312C/313C/314C/315-2 DP/317-2
- Modular conveyor segments where the HMI/PG must poll the "correct" PLC
- Hot-standby or peer-to-peer MPI networks where the CPU needs its own node number to build routed messages
- Asset-tracking systems that need to embed the MPI station number into a barcode, alarm, or DB string for traceability
Hard-coding the station number in the program defeats the purpose of a single project. The correct approach is to read the address at runtime from the CPU's own system data and place it in a global DB or output word.
The Siemens tool for this is SFC 51 "RDSYSST" (Read System State), which queries the System Status List (SSL) of the CPU. The S7-300/400 System Software for S7-300/400 System and Standard Functions Reference Manual documents SFC 51 in detail (Siemens Entry ID 1214574). The companion FAQ on reading system states is at 11774682.
2. Prerequisites
Before implementing the read, confirm the following:
- CPU family: S7-300 with firmware >= V2.0. All 31x, 31xC, 31xT, and 31xF variants support SFC 51. S7-400 uses the same call, but some SZL_IDs differ.
- STEP 7 version: STEP 7 V5.4 SP5 or later (or TIA Portal V13 SP1+ for S7-300 in the older TIA port). SFC 51 is in the standard library under Standard Library > System Function Blocks.
- Hardware configuration: The CPU must have its MPI interface enabled in HW Config (Properties > MPI/DP > Parameters > MPI address). Default = 2.
- Program capacity: A 34-byte buffer is sufficient for the standard partial lists (SZL partial lists are returned in 32-byte data records plus 2 bytes of header).
- Authorization: SFC 51 does not require a special password; it runs in OB 1, OB 100, and cyclic OBs without security attributes.
3. SFC 51 (RDSYSST) Fundamentals
SFC 51 reads a System Status List (SSL) or a partial list (SZL) from the CPU. The call signature is:
// SFC 51 - RDSYSST - Read System State
// STL / English keyword form
CALL "RDSYSST"
REQ := TRUE // BOOL - 1 = start read on each call (use edge for one-shot)
SZL_ID := W#16#0111 // WORD - System Status List identifier
INDEX := W#16#0002 // WORD - object index (e.g. slot 2 for S7-300 CPU)
RET_VAL:= MW100 // INT - return value (0 = OK, see error table)
BUSY := M101.0 // BOOL - 1 while SFC is working
SZL_HEADER := P#M 110.0 BYTE 6 // ANY - 6-byte header (SZL ID, partial list length, count)
DR := P#M 116.0 BYTE 32 // ANY - 32-byte data record buffer
Key parameters:
| Parameter | Type | Description |
|---|---|---|
| REQ | BOOL | Level-triggered start. Use a positive edge for one-shot reads; level-triggered only for cyclic refresh. |
| SZL_ID | WORD | Identifies the SSL/SZL. Hex constant, e.g. W#16#0111. |
| INDEX | WORD | Object index. For module-related SZLs this is the slot number; for interface SZLs this is the interface ID. |
| RET_VAL | INT | 0 = OK, 80A1h = SZL_ID not supported, 80A2h = access error, 80B1h = invalid INDEX, 80B2h = SZL in progress. |
| BUSY | BOOL | 1 while read is in progress (SFC 51 typically completes within 1 PLC scan). |
| SZL_HEADER | ANY (6 bytes) | Returns the SZL_ID echoed, length of each data record, and number of records. |
| DR | ANY (variable) | Destination area for the data record(s). Size must be >= 32 bytes for module SZLs. |
The SZL_HEADER returns 6 bytes:
Bytes 0-1 : SZL_ID (echo of the requested ID)
Bytes 2-3 : Length of one data record in bytes (N)
Bytes 4-5 : Number of data records returned (COUNT)
The CPU supplies 32 bytes per data record when the actual record length is shorter; the rest is padded with zero.
4. SSL IDs Relevant to the MPI/PROFIBUS Address
The S7-300/400 manual lists more than 100 SZL_IDs. Only a handful carry interface address information. The table below summarizes the working IDs for retrieving the CPU's integrated MPI/PROFIBUS address.
| SZL_ID (Hex) | Name | INDEX | Returns | Offset of MPI/PB address | Notes |
|---|---|---|---|---|---|
| W#16#0011 | Module Identification (S7-400 style) | Rack/Slot | Module index, MLFB, type ID, version | Not directly contained | Limited use for interface address |
| W#16#0F31 | Module Identification (all modules) | 0 | All modules' identification data | See SZL_ID 0111 | Use to enumerate slots first |
| W#16#0111 | Status of a Module | Slot (0 = own CPU, 2 for S7-300 central) | Module status, including interface logical address | Bytes 28-29 (logical base address of interface) | Primary candidate for MPI/PB address |
| W#16#0019 | Communication Status | Interface ID (0 = MPI, 1 = DP, 2 = PN) | Communication path status, port addresses | Bytes 4-5 contain PROFIBUS station number of selected interface | Best fit for the "station number" the user asked about |
| W#16#001C | Interface Parameter Assignment | Interface ID | Configured interface parameters | Bytes 6-7 = own station address | Mirrors HW Config setting |
| W#16#0092 | Network Diagnostics (PROFIBUS) | DP master system ID | DP slave diagnostics | n/a (DP slaves only) | Use SFC 13 (DPNRM_DG) for DP slaves |
5. Reading the MPI Address - Step-by-Step STL Implementation
The complete, copy-paste-ready STL block reads the MPI station number at startup, stores it in a global DB, and exposes it as an integer output for the rest of the program.
Step 1 - Allocate a global DB (e.g. DB 200 "CPU_Identity") with the following layout:
DATA_BLOCK "CPU_Identity"
VERSION : 0.1
STRUCT
MPI_Address : INT; // station number 0..31 (MPI) / 1..126 (DP)
Interface_ID : BYTE; // 0=MPI, 1=DP, 2=PN
SZL_Header_Valid : BOOL; // 1 = read finished OK
SZL_Error : INT; // RET_VAL from SFC 51 last call
Read_Done : BOOL; // first scan finished
END_STRUCT;
END_DATA_BLOCK
Step 2 - Call SFC 51 in OB 100 (startup) or the first scan of OB 1:
// OB 100 - Startup - One-shot read of own MPI station number
// Uses SZL_ID W#16#0019, INDEX 0 = integrated MPI interface
SET
= "CPU_Identity".SZL_Header_Valid // reset ready flag
CALL "RDSYSST" , DB1 // DB1 = SFC 51 instance
REQ := TRUE
SZL_ID := W#16#0019
INDEX := W#16#0000 // 0 = MPI, 1 = DP, 2 = PN
RET_VAL := "CPU_Identity".SZL_Error
BUSY := M200.0
SZL_HEADER := P#M 50.0 BYTE 6
DR := P#M 56.0 BYTE 32
AN M200.0 // BUSY 0 = finished
JC _end
// Extract station number from DR:
// Bytes 0-1 : SZL_ID echo
// Bytes 2-3 : reserved
// Bytes 4-5 : own station address (MPI/PB/PN)
L MB 60 // low byte of own address
T "CPU_Identity".MPI_Address
L MB 57 // interface ID byte
T "CPU_Identity".Interface_ID
SET
S "CPU_Identity".SZL_Header_Valid
S "CPU_Identity".Read_Done
_end: NOP 0
Step 3 - Use the value in the rest of the program:
// Ladder fragment in FBD form
L "CPU_Identity".MPI_Address
T MW 120 // expose at output word 120
T DB100.DB[DB100.Offset_Base] // optional: copy to recipe header DB
The same pattern works in LAD with a single contact to enable the SFC 51 box and a MOVE block to copy bytes 60-61 into the DB.
6. Alternative Methods for Reading the Station Number
If SFC 51 does not return the expected data (CPU firmware too old, SZL not implemented on that CPU), use one of the following approaches.
6.1 SFB 52 "RDREC" - Read Data Record 0 of the Integrated Interface
The CPU's integrated MPI/PROFIBUS interface responds to a DP slave diagnostic request even when no DP slaves are connected. The diagnostic data record (DS 0) contains the station number.
CALL "RDREC" , DB52
REQ := M210.0
ID := DW#16#0FFF // own logical address of interface
INDEX := 0 // DS 0
MLEN := 32 // read up to 32 bytes
VALID := M211.0
BUSY := M211.1
ERROR := M211.2
STATUS := MW212
LEN := MW214
RECORD := P#M 220.0 BYTE 32
// First 6 bytes = standard DP-V0 diagnostic; byte 4 = station number
L MB 224
T "CPU_Identity".MPI_Address
ID parameter: Use the diagnostic address of the integrated DP interface. In HW Config, open the Properties of the CPU's DP interface and copy the "Diagnostic address" of slot 0. Typical value: 2046 (CPU 315-2 DP) or 16382 (CPU 317-2 DP). Refer to the S7-300 CPU manual at 8859629 for the exact default address of your CPU.
6.2 SFC 5 "GADR_LGC" - Get Logical Address of a Slot
SFC 5 returns the I/O base addresses of a module in a given rack/slot. It does not return the MPI station number, but combined with the interface properties in SZL_ID W#16#0011 it can be used to derive the interface's logical address. Use this when the application must build direct I/O access to the integrated interface.
CALL "GADR_LGC"
IOID := B#16#54 // 54h = input area of interface
LADDR := W#16#7FFE // any address in interface area
RET_VAL := MW230
SUBSLOT := MW232
SUBADDR := MD234
6.3 Pointer-Based Access to the System Data Block (SDB)
The interface parameters are stored in SDB 1 (PROFIBUS DP master) and SDB 2 (MPI). Reading these directly from user logic is not supported; configure via HW Config instead. SFC 51 is still the correct runtime path.
6.4 System Function Block SFB 81 (RD_SBL) - Read Slave Diagnostics
For DP slave station numbers (e.g. an ET 200S), use SFB 81 instead of SFC 51. The S7-300 manual 18652056 covers distributed I/O diagnostics.
7. Multi-PLC Project Strategy
When the same project must be downloaded to many CPUs with different station numbers, follow the workflow below.
- Compile once in STEP 7 / TIA Portal with a placeholder MPI address (typically 2).
- Distribute the program via SD card, Ethernet download, or the S7 Memory Card.
- On first power-up, the program reads the real address from SFC 51 and stores it in DB 200.
- Use the value in all peer-to-peer (S7 communication "PUT/GET"), broadcast messages, and alarm tags.
Critical engineering points:
- The address is read once at startup. Re-read it in OB 100 (warm restart) and OB 101 (hot restart) to capture any HMI-driven address change. STEP 7 allows the MPI address to be reassigned online via the PG; OB 100 will see the new value after the next restart.
- For PN CPUs (e.g., 315-2 PN/DP), the IP address is not in SZL_ID 0019. Use SZL_ID W#16#0131 (own IP parameters) or the system function blocks of Open Communication (FB 65/66) for IP retrieval.
- Avoid calling SFC 51 in a fast OB (e.g. OB 35 at 100 ms). The call typically completes in 1-2 ms but is not deterministic; restrict to OB 1, OB 100, and OB 101.
- If the program must change its own MPI address at runtime, use SFC 5 (GADR_LGC) to find the interface, then write the new value with the PG function "Assign MPI Address". SFC 51 cannot write the address; this is a hardware-configuration function.
8. Verification and Commissioning
Add a VAT (Variable Table) to the project to verify the read result.
- Open the S7 program in STEP 7 and create a VAT named "CPU_ID_Check".
- Insert the following monitor entries:
DB200.DBW0 INT // MPI_Address (decimal 0..31 = MPI, 1..126 = DP) DB200.DBB2 BYTE // Interface_ID DB200.DBB3 BOOL // SZL_Header_Valid DB200.DBW4 INT // SZL_Error (should be 0000 after successful read) MW 60 BYTE // raw byte from SFC 51 DR buffer (offset 4) MW 50 WORD // SZL_ID echo (should be 0019) MW 52 WORD // record length (should be 0006 or 0008) - Download the project, perform a CPU restart (STOP -> RUN), and switch the VAT to "Monitor".
- Confirm the following:
- DB200.DBW0 equals the value set in HW Config under "MPI/DP Properties > Address".
- DB200.DBB3 = 1 (read complete).
- DB200.DBW4 = 0 (no error).
- MW 50 = W#16#0019 (SZL_ID echo matches request).
- Change the MPI address in HW Config, re-download, restart, and verify DB200.DBW0 changes to the new value.
9. Troubleshooting Matrix
| Symptom | RET_VAL (hex) | Probable Cause | Corrective Action |
|---|---|---|---|
| DB200.MPI_Address = 0 after restart | 80A1 | SZL_ID not supported on this CPU/firmware | Check CPU firmware; try SZL_ID W#16#0111 or W#16#001C; fall back to SFB 52 / DS 0 read |
| DB200.SZL_Header_Valid never sets | 80A2 | Access error - DR or SZL_HEADER ANY pointer invalid | Verify ANY pointer length (6 bytes for header, >= record length for DR); avoid cross-section overlap with M200..M231 used by the call |
| CPU goes to SF with "Parameter assignment error" | 80B1 | Invalid INDEX for the SZL_ID | Confirm interface ID. For integrated MPI use INDEX 0; for integrated DP use INDEX 1; for PN use INDEX 2 (only S7-300 PN/DP CPUs) |
| DB200.MPI_Address = 255 or unexpected high value | 0000 (read OK) | Wrong byte offset; the address is at a different position in the DR | Inspect the raw 32-byte DR buffer in the VAT. The address is the byte where the value matches the HW Config setting |
| Read OK at startup but value 0 at runtime | 0000 (read OK) | OB 1 call is gated by a condition that never becomes true; or a MOVE elsewhere overwrites the DB | Use VAT to watch DB200.DBB3 and DB200.DBW0 online; remove any STMSFLY conditions gating the SFC call |
| SFC 51 returns RET_VAL 80B2 "SZL in progress" forever | 80B2 | Multiple calls overlapping on a multi-processor CPU; the same SFC instance re-triggered before completing | Use a single SFC 51 instance (DB) per SZL_ID; gate REQ on BUSY = 0; never call from OB 35/OB 61 |
| Works on CPU 315-2 DP but not on CPU 312C | 80A1 | CPU 312C (V2.x) supports fewer SZL_IDs than the 315-2 DP (V3.x) | Verify the SZL_ID in the S7-300 manual table; older firmware only supports SZL_IDs 0F31 and 0011 |
| MPI address read OK, but HMI cannot connect | n/a | HMI is configured for a fixed MPI address; the SFC read returns the right value but the HMI does not match | Set the HMI connection to "Online accessible nodes" and let WinCC flexible / TIA Portal discover the running address |
| PROFINET CPU returns wrong address | 0000 (read OK) | IP address and MAC are at a different SZL_ID; reading 0019H gives the PROFIBUS station number, not the IP | Use SZL_ID W#16#0131 "IP Parameters" or FB 65/66 for Open Communication IP discovery |
10. Edge Cases and Field Notes
Firmware-dependent SZL support. S7-300 CPUs with firmware V2.0 implement SZL_IDs 0000, 0011, 0012, 0013, 0014, 0015, 0019, 0111, 0F31, 0F32. CPUs with firmware V3.x add 001C, 001E, 001F, 0131, 0F33, 0132, 0424, 0F82. Always consult the CPU's Module Information in STEP 7 (online > Module Information > Diagnostic Buffer) when an SZL_ID returns 80A1.
Multi-processor S7-400 caveat. On an S7-400 with multiple CPUs, SFC 51 returns the SSL of the CPU on which it executes. If the project uses CPU-to-CPU communication, the program must run on the CPU whose address is being read.
PROFIBUS DP master vs. slave role. When the integrated interface is configured as DP master, INDEX = 1 in SZL_ID 0019H returns the master's own station number. When the interface is configured as DP slave, the same INDEX returns the slave's own station number, which differs from the master's. Verify the role in HW Config > Properties > "Operating Mode".
Cyclic re-read with watchdog. Some commissioning engineers re-execute SFC 51 every hour to catch operator-driven address changes. Wrap the call in an FB with a TON timer; if the read fails (RET_VAL <> 0) for three consecutive attempts, raise a maintenance alarm and revert to the cached value in DB 200.
Memory card migration. When a project is moved between CPUs of different type (e.g., 313C -> 314C), the MPI default address may revert to 2 on the new CPU. The SFC 51 read in OB 100 will pick up the new value automatically, but the assignment of the address in the new CPU's HW Config is the integrator's responsibility.
SFC 51 in a fail-safe (F) CPU. SFC 51 is not a safety function and must not be used in the F-runtime group. Reading the MPI address for a diagnostic purpose is acceptable; using it to make a safety decision is not. The S7-300F system manual 19088450 defines the boundary.
Comparison with TIA Portal. In TIA Portal V13 and later, SFC 51 still works inside S7-300 programs; the call is identical. For S7-1500, the equivalent instruction is "RD_SBL" (read S7 system state) under "System diagnostics" or the GET_DIAG system block. S7-1500 uses a different SZL concept; the program must be ported manually if migrating.
Why the manual does not list "MPI address" by name. The S7-300/400 manual groups SZLs by category (module identification, status, communication). The interface station number lives under "Communication Status". Engineers searching the manual index for "MPI" sometimes miss it; searching for "station number" or "interface ID" returns the right page.
11. Frequently Asked Questions
What SZL_ID returns the S7-300 CPU's own MPI address with SFC 51?
Use SZL_ID = W#16#0019 (Communication Status) with INDEX = W#16#0000 for the integrated MPI interface. Bytes 4-5 of the returned data record contain the station number. For the integrated PROFIBUS interface, use INDEX = W#16#0001.
Can SFC 51 change the CPU's MPI address from ladder logic?
No. SFC 51 is read-only. To change the MPI address, use HW Config or the PG function "Assign MPI Address" (PLC > Assign Address). The runtime program must restart (OB 100) to read the new value with SFC 51.
Why does SFC 51 return RET_VAL 80A1 on my CPU 312C?
CPU 312C with firmware V2.x supports a smaller set of SZL_IDs. The Communication Status (W#16#0019) was added in firmware V3.x. Upgrade the CPU to V3.x or use SFB 52 with data record 0 of the integrated interface as an alternative.
How do I read the IP address of a PROFINET S7-300 (e.g., 315-2 PN/DP) from the program?
SZL_ID W#16#0019 does not return the IP address. Use SZL_ID W#16#0131 (own IP parameters) on firmware V3.x, or read the IP from the system data block using FB 65 / FB 66 (Open Communication) and the IP_GET primitive. The IP appears at bytes 0-3 of the 32-byte DR buffer.
Is SFC 51 deterministic? Can I call it in OB 35?
No. SFC 51 typically completes in 1-2 ms but the call is not time-deterministic and may extend a scan if a parallel SFC 51 call is in progress. Restrict SFC 51 to OB 1 (level-triggered or first scan), OB 100, and OB 101. Do not use it in OB 35/OB 61/OB 82.
Can I read the MPI address of a remote CPU via S7 communication?
Not directly. S7 communication (PUT/GET / BSEND/BRCV) exposes partner MPI addresses only when the connection is configured. To discover a remote CPU's address, use PG functions or open a separate S7 connection with placeholder address and let SFC 51 return the partner ID once the link is up.
What is the maximum MPI station number SFC 51 can return?
For MPI: 0 to 31. For PROFIBUS DP: 1 to 126. SFC 51 will not return 127 (reserved for broadcast) on a valid read; if the value is 127, the data record is corrupted or the SZL was misread - verify the offset.