SCL AND Operator Bit Masking Explained in TIA Portal

David Krause13 min read
SiemensTechnical ReferenceTIA Portal
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

SCL AND Operator Bit Masking Explained in TIA Portal

When you encounter legacy SCL code such as IF (Byte_To_Bool(value) AND 1) THEN ... END_IF;, the literal expression AND 1 can confuse engineers transitioning from LAD/FBD or from other IEC 61131-3 dialects. The expression is not an address reference, it is a bit-mask operation. This reference explains the semantics of AND in SCL, the role of the constant 1 as a binary mask, the interaction with the Byte_To_Bool conversion, and the recommended idioms for bit extraction in SIMATIC S7-1200 and S7-1500 controllers programmed with TIA Portal.

Target audience. Commissioning engineers, service technicians, and PLC programmers who maintain or modernize SCL blocks in TIA Portal V15..V19 and need a defensible interpretation of bit-mask logic inside IF and WHILE constructs.

1. Overview of SCL and the AND Operator

Structured Control Language (SCL) is Siemens' high-level, Pascal-derived implementation of the IEC 61131-3 ST (Structured Text) language. It is fully integrated into TIA Portal and supported on S7-300/400 (with restrictions), S7-1200, S7-1500, ET 200SP CPUs, and the WinAC RTX platform. SCL expressions and operations are documented in the SIMATIC S7-1200 manual collection, which states that the SCL control statements include IF-THEN, CASE-OF, FOR-TO-DO, WHILE-DO, REPEAT-UNTIL, CONTINUE, GOTO, and RETURN, and that a single statement typically occupies one line within a block (Siemens TIA Portal Docs - SCL Expressions and Operations).

The bitwise AND operator is a first-class element of SCL and follows IEC 61131-3 semantics. It performs a bitwise logical conjunction on two integer operands. The result type is the wider of the two operand types. When the right-hand operand is the integer literal 1, the operation isolates the least-significant bit of the left-hand operand. This is the foundation of every bit-mask test in SCL.

The key SCL syntax forms for a single-bit test are listed below. All four statements are semantically equivalent for the data types BOOL, BYTE, WORD, and DWORD when the bit under test is bit 0:

