SFC14/SFC15 Sequential PKW Access Resolving Response Mix-Up on S7

David Krause15 min read
ProfibusSiemensTroubleshooting
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

Problem Overview: Non-Cyclic PKW Parameter Access on S7

Sequential non-cyclic parameter read/write operations between a Siemens SIMATIC S7 CPU (S7-300/S7-400) and a PROFIBUS-DP slave — in this case a Schneider Electric Altivar 312 (ATV312) variable frequency drive — require careful orchestration when the PKW mechanism (Parameter-Kennung-Wert, 8 bytes) is used. The PZD (Prozessdaten) area handles the cyclic control/status words and setpoint/actual speed on a 4-byte boundary and uses continuous SFC14/SFC15 calls without issue.

The PKW channel is fundamentally different: it is a request/response protocol where each 8-byte write of a parameter address+function code must be matched with the corresponding 8-byte read containing the parameter value. When several parameters are polled in a tight sequence (step 0 → step 1 → step 2 → step 3), the user often observes that response words in the input area flicker or contain values that do not correspond to the request just issued. This is the classic "response mix-up" symptom and is the focus of this article.

Root Cause: SFC14/SFC15 Have No Built-In Request Tagging

Unlike the USS/Modbus/DPV1 acyclic services available on newer S7 CPUs, the standard SFC14 (DPRD_DAT) and SFC15 (DPWR_DAT) blocks operate on raw consistent I/O areas. They expose only:

  • REQ — edge-triggered execution
  • LADDR — logical base address of the DP slave I/O area
  • RET_VAL — return code (0 = OK, non-zero = error)
  • RECORD — pointer to the data area in the S7

There is no transaction ID, no DONE bit per request, and no per-packet acknowledgement. RET_VAL = 0 only confirms the system service was accepted by the PROFIBUS stack, not that the response you are about to read belongs to the request you just issued. Because PROFIBUS-DP is a master-slave bus with deterministic cycle time (typically 1.5–10 ms with a 1.5 Mbaud line and 12 Mbaud), the round-trip latency for an 8-byte PKW exchange can vary between 1 and 3 bus cycles depending on slave response time and bus load. If you fire request N+1 before the response of request N has been fully written into the input area, the read buffer can contain the value of either N or N+1 — leading to the observed flickering VAT values.

Why "Just Add a Delay" Works But Is Not Acceptable

A 50–100 ms delay between SFC15 and the subsequent SFC14 will empirically eliminate the mix-up on lightly loaded buses because the bus cycle is forced to complete and the input area is refreshed. However, this is not an engineering solution for three reasons:

  1. Non-deterministic on loaded buses — when other DP slaves share the bus, the cycle can stretch beyond the arbitrary timer value.
  2. Wastes OB1 time — the SFC call is synchronous and the timer blocks the priority class.
  3. Hides the real problem — a robust sequencer must verify response identity, not just hope for the best.

The Correct Solution: Address-Matching Sequencer

The PKW telegram structure carries the parameter address (PNU) and the request/response identifier in both directions. By reading the address echo from the response telegram and comparing it to the address you just wrote, you can deterministically confirm that the response corresponds to the request. This is the same mechanism used internally by drives when the host master is a PLC and is the basis for the standard Siemens DRIVE ES / STARTER parameter access library.

PKW Telegram Structure (8 bytes / 4 words)

Word Byte Function Direction (Master→Slave / Slave→Master)
1 0,1 Identifier (PKE) — high byte: AK (Auftrags-/Antwort-Kennung), low byte: PNU high Master→Slave: task; Slave→Master: response
2 2,3 Parameter number (low byte PNU) + IND (parameter index, high byte) Both directions
3 4,5 Parameter value (PWE high word) — for read = parameter value; for write = value to be written Both directions
4 6,7 Parameter value (PWE low word) Both directions

The PNU (Parameter Number) is reconstructed by combining byte 0 low and byte 2 high. For an ATV312 the parameter address is the PNU only — IND is always 0 unless accessing array parameters (in which case IND holds the index). The same PNU value is echoed in the response, which is the field you must match against.

