Problem Overview: Mixing Bulk Transfer and Single-Byte Forwarding
On a Siemens SIMATIC S7-300/S7-400 pair linked through a PROFIBUS DP/DP Coupler (catalog number 6ES7158-0AD01-0XA0 or current successor), a common commissioning task is to mirror 70 bytes of process data in each direction and forward a single status byte (diagnostic flag, handshake, or peer-state indicator) from one PLC to a non-contiguous location in the peer DB. The combination of SFC15 DPWR_DAT for consistent 70-byte writes and SFC20 BLKMOV for variable-length copies routinely raises three practical questions: which addressing level to use, whether the STEP 7 compiler accepts mixed pointer parameters, and how to avoid data collisions when the same output range is written from two networks in the same OB1 cycle.
This reference walks through the correct hardware configuration of the DP/DP Coupler, the byte-level DB addressing required by SFC20, the choice between MOVE and BLKMOV for a single byte, and the cycle-order rules that prevent write-after-write race conditions on the same PROFIBUS output slot.
Prerequisites
- Two SIMATIC S7-300 or S7-400 stations programmed with STEP 7 V5.5 or STEP 7 Professional in TIA Portal V16+.
- One PROFIBUS DP/DP Coupler (6ES7158-0AD01-0XA0) configured in HW Config on both masters with matching I/O slot sizes (max 244 bytes input + 244 bytes output per side, total per side 488 bytes).
- One PROFIBUS cable per side, terminated and shielded per the manufacturer manual.
- DB1 (process image buffer, 70-byte Inputs and 70-byte Outputs arrays) and DB2 (forwarded single-byte buffer) compiled with the "Non-optimized" (standard) access attribute, because SFC inputs require absolute byte-level pointers.
- Symbolic or absolute I/O addresses for the coupler, e.g.,
PEW 256/PAW 256, configured in HW Config under the DP/DP Coupler object.
Step 1: Hardware Configuration of the DP/DP Coupler
The DP/DP Coupler exposes only I and Q addresses in each PLC's hardware configuration. It does not provide a peer DB-to-DB tunnel. On PLC1, configure an I-address range (for example 70 bytes starting at IB 256) and a Q-address range (70 bytes starting at QB 256). On PLC2 the I and Q ranges are configured independently with the same total length, but the absolute address numbers do not need to match; only the byte count must match in each direction.
Configure both PLCs identically with respect to length (input bytes, output bytes), but independently with respect to address. For 70 bytes in each direction:
| Side | Input length (bytes) | Output length (bytes) | Typical start address |
|---|---|---|---|
| PLC1 input from PLC2 | 70 | 0 (or 70 if mirrored) | IB 256 |
| PLC1 output to PLC2 | 0 (or 70) | 70 | QB 256 |
| PLC2 input from PLC1 | 70 | 0 (or 70) | IB 256 |
| PLC2 output to PLC1 | 0 (or 70) | 70 | QB 256 |
After download, verify in HW Config that the DP slave diagnostic buffer reports "DP slave is in data exchange" (SF LED off, BF LED off) on both masters before continuing.
Step 2: 70-Byte Consistent Transfer with SFC14 / SFC15
For consistent transfer of more than 4 bytes, the I/O read/write instructions SFC14 DPRD_DAT and SFC15 DPWR_DAT must be used. They bypass the standard process-image update and access the coupler slot directly, guaranteeing that all 70 bytes are transferred atomically with respect to the OB1 cycle.
Network 1 - read 70 bytes from PLC1's input slot into DB1.Inputs:
CALL "DPRD_DAT"
LADDR := W#16#100 // 256 decimal = coupler input slot start
RET_VAL:= MW100 // 0 = OK, see error table below
RECORD := P#DB1.DBX0.0 BYTE 70
Network 2 - write 70 bytes from DB1.Outputs to PLC1's output slot:
CALL "DPWR_DAT"
LADDR := W#16#100 // 256 decimal = coupler output slot start
RECORD := P#DB1.DBX70.0 BYTE 70
RET_VAL:= MW102
Note that RECORD uses an any-pointer with explicit byte count. For 70 bytes, the LADDR must match the start of the configured I or Q range in HW Config (hex 100 = decimal 256). RET_VAL codes 0000h = OK, 8090h = address error, 8092h = segmented error. See the Siemens FAQ on I/O data configuration of the DP/DP Coupler (entry ID 19281019) for length limits per slot.
Step 3: Byte Forwarding - Why BLKMOV Trips Up the Compiler
The original test project attempted to use SFC20 BLKMOV with a 1-byte source from a 1-byte register tag and a destination pointer to DB2. Compiler complaints and runtime confusion come from three sources:
- Size mismatch in the ANY pointer. The source ANY in Network 3 was declared as a pointer to a 1-byte register, but the destination ANY was declared as a full DB reference. SFC20 requires both ANYs to encode an explicit byte count that matches the actual data length. A full DB ANY defaults to its entire declared length, not 1 byte.
-
Byte-level vs. word-level pointer granularity. SFC20's SRCBLK and DSTBLK parameters accept the form
P#DBx.DBByyy.b BYTE n. OmittingBYTE nor usingWORDfor a single byte causes STEP 7 to interpret the source as 2 bytes and silently extend the read into the next byte. -
Symbolic-only addressing. If DB2 is declared "optimized" (S7-1500) or accessed with a fully symbolic tag, the absolute pointer
P#DB2.DBX0.0 BYTE 1may not be accepted without an AT view.
For a single byte, the simplest and safest solution is the MOVE box (LAD/FBD) or the STL pair L B#16#?? T "DB_Buffer".Recv_byte. BLKMOV is only useful when the byte count exceeds 1 or when the source/destination crosses a word boundary that MOVE cannot handle atomically.
Step 4: Implementing the Byte Forward (MOVE Preferred)
Network 3 - forward byte 69 from the received 70-byte input buffer into a single-byte variable that will be re-emitted to the peer:
// LAD
DB1.Inputs.Byte[69] MOVE DB2.Recv_byte
// Equivalent STL
L DB1.DBB69
T DB2.DBB0
Network 4 - write that forwarded byte (alongside the 70-byte process data) back to the peer via the same output slot. Two architectural options apply:
| Option | Approach | Risk |
|---|---|---|
| A: Append at the tail of the 70-byte block | Place the forwarded byte at DB1.Outputs[70] and extend the DPWR_DAT record length to 71 bytes on both sides. |
Both sides must agree on the extended length; the DP/DP Coupler must be reconfigured. |
| B: Replace a byte within the existing 70-byte block | Use MOVE to copy DB2.Recv_byte into DB1.Outputs[k] before SFC15 is called. |
None - same SFC15 call, same slot length, the byte is just updated in the source DB. |
Option B is recommended because it does not change the DP/DP Coupler configuration and avoids the "simultaneous writing" concern raised in the original post. There is no collision as long as Network 3 (MOVE) executes before Network 4 (SFC15 DPWR_DAT) within the same OB1 scan, because the source DB is updated before the consistent write occurs.
// Full Network sequence (OB1, cycle)
Network 1: SFC14 // read 70 bytes from coupler into DB1.Inputs
Network 2: MOVE // copy forwarded byte from DB1.Inputs[69] -> DB2.Recv_byte
Network 3: MOVE // copy DB2.Recv_byte -> DB1.Outputs[3] (or any position)
Network 4: SFC15 // write 70 bytes from DB1.Outputs to coupler
Step 5: Resolving the "Simultaneous Writing" Question
The original poster correctly identified that two different instructions writing the same I/O address range in the same cycle can cause a PROFIBUS data collision warning in the diagnostic buffer. The DP/DP Coupler does not arbitrate writes from the same PLC; it simply forwards the last consistent image received from the master. If Network 2 (SFC15 with 70 bytes) and Network 4 (SFC20 with 1 byte) both target the same starting PAW 256 area, the second call overwrites the first within the OB1 cycle, and the bus will carry whichever value was committed last.
The fix is to consolidate all output bytes into one source DB and emit them with a single SFC15 call per cycle. Single-byte forwarding becomes a pre-write MOVE into the source DB, not an additional SFC call against the hardware address.
Step 6: Pointer Forms and Byte-Level Addressing
The exact byte-level ANY pointer accepted by SFC14/SFC15/SFC20 in STEP 7 V5.5:
| Parameter | Acceptable form | Example |
|---|---|---|
| SRCBLK / DSTBLK | P#[Area]x.DB[DB#]y[.bit] BYTE n | P#DB1.DBX0.0 BYTE 70 |
| SRCBLK / DSTBLK (bit-granular) | P#DB1.DBX0.0 BIT 8 | P#DB1.DBX10.3 BIT 8 |
| LADDR | WORD (hex IO address) | W#16#100 (= 256 dec) |
For a 1-byte source/destination, the cleanest form is:
P#DB1.DBX69.0 BYTE 1 // single byte at offset 69 of DB1
P#DB2.DBX0.0 BYTE 1 // single byte at offset 0 of DB2
If you use a symbolic tag such as "Buffer_DB".Recv_byte in a S7-300/400 standard DB, the compiler resolves it to the same absolute pointer at download time. S7-1500 optimized DBs require either an AT view returning a BYTE or the use of MOVE_BLK with VARIANT inputs.
Step 7: Verification and Diagnostic Checks
- Online > Monitor/Modify DB1.Inputs[0..69] in PLC1 and confirm that toggling a bit in PLC2's DB1.Outputs is reflected within one PROFIBUS cycle (~5 ms at 1.5 Mbaud, ~1 ms at 12 Mbaud).
- Inspect
RET_VALof both SFC14 and SFC15 in the VAT; it must read 0000h. A non-zero value with bit 15 set (negative) indicates a coupler-side fault - see the Siemens FAQ on special features of I/O addressing with the DP/DP Coupler (entry ID 22327981). - Open the DP slave diagnostic buffer on PLC1 (right-click the DP/DP Coupler in HW Config > "DP Slave Diagnostics"). The entry "Configuration OK / Data exchange entered" must be present, with no entries flagged "Configuration fault" or "Station failure".
- Force
DB2.Recv_bytein PLC1 to 16#AA, then verify the corresponding byte in PLC2's DB1.Inputs reflects 16#AA within one cycle. - Disconnect one PROFIBUS connector: the BF LED on the affected side must illuminate, and the diagnostic buffer must record a station failure. Reconnect and confirm auto-recovery without PLC stop.
RET_VAL Error Code and Troubleshooting Matrix
| RET_VAL (hex) | Meaning (SFC14/15) | Typical cause / action |
|---|---|---|
| 0000 | No error | - |
| 8090 | Address error: LADDR does not match a configured I/O area | Wrong slot start in HW Config or download mismatch |
| 8092 | Segmented error: ANY pointer crosses a segment boundary | RECORD pointer to P#DB1.DBX60.0 BYTE 20 when DB1 length is 64 |
| 8093 | Length error in LADDR / RECORD | RECORD length exceeds the configured slot length |
| 80A0 | Access error: module removed or faulty | PROFIBUS cable break, coupler power loss |
| 80B0 | DP slave not in data exchange | Configuration mismatch between the two masters |
| 80B1 | Target slot inconsistent | Length on one master differs from the other |
| 80B2 | DP slave reports "not ready" | Coupler diagnostic buffer fault |
| Symptom | Likely cause | Action |
|---|---|---|
| BF LED solid on one side, flashing on the other | PROFIBUS cable swap or missing termination | Check A/B line polarity; ensure terminating resistor ON at both line ends only |
| BF off, but SFC15 RET_VAL = 8093 | Output slot length on this master is 0 bytes | Reconfigure HW Config with non-zero output length, redownload both stations |
| 70 bytes transfer correctly, single byte always reads 0 | MOVE placed after SFC15 in OB1 - too late in cycle | Reorder networks: MOVE -> SFC15 |
| Diagnostic buffer shows "Configuration fault" on PLC2 | Length mismatch: PLC1 sends 70, PLC2 expects 71 | Reconcile slot length on both masters; only one length is allowed per direction |
| Compiler rejects ANY pointer in SFC20 | DB2 is "optimized" (S7-1500) or pointer is symbolic only | Use absolute pointer P#DB2.DBX0.0 BYTE 1 or add an AT view returning BYTE |
| Single byte toggles but 70-byte block reads garbage after a STOP/RUN | Initial values of DB1.Inputs not zeroed | Initialize DB1 with desired preset in OB100 (restart OB) |
Field-Proven Caveats and Commissioning Notes
- Cycle order is mandatory. Always execute input read (SFC14), then any in-PLC forwarding (MOVE / BLKMOV), then output write (SFC15). Reversing the order produces one-cycle-old data on the forwarded byte.
- OB1 vs. OB35 placement. If the bulk transfer is moved to a cyclic interrupt (OB35) for deterministic timing, the byte forward must move to the same OB or be guarded by a "data valid" flag; otherwise the read may interleave with the write.
- Consistency in the peer DB. Mark DB1 and DB2 as "non-optimized, standard" in the DB properties. Optimized access on S7-1500 hides the absolute offsets that the SFC pointers require.
- Symmetric vs. asymmetric I/O. The DP/DP Coupler supports asymmetric I/O (for example 70 bytes in / 4 bytes out). Asymmetric configurations remain consistent in each direction, but the slot lengths on the two masters must match in the same direction (input on PLC1 = output on PLC2 and vice versa).
- Diagnostic buffer pollution. SFC14 RET_VAL = 80A0 (access error) after a power cycle on the peer PLC is normal for the first scan; clear the diagnostic buffer after warm restart to avoid masking real faults.
For the authoritative coupling rules and the maximum payload per side, refer to the Siemens DP/DP Coupler manual (entry ID 1179382).
Frequently Asked Questions
Can I use SFC20 BLKMOV to write a single byte to a DP/DP Coupler output address?
Technically yes, but it bypasses the consistency guarantees of SFC15 DPWR_DAT and is the most common source of sporadic bus errors and "Configuration fault" entries. Use SFC15 for the entire configured output range and copy the single byte into the source DB with a MOVE box before the SFC15 call. This is the only field-proven pattern for mixed-width transfer.
What is the maximum payload per direction on a DP/DP Coupler?
The DP/DP Coupler (6ES7158-0AD01-0XA0) supports up to 244 bytes of input and 244 bytes of output per side, with the total of input + output per side not exceeding 488 bytes. For larger payloads, use an IE/PN coupler or a PROFINET IO router instead.
Why does SFC20 BLKMOV with a 1-byte source still need a BYTE-typed ANY pointer?
The ANY pointer encodes the data type and length. If you declare the source as a WORD or INT but only need one byte, the SFC reads two bytes from the source and writes them as one byte to the destination, corrupting the next memory location. Always specify BYTE 1 explicitly: P#DB1.DBX69.0 BYTE 1.
Do I need the same input length on PLC1 as the output length on PLC2?
Yes, but only in the matching direction: the bytes that PLC1 reads as inputs (LADDR on SFC14) must equal the bytes that PLC2 writes as outputs (RECORD on SFC15 in PLC2), and vice versa. The absolute address (256 vs. 300) does not need to match - only the byte count.
My forwarded byte is always one cycle behind - why?
You are copying it into the output DB after SFC15 has already pushed the output image to the coupler. Move the MOVE instruction (or BLKMOV) to a network that executes before the SFC15 call within the same OB1 cycle. The peer will then receive the updated byte on the next bus cycle, not the cycle after that.