Table 1 — Equivalent SCL syntaxes for testing bit 0 of a value
Syntax form Type of right operand Notes
IF (value AND 1) <> 0 THEN Integer literal Implicit conversion; classic idiom.
IF (value AND 2#1) <> 0 THEN Binary literal Self-documenting; bit position visible.
IF (value AND 16#01) <> 0 THEN Hexadecimal literal Compact; one hex digit per nibble.
IF value.%X0 THEN Bit slice S7-1500 only; no operator required.
IF Byte_To_Bool(value) THEN Standard function Returns LSB only (see §5).

2. Bit Masking Fundamentals in SCL

A bit mask is a constant whose binary representation contains 1s exactly in the positions you want to keep and 0s everywhere else. The AND operator applies that mask to an integer value, producing a result that is non-zero if and only if at least one of the masked positions is set in the source value.

For the mask 1 (binary 2#0000_0001), only bit 0 survives. The truth table for an 8-bit operand is shown below:

Table 2 — Truth table: x AND 1
x (hex) x (binary) x AND 1 Result is TRUE when
16#00 2#0000_0000 0 —
16#01 2#0000_0001 1 Bit 0 = 1
16#02 2#0000_0010 0 —
16#03 2#0000_0011 1 Bit 0 = 1
16#FE 2#1111_1110 0 —
16#FF 2#1111_1111 1 Bit 0 = 1

For a 16-bit operand the mask is still 1 because AND operates on the value, not on the data type. The other 15 bits of the source are masked out and contribute zero to the result.

2.1 Mask generation rules

To test bit n of an integer V, the canonical mask is 2 ** n or its equivalent literal form. The SCL compiler will fold this expression at compile time when both operands are constants, so no runtime cost is incurred. The patterns below all compile to a single-word load and bit-test on S7-1500:

// Test bit 0
IF (V AND 2#0000_0001) <> 0 THEN ... END_IF;
// Test bit 3
IF (V AND 2#0000_1000) <> 0 THEN ... END_IF;
// Test bit 7
IF (V AND 16#80) <> 0 THEN ... END_IF;
// Test bit 15
IF (V AND 16#8000) <> 0 THEN ... END_IF;

3. AND 1 vs AND 2#1 vs AND TRUE — Syntax Comparison

The SCL compiler accepts the right-hand operand of AND in any literal form that resolves to an integer. The three forms 1, 2#1, and 16#01 produce the same bit pattern and the same machine code. The form TRUE is also accepted, but its type is BOOL rather than an integer, and the SCL compiler performs an implicit conversion from BOOL to the left operand's integer type. The conversion rule is TRUE → 1 and FALSE → 0, which preserves the mask semantics.

Compiler quirk. Some TIA Portal versions (V15.0, V15.1) issue warning "Implicit conversion of BOOL to INT" in the block consistency check when AND TRUE is used. Resolve by replacing with an explicit integer mask such as 1 or 2#1. The warning does not affect generated code; it is a style hint.

3.1 Comparison table

Table 3 — Right-operand forms and their compiler behavior
Expression Type of 1 Compiler warning Generated code
value AND 1 INT literal None Single AND word op
value AND 2#1 INT binary literal None Identical to above
value AND 16#01 INT hex literal None Identical to above
value AND TRUE BOOL Possible implicit-conversion note Conversion + AND word op
value AND 16#FFFF INT hex literal None Identical mask, wider result

4. Address Reference Behavior in SCL

The question that motivated this reference is whether AND 1 could be a syntactically shortened form for addressing bit 550.1 in the input area. It cannot. SCL bit addressing is always written with a % qualifier (%I for input, %Q for output, %M for memory) and an explicit bit offset, for example %I550.1 or, in TIA Portal symbolic form, "IW550".%X1. The plain token 1 is the integer literal one, never an address fragment.

However, the appearance of 550 in the input image is not a coincidence. S7-1200 and S7-1500 CPUs place process-image inputs in word-aligned addresses. The identifier I550.0 refers to bit 0 of input byte 550, and I550.1 to bit 1 of the same byte. When legacy code reads Byte_To_Bool(IB550) it implicitly extracts bit 0, which is why the AND 1 mask in the surrounding IF looks redundant.

4.1 SCL bit-slicing syntax (S7-1500)

On S7-1500 CPUs with firmware V2.0 or later, SCL supports a typed bit-slice syntax that avoids the need for an explicit mask:

IF "DB_Modbus".StatusWord.%X0 THEN        // bit 0 of a WORD tag
   // ...
END_IF;

The .%X<n> accessor is not available on S7-1200 (firmware V4.x); on those controllers the bit-mask idiom remains the recommended approach. S7-300/400 SCL supports the older DBx.DBBy.%X<n> absolute form.

5. The Byte_To_Bool Function in SCL

Byte_To_Bool is a standard type-conversion function in the IEC 61131-3 library. It accepts a BYTE operand and returns the value of the least-significant bit as a BOOL. The semantics are identical to the expression (byte AND 1) <> 0. This is the reason the surrounding mask looks redundant: Byte_To_Bool has already reduced the byte to the LSB before the AND is evaluated.

Table 4 — Byte_To_Bool behavior on representative inputs
Input (BYTE) Binary Output (BOOL)
16#00 2#0000_0000 FALSE
16#01 2#0000_0001 TRUE
16#02 2#0000_0010 FALSE
16#55 2#0101_0101 TRUE
16#A0 2#1010_0000 FALSE
16#FF 2#1111_1111 TRUE

Because Byte_To_Bool returns BOOL, applying AND 1 to that result triggers the implicit BOOL-to-INT conversion mentioned in §3. The boolean TRUE becomes integer 1, and the mask 1 AND 1 remains 1 (non-zero, truthy). The boolean FALSE becomes integer 0, and 0 AND 1 is 0 (falsy). The net effect is a no-op identity, which is why the legacy code still works even though the mask is logically superfluous.

6. Bit Extraction Patterns and Best Practices

For new SCL code on S7-1200 and S7-1500, prefer the most readable form. The following examples demonstrate equivalent tests for bit 0 of a word tag named StatusWord:

// Pattern A — explicit mask, no conversion (recommended for S7-1200)
IF (StatusWord AND 2#0000_0001) <> 0 THEN
   // bit 0 is set
END_IF;

// Pattern B — bit slice (recommended for S7-1500, FW V2.0+)
IF StatusWord.%X0 THEN
   // bit 0 is set
END_IF;

// Pattern C — boolean conversion of a BYTE (legacy compatible)
IF Byte_To_Bool(LO_BYTE(StatusWord)) THEN
   // bit 0 of the low byte is set
END_IF;

// Pattern D — symbolic bit tag (TIA Portal optimized)
IF "Status_bit0" THEN
   // bit 0 mapped to a derived BOOL tag in the data block
END_IF;

6.1 Setting, clearing, and toggling bits

The AND operator is read-only. To modify a bit in place, combine AND (clear) and OR (set) with a mask, or use the dedicated SCL bit-slicing assignment syntax on S7-1500:

// Clear bit 3
WordTag := WordTag AND 16#FFF7;       // 16#FFF7 = 2#1111_0111_0111_0111

// Set bit 3
WordTag := WordTag OR  16#0008;

// Toggle bit 3
WordTag := WordTag XOR 16#0008;

// S7-1500 bit-slice assignment
WordTag.%X3 := TRUE;   // set
WordTag.%X3 := FALSE;  // clear
WordTag.%X3 := NOT WordTag.%X3;  // toggle

7. Common Pitfalls and Misinterpretations

The most frequent issues observed in the field are summarized below.

Table 5 — Pitfall matrix for SCL bit-mask logic
Pitfall Symptom Root cause Correction
Masking with a negative literal Compiler error or unexpected sign extension -1 is interpreted as INT and sign-extends to 32 bits Use 16#FFFF or cast with WORD#16#FFFF
Masking a signed INT tag Bit test result differs from expectation for negative values Two's-complement representation Cast to WORD or UINT before masking
Using AND on REAL Compiler error "Type conversion not possible" AND is integer-only Use TRUNC or move to DINT first
Confusing AND with & Syntax error in strict SCL mode & is C-style, not SCL Use only AND
Using AND on BOOL directly Warning, possible code bloat Bool already returns truthy Use IF b THEN directly
Wrong bit position IF triggers on the wrong input pattern Off-by-one in mask Use binary literal: 2#0000_1000 is bit 3
Implicit BOOL→INT on AND TRUE Compiler warning Implicit conversion Replace with integer literal 1

8. Verification and Testing Strategies

Before trusting legacy SCL code that contains AND <mask> constructs, run the following verification procedure in TIA Portal:

  1. Compile and check warnings. Project tree → right-click CPU → Compile > Software (rebuild all). Resolve every warning of class Implicit type conversion and Bit access not on %I/%Q/%M before continuing.
  2. Inspect the compiled STL. Right-click the SCL block → Generate source from blocks (or use Compare STL/FBD view). Confirm that the AND compiles to a single 16-bit or 32-bit logical AND. A multi-instruction sequence indicates an unintended type promotion.
  3. Trace the right operand. Use Go to definition on the literal to verify it resolves to an integer constant and not a tag named "1" in a global data block.
  4. Force and monitor. Load the block to the CPU, open the watch table, and force the source byte to 16#00, 16#01, 16#02, and 16#FF in turn. The IF branch must execute only when the LSB is set.
  5. Edge-detect with PLCSIM. In S7-PLCSIM V15 or later, add a sequence of transitions in the input image and record the OB1 scan-cycle count at which the IF evaluates to TRUE. The transition count must match the number of LSB edges in the test vector.
  6. Cross-check with LAD. Translate the SCL construct to an equivalent LAD network: ---[ IB550 AND 1 ]---( ) using a WAND_W (word AND word) box feeding a comparator. Both branches must produce identical results on the same input pattern.
  7. Document the intent. Add a header comment with the mask in binary form so that future maintainers do not need to re-derive the bit position, e.g. // AND 2#0000_0001 → tests bit 0 (LSB) of StatusByte.

9. Performance Considerations

On S7-1500 CPUs, a single AND against a constant mask is a one-cycle operation in the bit-instruction set. On S7-1200 CPUs (firmware V4.x), the same construct compiles to a load-immediate / AND-word / compare sequence of roughly 3 to 5 µs per call, depending on the data type width. Constant folding eliminates any runtime cost of the mask itself, so the only variable cost is the bit-test itself.

If the SCL code is inside a tight FOR loop that runs every OB1 cycle, prefer the bit-slice syntax on S7-1500 because it avoids the integer-to-bool conversion generated by Byte_To_Bool. The relevant benchmark on a CPU 1515-2 PN is approximately:

Table 6 — Approximate execution time per call (CPU 1515-2 PN, FW V2.9)
Form Instruction count Typical time
value AND 1 <> 0 3 ~0.045 µs
value.%X0 2 ~0.030 µs
Byte_To_Bool(value) AND 1 5 ~0.075 µs
Byte_To_Bool(value) 4 ~0.060 µs
Note. Times are from the Siemens instruction-list reference for S7-1500, FW V2.9. They scale with bus load, organization-block priority, and configured minimum cycle time. Use the S7-1500 Measuring point for runtime function (Tools > Task Card > Performance) to obtain a value specific to your project.

10. SCL Coding Standards and Style

The following style recommendations are taken from the SIMATIC S7-1200 manual collection and the SITRAIN course SIMATIC Programming 1 with SCL in TIA Portal (SITRAIN course page; see also the introductory walkthrough Writing your first SCL Code in TIA Portal for context on FB/FC structure and block interface design).

  • Always write the mask in binary or hexadecimal form unless the literal 1 is unambiguously the LSB.
  • Prefer the bit-slice syntax .%X<n> on S7-1500 because it removes the risk of mask typos and produces smaller STL.
  • Cast to an unsigned type before masking signed integers.
  • Comment the bit position in plain text above the test.
  • Extract named BOOL tags for frequently tested bits in the data block; this makes the SCL self-documenting and allows the HMI to subscribe to the same tag.

11. Cross-Reference: STL, LAD, and FBD Equivalents

Engineers familiar with LAD/FBD often find it easier to confirm the SCL semantics by translating the construct to another language. The table below shows the four equivalent representations for testing bit 0 of a word.

Table 7 — Cross-language equivalent: test bit 0 of MW100
Language Code
SCL IF (MW100 AND 2#0000_0001) <> 0 THEN "Bit0Set" := TRUE; END_IF;
STL L MW100
L 1
AW
JPZ ZERO
SET
= "Bit0Set"
ZERO:
LAD MW100 ---[ WAND_W 1 ]---[ <>0 ]---( "Bit0Set" )
FBD MW100 & WAND_W 1 ⇒ CMP <> 0 ⇒ AND "Bit0Set"

12. Frequently Asked Questions

What does AND 1 mean inside an SCL IF condition?

AND 1 is a bitwise conjunction with the integer literal 1 (binary 2#0000_0001). It tests whether bit 0 of the left operand is set; the result is non-zero if and only if the LSB is 1. It is not an address reference and has no connection to the input image address 550.1.

Is AND 1 the same as AND TRUE in SCL?

Yes, semantically. TRUE is implicitly converted to integer 1 by the SCL compiler. However, the conversion can trigger a warning in TIA Portal under Block consistency > Implicit type conversion. For clean builds, prefer the integer literal 1 or the binary literal 2#1.

Why does the legacy code use AND 1 after Byte_To_Bool when the conversion already returns the LSB?

The mask is logically redundant. Byte_To_Bool(x) returns the LSB as a BOOL; BOOL AND 1 then re-encodes the boolean as 1 or 0. The author likely wrote it for clarity or copied it from a word-mask idiom. It is safe to remove, and modernizing the code to the S7-1500 bit-slice syntax x.%X0 yields a smaller and faster block.

Can AND be used on a REAL tag in SCL?

No. AND is defined for integer types only (BOOL, BYTE, WORD, DWORD, SINT, INT, DINT, LINT, and their unsigned variants). For floating-point values, convert with TRUNC or REAL_TO_DINT first, or extract the IEEE-754 bit pattern with a AT-style overlay (S7-1500).

Which SCL form is best for testing a single bit on S7-1500 firmware V2.9?

Use the typed bit-slice syntax tag.%X<n>. It compiles to a single load-and-test sequence, is self-documenting, and avoids any type-conversion warnings. Reserve the explicit AND mask form for S7-1200 projects, for S7-300/400 SCL, or when the bit under test is computed at runtime.

Back to blog