ATV312-Specific AK Codes (Request/Response Identifiers)

AK (hex) Direction Meaning
0x01 Master→Slave Read parameter value (request)
0x02 Master→Slave Write parameter value (single word)
0x03 Master→Slave Write parameter value (double word)
0x07 Master→Slave Read parameter description (text array)
0x08 Master→Slave Read parameter value (array element)
0x00 / 0x01 Slave→Master Response: positive, value in PWE
0x07 / 0x08 Slave→Master Response: positive, value(s) in PWE
0x05 Slave→Master Negative response — error code in PWE low word

For monitoring-only parameters, AK=0x01 (read single parameter value) is used. The response carries the same PNU and the parameter value in PWE words 3 and 4.

Implementation: Sequencer FB in S7 STL / SCL

The following FB (Function Block) implements the address-matching sequencer. The key engineering decision is: do not advance to the next step until the response PNU matches the request PNU. This is a closed-loop handshake that is robust against any bus latency or slave response time.

FB Interface (SCL)

FUNCTION_BLOCK FB_PKW_Sequencer
VAR_INPUT
    iStart        : BOOL;     // Start the sequence
    iLogicalAddr  : INT;      // PROFIBUS logical base address of the PKW slot
    iPKE_Template : WORD;     // AK << 8 | PNU_high (build per request)
    iPNU_Low      : BYTE;     // PNU low byte of first parameter
    iNumParams    : INT;      // How many parameters to read in sequence
END_VAR
VAR_OUTPUT
    oBusy         : BOOL;
    oDone         : BOOL;
    oError        : BOOL;
    oStatus       : WORD;     // Last RET_VAL or sequencer state
    oValues       : ARRAY[1..16] OF WORD;  // Captured parameter values
END_VAR
VAR
    sState        : INT;      // 0=idle, 1=write req, 2=read+verify, 3=advance
    sWriteBuf     : ARRAY[0..7] OF BYTE;  // 8-byte PKW request
    sReadBuf      : ARRAY[0..7] OF BYTE;  // 8-byte PKW response
    sIdx          : INT;      // Current parameter index
    sReqPNU       : WORD;     // PNU we asked for (built from PKE word 1)
    sRespPNU      : WORD;     // PNU echoed by the slave
    sRetVal       : INT;      // Last SFC return code
    sTimeout      : TON;      // Watchdog timer
END_VAR

Sequencer Body (SCL — Core Handshake Logic)

// --- Build request PNU from input parameters (byte-packed PKE) ---
// PKE word 1 layout: AK[15..8] | PNU_high[7..0]
// PKE word 2 layout: PNU_low[15..8] | IND[7..0]
// ATV312: IND always 0, PNU_high = iPKE_Template low byte

IF iStart AND (sState = 0) THEN
    sState  := 1;
    sIdx    := 1;
    oBusy   := TRUE;
    oDone   := FALSE;
    oError  := FALSE;
END_IF;

CASE sState OF

