Overview: PIW/PQW Addressing in the S7 Memory Model
Process-input words (PIW) and process-output words (PQW) are the peripheral I/O image areas of the SIMATIC S7-300 and S7-400 CPU families. Unlike IW and QW (inputs/outputs image), the peripheral area is read or written directly to the I/O backplane on every bus cycle, bypassing the process-image update. PIW and PQW addresses are always 16-bit aligned, so PIW 128 occupies byte 128/129 of the peripheral input area (PII), while PQW 128 occupies byte 128/129 of the peripheral output area (PIQ).
Because the data unit the CPU reads or writes in a single cycle is 16 bits, the data type most engineers first associate with a PIW or PQW is INT (16-bit signed integer) or WORD (16-bit bit pattern, unsigned). In STEP 7 V5.x, however, the address remains a WORD-length cell regardless of the symbolic data type you assign. This causes the common confusion at the center of the original question: declaring a symbol as INT and tying it to a PIW works for math instructions, but declaring the same symbol as WORD blocks it from being passed to the SCALE block's INT input.
| Address | Area | Width | Update | Common Use |
|---|---|---|---|---|
| PIW / PEW | Peripheral inputs | 16 bits | Direct, every OB1 scan or PPO read | Analog input raw value |
| PQW / PAW | Peripheral outputs | 16 bits | Direct, every OB1 scan | Analog output raw value |
| IW / EW | Process-image input | 16 bits | At OB1 entry (or PIP) | Digital and analog input snapshot |
| QW / AW | Process-image output | 16 bits | At OB1 exit | Digital and analog output snapshot |
| PID / PED | Peripheral inputs | 32 bits | Direct | Counter/encoder words |
| PQD / PAD | Peripheral outputs | 32 bits | Direct | 32-bit analog modules |
Why a PIW/PQW Cell Is Always a WORD-Length Cell
The peripheral I/O area is mapped 1:1 onto the I/O modules in the rack. A 4-channel SM 334 analog input module, for example, occupies PIW 288..295 (four 16-bit words). A SM 332 8-channel analog output module occupies PQW 304..319. The cell size is fixed by the hardware and the slot configuration in HW Config; STEP 7 does not store a data type with the address itself, only with the symbol that references it.
When you read L PIW 128 in STL, the accumulator's low word is loaded with the 16-bit value. When you read L PID 288, the entire 32-bit accumulator is loaded. The CPU does not check whether the programmer treats the result as signed (INT) or as a bit string (WORD) — that decision is enforced only by the editor's type check and by the IEC 61131-3 data-type rules of the block being called.
INT vs WORD: Where the Type Check Fires
STEP 7's LAD/FBD editor enforces strict data-type compatibility at the parameter boundary of a block call. The default setting, controlled by Options > Customize > LAD/FBD > "Type Check of Address", is enabled. With the checkbox enabled:
- A
PIWsymbol declared asINTis accepted at any block input declared asINTorWORD(INT is the more restrictive of the two). - A
PIWsymbol declared asWORDis rejected at anINTinput (e.g., theINof FC105 SCALE) but accepted at anyWORDorDWORDinput. - A
PIWsymbol declared asREALis rejected outright — the cell is 16 bits wide, not 32.
The same rule applies in reverse to the double-word case: a PID/PQD symbol declared as DINT is accepted where a DINT parameter is expected, while a DWORD symbol is rejected at a DINT parameter. The underlying value is identical; only the editor's interpretation differs.
Unchecking Type Check of Address disables the warning. This is a quick escape hatch for legacy code, but it is not recommended because the compiler will then quietly accept an INT symbol where a WORD was intended, masking sign-extension bugs. For example, the value 16#8000 is +32768 as a UINT but -32768 as INT — the wrong sign can cause a SCALE block to drive the output negative when the input is at the upper rail of a unipolar 4–20 mA module.
Recommended Symbol Declarations for Analog I/O
For STEP 7 V5.5 / TIA Portal V13 and later, the recommended practice is to declare the symbol that points to a PIW or PQW as the data type that matches the block you are going to feed. The two dominant cases are:
| Use Case | Recommended Symbol Type | Reason |
|---|---|---|
| Direct to FC105 SCALE / FC106 UNSCALE | INT (signed 16-bit) | FC105 IN and FC106 OUT are typed as INT |
Pass to a bit-test instruction (e.g., A, AN, L with WXOR) |
WORD | Word operations ignore sign and are bit-mask safe |
| Long-term storage of raw value in a data block | INT (after type conversion) | Matches scaled engineering value; easier to scale later |
| Hand-off to a non-Siemens field device over PROFINET or PROFIBUS DP using SFC14/15 | WORD or array of WORD | Consistent record framing; conversion to INT inside the FB |
If the same PIW must be read in two contexts — once for scaling and once for a bit test on a fault-flag bit — declare two separate symbols pointing to the same address. STEP 7 allows multiple symbols to reference a single absolute address; the symbol is just a label, the address is the underlying cell. A common naming convention is AI_RAW_PIW128 (INT) for the scaled path and AI_RAW_WORD_PIW128 (WORD) for the bit-test path. The second symbol still compiles to the same address; you are not duplicating the I/O read.
Working with FC105 SCALE and FC106 UNSCALE
FC105 SCALE accepts a 16-bit integer at IN and produces a 32-bit REAL at OUT, scaled between LO_LIM and HI_LIM. FC106 UNSCALE performs the inverse. Both blocks are part of the Standard Library > TI-S7 Converting Blocks in STEP 7 V5.x. The full parameter set is shown below.
| Parameter | Type | Range / Unit | Description |
|---|---|---|---|
| IN (FC105) | INT | −27648 to +27648 (bipolar) or 0 to 27648 (unipolar) | Raw input from PIW |
| HI_LIM | REAL | Engineering high (e.g., 100.0 bar) | Value at IN = 27648 |
| LO_LIM | REAL | Engineering low (e.g., 0.0 bar) | Value at IN = 0 (or −27648 bipolar) |
| BIPOLAR | BOOL | 0 = unipolar, 1 = bipolar | Selects scale type |
| OUT | REAL | LO_LIM ≤ OUT ≤ HI_LIM | Engineering value |
| RET_VAL | WORD | 0 = OK, 80A0 = overflow, 80A1 = underflow | Status output |
Because the IN parameter is INT, the symbol passed to it must be INT (or a temporary variable of type INT in the calling block). Passing a WORD symbol directly is rejected when the type check is on. The cleanest fix is to either:
- Re-type the symbol to
INTin the symbol table, or - Insert a
WORD_TO_INTconversion (FC33) on the rung in front of the SCALE block. This is the recommended approach when the same raw value is needed elsewhere as a WORD.
STL Snippet: WORD PIW -> INT -> SCALE
// Raw PIW (declared WORD in the symbol table) is bit-tested
// and the same value is fed to FC105 as INT
A "AI_FAULT_BIT"; // WORD symbol on PIW 128, bit 7
JC FAU; // jump to fault handler
L "PIW_RAW_W"; // WORD symbol on PIW 128
ITD ; // INT -> DINT (sign-extend)
DTR ; // DINT -> REAL
// ... or simply:
L "PIW_RAW_W"; // load WORD
T #wRaw; // move to a static INT in the FB
CALL FC105
IN := #wRaw
HI_LIM := 1.000000e+002
LO_LIM := 0.000000e+000
BIPOLAR := FALSE
RET_VAL := #wFC105Status
OUT := #rEngValue
NOP 0;
Procedure: Changing the Type-Check Behavior
- Open the LAD/FBD/STL editor in STEP 7 V5.x.
- From the menu bar, choose Options > Customize.
- Select the LAD/FBD tab.
- Toggle the Type Check of Address checkbox. Default is enabled.
- Click OK and recompile the affected blocks.
Procedure: Wiring a Symbol to FC105 via the Symbol Table
- In the symbol table, ensure the row for the analog input symbol is declared as
INT(notWORD). Use a name likeAI_RAW_PIW128with the addressPIW 128. - Open the FC or FB that calls FC105. From the library tree on the right, drag FC105 onto a network.
- At the
INinput, type the symbolic nameAI_RAW_PIW128. With the type check on, this passes because the symbol is INT. - Wire
HI_LIM,LO_LIM,BIPOLAR, andRET_VALto local variables (e.g.,#rEngValue,#wFC105Status). - Save the block and download to the CPU.
Address Layout Examples for Common Analog Modules
| Module | Order Number | Slot | Address Range | Resolution |
|---|---|---|---|---|
| SM 331 AI 8x12 bit | 6ES7 331-7KF02-0AB0 | 4 | PIW 288..303 (4 used, 4 reserved) | 0…27648 unipolar / ±27648 bipolar |
| SM 331 AI 2x14 bit | 6ES7 331-7NB00-0AB0 | 4 | PIW 288..291 | ±27648 bipolar only |
| SM 332 AO 4x12 bit | 6ES7 332-5HD01-0AB0 | 5 | PQW 304..311 | 0…27648 or ±27648 |
| SM 334 AI 4/AO 2 x12 bit | 6ES7 334-0CE01-0AA0 | 4 | PIW 288..295 / PQW 304..307 | Mixed |
| SM 335 AI 4/AO 4 x14 bit | 6ES7 335-7HG01-0AB0 | 4 | PIW 288..295 / PQW 304..311 | ±27648, configurable |
Always confirm the actual addressing in HW Config > Module Properties > Addresses because slot numbers, slot-priority, and the start address assigned by STEP 7 are user-configurable. Mismatched addresses are a far more common commissioning fault than data-type mismatches.
FC105 and FC106 Status Words (RET_VAL)
Always wire the RET_VAL output to a WORD variable and check it in the calling block. A non-zero value indicates the input is outside the scaled window. A non-zero RET_VAL does not mean the block has failed — the OUT value is still written; it is clamped to LO_LIM or HI_LIM.
| RET_VAL | Meaning | Field Action |
|---|---|---|
| W#16#0000 | OK | None |
| W#16#80A0 | IN > 27648 (over-range) or bipolar > 27648 | Alarm to HMI; check sensor scaling; verify input channel is not open-circuit on a 4–20 mA loop |
| W#16#80A1 | IN < 0 (unipolar) or IN < −27648 (bipolar) | Alarm to HMI; check wiring polarity and 24 V supply |
Why Not Use a TEMP Variable Instead of the Symbol?
The cleanest engineering approach is to read the PIW once at the top of the calling block into a TEMP or STAT variable, then use that local variable for every subsequent operation. This decouples the rest of the program from the absolute address and makes the data type explicit at the variable declaration:
// FB "AI_Scaling" — declaration section
VAR
iRaw : INT; // raw count from PIW
wRaw : WORD; // alternative for bit tests
rEng : REAL; // engineering value
wStatus : WORD; // FC105 RET_VAL
bFault : BOOL; // latched alarm
END_VAR
// Implementation
L "AI_RAW_PIW128"; // symbol declared INT, no conflict
T #iRaw;
CALL FC105
IN := #iRaw
HI_LIM := 1.0e2
LO_LIM := 0.0e0
BIPOLAR := FALSE
RET_VAL := #wStatus
OUT := #rEng;
A L 0; // test the sign of RET_VAL
JC Fault;
// ... rEng is now safe to use downstream
This pattern eliminates the INT/WORD symbol choice from the calling site entirely: the symbol on the PIW is declared as INT, the value is moved to a local INT, and all scaling, alarming, and HMI hand-off logic operates on locals. The only place the data type matters is in the symbol table and the local declaration, and both are explicit.
DINT vs DWORD: The 32-Bit Extension of the Same Problem
The discussion thread explicitly notes that the same INT/WORD type-check issue exists for 32-bit peripherals (PID/PQD). A PID symbol declared as DWORD cannot be passed directly to a block input of type DINT when the type check is on. The fix is identical:
- Declare the symbol as
DINTif it feeds signed arithmetic, or - Insert a
DWORD_TO_DINT(FC30) conversion at the boundary, or - Read the
PIDinto aDINTlocal first.
32-bit peripherals are common on the ET 200S 4AI/HS counter modules and on PROFIBUS DP slaves configured with 32-bit consistency. The behavior is identical to the 16-bit case and the same type-check checkbox controls it.
Verification After a Symbol Type Change
- In the symbol table, confirm the new data type and recompile the entire S7 program (Program > Compile All in STEP 7 V5.x).
- Use PLC > Download to push the rebuilt program. Hardware configuration does not change.
- Go online with the CPU (PLC > Monitor/Modify). Open the FC/FB that calls FC105 and watch the
INvalue. Verify it tracks the HMI raw count. - Force a known input (e.g., a 4 mA loop or a precision 24 V source on a voltage channel). Confirm
rEngequals the calculatedLO_LIMand thatwStatusremains W#16#0000. - Sweep the input to the upper rail and verify the
wStatusstays zero until the input exceeds 27648 counts (unipolar) or 27648 in absolute value (bipolar).
Troubleshooting Matrix
| Symptom | Likely Cause | Resolution |
|---|---|---|
| FC105: "Type incompatibility of input IN" | PIW symbol declared WORD, IN expects INT | Re-declare as INT or add WORD_TO_INT |
| FC105: RET_VAL = 80A0 at any input above 4 mA | Unipolar mode with bipolar input; or sign error | Set BIPOLAR = FALSE; check INT vs WORD interpretation |
| Symbol name shows in the editor but value = 0 | Symbol table change not propagated to block | Close and reopen the calling block; recompile |
| SCALE output is negative on a 4–20 mA loop | PIW symbol declared WORD interpreted as INT bit pattern | Force type check on, declare symbol as INT, recompile |
| Symbol table "Address already in use" on save | Two symbols pointing to the same PIW with different data types | Use unique symbol names; only the address needs to be unique, not the symbol itself |
| FC105 instance shows red X after download | Type check disabled in project settings but enabled on the block | Re-enable type check, re-download, reset CPU |
Best-Practices Summary
- Declare the symbol that points to a
PIWorPQWasINTwhen the value is going to be scaled, compared, or otherwise treated as a signed number. - Declare a second symbol as
WORDon the same address if a bit test is also needed. Multiple symbols on one address are legal in STEP 7. - Never disable Type Check of Address for production code. Use it as a temporary migration tool only.
- Always wire
RET_VALof FC105/FC106 to a WORD variable and alarm on W#16#80A0 / 80A1. - Where possible, copy the raw value to a local
INTorDINTat the top of the calling block and operate on the local thereafter. This decouples the rest of the program from the absolute address. - Confirm module addressing in HW Config before assuming PIW 128 is the first analog input. Slot order and start address are user-configurable.
Should I declare a PIW or PQW symbol as WORD or INT?
Declare the symbol as INT when the value will be scaled, compared, or treated as a signed number (for example, the IN input of FC105 SCALE). Declare a second symbol as WORD on the same address if a bit test is also required. The peripheral cell is always 16 bits wide regardless of the symbol type, so the choice is purely about which editor check the symbol should satisfy.
Why does the SCALE block reject my PIW symbol even though the address is correct?
FC105 SCALE declares its IN parameter as INT. When the symbol table entry is typed as WORD, the LAD/FBD editor's type check blocks the connection with a "type incompatibility" message. Either change the symbol's data type to INT, or insert a WORD_TO_INT (FC33) conversion in front of the SCALE call.
Does disabling the Type Check of Address fix the FC105 problem?
Yes, it removes the compiler error, but it is not recommended for production code. Disabling the check also masks genuine type errors, such as passing a WORD to a BCD input, and can cause SCALE blocks to misbehave when a value of 0x8000 is interpreted as either 32768 (WORD) or -32768 (INT). Re-enable the check and fix the symbol type at the source instead.
Can two symbols point to the same PIW with different data types?
Yes. STEP 7 allows multiple symbol-table entries to reference one absolute address. A common convention is AI_RAW_PIW128 (INT) for the scaled path and AI_RAW_W_PIW128 (WORD) for bit-test paths. The address is what the CPU reads, and the symbol is just a label and a type hint at the call site.
Does the same INT/WORD issue apply to 32-bit peripherals like PID and PQD?
Yes, the editor enforces the same rule at the wider width. A PID symbol declared as DWORD cannot be passed directly to a DINT input when the type check is on, and the fix is the same: re-declare as DINT, use DWORD_TO_DINT (FC30), or copy the PID value into a DINT local at the top of the calling block.