1:  // ----- WRITE REQUEST -----
    // Build the 8-byte PKW telegram: AK=0x01 (read request), PNU
    sWriteBuf[0] := 16#01;                          // AK = read param value
    sWriteBuf[1] := iPKE_Template;                   // PNU high
    sWriteBuf[2] := iPNU_Low;                        // PNU low
    sWriteBuf[3] := 16#00;                           // IND = 0
    sWriteBuf[4] := 16#00;                           // PWE high = 0
    sWriteBuf[5] := 16#00;
    sWriteBuf[6] := 16#00;                           // PWE low = 0
    sWriteBuf[7] := 16#00;

    sReqPNU := WORD#16#0000;
    sReqPNU := SHL(WORD#16#00FF AND WORD_TO_INT(iPKE_Template), 8)
               OR SHL(BYTE_TO_WORD(iPNU_Low), 0);
    // Simpler: build the 16-bit PKE word 1 directly if your
    // template already encodes it.

    sRetVal := DPWR_DAT(
        LADDR  := iLogicalAddr,
        RECORD := sWriteBuf
    );
    IF sRetVal = 0 THEN
        sState := 2;
        sTimeout(IN := FALSE);   // arm watchdog
        sTimeout(IN := TRUE, PT := T#500ms);
    ELSE
        oError  := TRUE;
        oStatus := INT_TO_WORD(sRetVal);
        sState  := 99;            // fault
    END_IF;

2:  // ----- READ RESPONSE + PNU MATCH -----
    sRetVal := DPRD_DAT(
        LADDR  := iLogicalAddr,
        RET_VAL:= sRetVal,
        RECORD := sReadBuf
    );
    IF sRetVal <> 0 THEN
        oError  := TRUE;
        oStatus := INT_TO_WORD(sRetVal);
        sState  := 99;
    END_IF;

    // Reconstruct PNU from response PKE word 1 (byte 0, byte 1)
    sRespPNU := SHL(BYTE_TO_WORD(sReadBuf[1]), 8)
             OR BYTE_TO_WORD(sReadBuf[2]);

    // Reject "response in progress" markers (bus not yet written by slave)
    IF sReadBuf[0] = 16#00 AND sReadBuf[1] = 16#00
                    AND sReadBuf[2] = 16#00 THEN
        // No valid response yet — wait
        IF sTimeout.Q THEN
            oError  := TRUE;
            oStatus := 16#8001;  // local timeout
            sState  := 99;
        END_IF;
    ELSIF sRespPNU = sReqPNU THEN
        // MATCH: capture PWE (parameter value)
        oValues[sIdx].high := sReadBuf[4];   // PWE high byte
        oValues[sIdx].low  := sReadBuf[5];
        sState := 3;
    ELSE
        // PNU mismatch — do not advance; keep polling until match
        // (this is the line that eliminates the flicker)
        IF sTimeout.Q THEN
            oError  := TRUE;
            oStatus := 16#8002;  // address echo mismatch timeout
            sState  := 99;
        END_IF;
    END_IF;

3:  // ----- ADVANCE TO NEXT PARAMETER -----
    sIdx := sIdx + 1;
    IF sIdx > iNumParams THEN
        oBusy  := FALSE;
        oDone  := TRUE;
        sState := 0;
    ELSE
        sState := 1;  // next request
    END_IF;

99: // ----- FAULT TERMINATION -----
    oBusy := FALSE;
    // oError already latched

END_CASE;

Step-by-Step Commissioning Procedure

  1. Configure HW Config in STEP 7 / TIA Portal. Insert the ATV312 GSD file (ats0_0ab.gsd or current revision) into HW Catalog. Allocate a 4-word (8-byte) PKW slot and a 4-byte (2-word) PZD slot to the slave. Note the logical base address (e.g., I/Q address 256..271 for the PKW area). The PKW slot is the LADDR you pass to SFC14/SFC15.
  2. Build the request telegram in a DB. Use a data block of type STRUCT with two WORD fields for PKE and two for PWE, mapped over 8 bytes. Do not use BOOL arrays for the PKW area — it must be word-aligned for SFC consistency.
  3. First call in VAT for static test. Force one SFC15 call with a known parameter (e.g., read PNU=100 = ACC on ATV312, which is the acceleration ramp). Force RET_VAL to 0 manually if the bus is not yet live to confirm block address wiring.
  4. Implement the address-match handshake as shown above. The handshake is the heart of the sequencer. Do not remove the timeout (TON with PT=500 ms) — without it a single bus error can stall the OB1 cycle.
  5. Watch the PKW traffic in a PROFIBUS tracer. Tools such as Siemens PROFIBUS tracer or the diagnostic buffer in STEP 7 (PLC → Module Information → Diagnostic Buffer) confirm that the master is writing the correct AK/PNU sequence and the slave is responding with the matching PKE.
  6. Decide on call rate. The PKW channel is non-cyclic, so polling 10–20 monitoring parameters at 200–500 ms intervals is realistic on a 1.5 Mbaud bus. Faster rates starve the cyclic PZD traffic and can trip the watchdog in the drive.

ATV312 PKW-Specific Notes

  • IND is always 0 for monitoring parameters on ATV312. The parameter index field is not used for individual parameters — only for arrays, and the ATV312 rarely exposes array access via the standard PKW channel. Leave IND = 0 unless you have confirmed an array parameter.
  • Word-swap warning. The ATV312 (and most Schneider drives) return PWE in big-endian order, while S7 stores WORD in little-endian. The high and low bytes of oValues[] as written in the SCL above must be byte-swapped (or use TAW/CAW in STL) to obtain a correct 16-bit signed or unsigned parameter value.
  • Float parameters. Some ATV312 parameters are REAL (32-bit IEEE 754). When reading a float, read the first word (PWE high) and the second word (PWE low) into two adjacent WORDs, then assemble a DWORD, and finally cast to REAL. The byte order is again big-endian: PWE high is the most-significant word of the IEEE 754 representation.
  • Error code in negative response. When the AK in byte 0 of the response is 0x05 or 0x06, the PWE low word contains an error code specific to the drive. For the ATV312, common values are 0x0001 (invalid PNU), 0x0002 (parameter not changeable while running), 0x0017 (parameter access temporarily not possible, e.g., during auto-tuning). Always log the error code to the diagnostic buffer for field support.

Verification Procedure

  1. Static check. Open the sequencer in VAT and step it manually. Confirm oValues[1] corresponds to PNU 100 (ACC on ATV312), oValues[2] to PNU 101 (DEC), etc. Use the ATV312 HMI keypad to navigate to the same menu and read the parameter value to confirm numerical match.
  2. Timing verification. Use a trace in STEP 7 (Traces → Sequence of events) to record the time between oBusy := TRUE and oDone := TRUE for a known number of parameters. Expect N × 2 × T_bus where T_bus is the bus cycle (1.5–10 ms typical). If the elapsed time is 5× or more longer than the theoretical minimum, you have a bus load or response-time problem.
  3. Stress test. Add 10–20% bus load by enabling other DP slaves and rerun the sequence. The address-match handshake should keep oValues[] consistent; the only effect should be an increase in the per-parameter latency.
  4. Disconnect test. Physically disconnect the PROFIBUS connector and verify that the sequencer raises oError = TRUE and latches oStatus = 16#8001 (or your chosen timeout code) within the configured PT of the TON.
  5. Negative-response test. Request a non-existent PNU (e.g., 9999). The sequencer should complete, the response AK should be 0x05, and oValues[] for that slot should contain the error code, not a stale value.

Common RET_VAL Codes from SFC14 / SFC15

RET_VAL (hex) Meaning Action
0x0000 No error Proceed
0x808x System error in lower byte (refer to SFC14/SFC15 manual) Check HW Config, slave diagnostics
0x80A0 Negative acknowledgement from slave Check slave address, wiring, GSD revision
0x80A1 Slave not ready / not connected Check PROFIBUS cable and terminators
0x80A2 Invalid LADDR Verify logical base address in HW Config
0x80B0 PROFIBUS DP error, slave not in data exchange Slave diagnostic interrupt, check status word
0x80B1 Data length mismatch Configured length in HW Config vs. actual slot length
0x80B2 Wrong PKW length in GSD Verify PKW slot is exactly 8 bytes (4 words)
0x80C0 Read conflict (data not yet consistent) Re-poll after timeout
0x80C1 Write conflict Re-issue write after timeout

Alternative: DPV1 Acyclic Services (When Available)

If the S7 CPU is a newer model with integrated PROFIBUS (e.g., CPU 315-2 PN/DP, CPU 317-2) and the ATV312 supports DPV1, the more modern approach is to use SFB52 (RDREC) and SFB53 (WRREC) for acyclic parameter access. DPV1 carries a transaction ID internally and eliminates the need for the address-matching sequencer. Check the ATV312 firmware version and the connected communication card (VW3-A58301) for DPV1 support. Even with DPV1, the same address-echo verification pattern can be retained as a safety net for slow slaves.

Alternative: Continuous Polling Pattern (Background Task)

Another field-proven approach for monitoring-only parameters is to call SFC14 continuously in OB1 (or in a cyclic OB 30–38 with a 100 ms period) without SFC15. The drive can be configured to expose commonly used parameters in a pre-defined PKW slot via the ATV312 COMM menu. This eliminates the sequencer entirely at the cost of having to change the drive configuration. For more advanced installations, place the entire sequencer in a low-priority OB (e.g., OB 35 with 100 ms period) to prevent PKW latency from affecting the PZD cyclic response time.

Troubleshooting Matrix

Symptom Likely Cause Fix
Values flicker between parameters Sequencer reads response before bus update completes Add PNU-echo handshake as shown above
All values = 0, no error LADDR points to PZD area instead of PKW Check HW Config slot order; PKW is the first 8 bytes
RET_VAL = 0x80A1 after a few hours Loose PROFIBUS connector or EMC Tighten connectors, check shield grounding
First parameter always wrong, rest correct Initial buffer contains leftover data from slave power-on Pre-fill sReadBuf with 0 before first SFC14 call
Intermittent negative responses (AK=0x05) Drive in rUn state rejects changes to write-protected params Switch to read-only AK=0x01, filter error codes in sequencer
OB1 cycle time increases linearly with parameter count Sequencer runs in OB1 with blocking timeout Move sequencer to OB 35 with 100 ms period
Diagnostic buffer shows "DP slave failure" GSD mismatch with ATV312 firmware Update GSD to match drive firmware revision

Safety and Operational Notes

Read-only recommendation: For pure monitoring parameters (motor current, drive temperature, output frequency), never use AK=0x02/0x03 (write). A stray PKW write to a configuration parameter while the drive is in rUn can cause an uncontrolled change in motor behavior. The sequencer should use a single, hard-coded AK for all parameters and validate the response AK against the allowed list before acting on the value.
Bus cycle protection: PKW is non-cyclic and does not interrupt PZD cyclic exchange, but it does consume bus bandwidth. Limit the PKW polling to the parameters that are actually displayed in the HMI or archived. A polling rate of 1–2 parameters per second is the practical maximum on a 1.5 Mbaud bus shared with other slaves.

References for Further Verification

Why do I get flickering parameter values when reading multiple parameters sequentially via SFC14/SFC15?

The PKW channel is a request/response protocol with no built-in transaction ID in SFC14/SFC15. RET_VAL = 0 only confirms the system service was accepted, not that the response corresponds to the request just issued. The bus round-trip latency (1–3 cycles) means the input area may still contain the previous response when you issue the next read. Implement an address-matching sequencer that polls SFC14 until the response PNU equals the request PNU.

What is the correct PKW telegram structure for an ATV312?

The PKW area is exactly 8 bytes (4 words): word 1 = PKE (AK in high byte, PNU high in low byte), word 2 = PNU low (high byte) + IND (low byte, always 0 for monitoring parameters on ATV312), word 3 = PWE high, word 4 = PWE low. For a read request, AK = 0x01. The response echoes the same PNU in bytes 0–2.

Is a 50–100 ms delay between SFC15 and SFC14 acceptable?

Empirically it eliminates the mix-up on a lightly loaded bus, but it is not robust. Bus cycle time varies with slave count and bus load, and the timer is non-deterministic. Use a TON with a 500 ms PT combined with the PNU-echo verification, or move to DPV1 services (SFB52/SFB53) if the slave supports them.

How do I read a 32-bit REAL parameter from the ATV312 PKW area?

Read both PWE words (words 3 and 4 of the 8-byte response) into two adjacent WORDs, assemble a DWORD (PWE high is the most-significant word of the IEEE 754 representation, big-endian byte order), then cast to REAL. Apply a byte-swap (CAW) if your target S7 reads in little-endian.

Can I use SFB52 (RDREC) / SFB53 (WRREC) instead of SFC14/SFC15 on an S7-300 with the ATV312?

Yes, but only if both ends support DPV1. The CPU must have integrated PROFIBUS (CPU 31x-2 PN/DP or similar) and the ATV312 must be fitted with a DPV1-capable communication card and the correct GSD. DPV1 has a built-in transaction ID and removes the need for the address-matching sequencer, but the address-echo verification can still be retained as a safety net.

Back to blog