meta data for this page
  •  

This is an old revision of the document!


Direct / indirect addressing

Addressing methods are mostly tied to variable types, not areas, so the following procedures apply to both DB and Tag variables.

Direct addressing

Direct addressing in Simatic is typically symbolic addressing, meaning in the simplest case we correspond two variables of the same type to each other:

fromReal : Real;    
fromInt : Int;
toReal : Real;
toInt : Int;
…
 
#toInt := #fromInt;
#toReal := #fromReal;

If the types do not match, conversion will help us:

#toInt := REAL_TO_INT(IN := #fromReal);

It is crucial to understand that conversion can lead to data loss. In the example above, the REAL type can store much larger numbers and fractional parts, while the INT only handles smaller integers and rounds off fractions. When converting between variables with different ranges, all values outside the smaller range should be considered. In this case, rather than using an INT, a variable with a broader range should be selected (example DINT, LINT).

Direct addressing is also applicable to STRUCTURE and ARRAY types, as long as both sides have identical structures.

Another approach is direct addressing, which involves referring to sub-elements of a variable. Although this method applies to a limited range of variables, it is a simple form of assignment. While it isn't as straightforward as the S7-Classic AT command that many programmers prefer, it is at least available:

Slice addressing

Slice addressing involves dividing a memory region, such as a byte or word, into smaller segments like booleans. With S7-1200 and S7-1500, you can target specific parts within declared variables (only by byte, word, dword) and access segments of 1, 8, 16, or 32 bits.

Slice addressing TIA Portal

The following example is a SPLIT function that splits a WORD Input variable into bits:

// FC Input : inWord (Word)
// FC output: 16 variable bit0..bit15 (Bool)
// splitting
#bit0 := #inWord.%X0;
#bit1 := #inWord.%X1;
#bit2 := #inWord.%X2;
#bit3 := #inWord.%X3;
#bit4 := #inWord.%X4;
#bit5 := #inWord.%X5;
#bit6 := #inWord.%X6;
#bit7 := #inWord.%X7;
#bit8 := #inWord.%X8;
#bit9 := #inWord.%X9;
#bitA := #inWord.%X10;
#bitB := #inWord.%X11;
#bitC := #inWord.%X12;
#bitD := #inWord.%X13;
#bitE := #inWord.%X14;
#bitF := #inWord.%X15;

Pointer; indirect addressing

In the TIA Portal, there are two ways to perform indirect addressing or pointer referencing: the ANY and the VARIANT. However, it is important to note that the S7-1200 series PLCs do not support the ANY method. Using a pointer essentially involves moving a data block of a specific size to a memory area of the same size. This operation ignores the structure and variables within the data area, making it a quick and useful method when applied carefully. However, careless use of this tool can be very risky.

A key issue is that it doesn't handle the variables within the data being pointed to; for example, when searching for errors with xref, these procedures are not visible to the compiler, which can lead to difficult-to-detect errors caused by improper pointer use.

ANY type

Structure of the ANY Pointer (10 Bytes):

NameLengthDescription
Syntax ID1 byteAlways 16#10 for S7
Data Type1 byteCode for the type of data being pointed to (e.g., 16#02 for Byte; see bellow in the table “TIA Coding of data types”
Repetition Factor2 bytesNumber of elements of the specified data type
DB Numbe2 bytesThe number of the data block (0 if not in a DB)
Memory Area1 byteCode for the memory area (e.g., 16#84 for DB; see bellow in the table “TIA Coding of the memory area”)
Address3 bytesThe start address of the data (bit and byte address)
TIA Coding of data types

The following table lists the coding of data types for the ANY pointer:

Hexadecimal codeData typeDescription
B#16#00NILNull pointer
B#16#01BOOLBits
B#16#02BYTEbytes, 8 bits
B#16#03CHAR8-bit characters
B#16#04WORD16-bit words
B#16#05INT16-bit integers
B#16#06DWORD32-bit words
B#16#07DINT32-bit integers
B#16#08REAL32-bit floating-point numbers
B#16#0BTIMETime duration
B#16#0CS5TIMETime duration
B#16#09DATEDate
B#16#0ATODDate and time
B#16#0EDTDate and time
B#16#13STRINGCharacter string
B#16#17BLOCK_FBFunction block
B#16#18BLOCK_FCFunction
B#16#19BLOCK_DBData block
B#16#1ABLOCK_SDBSystem data block
B#16#1CCOUNTERCounter
B#16#1DTIMERTimer
2026/01/16 12:40 · vamsan
TIA Coding of the memory area

The following table lists the coding of the memory areas for the ANY pointer:

Hexadecimal codeAreaDescription
B#16#80PI/O
B#16#81IMemory area of inputs
B#16#82QMemory area of outputs
B#16#83MMemory area of bit memory
B#16#84DBXData block
B#16#85DIXInstance data block
B#16#86LLocal data
B#16#87VPrevious local data
2026/01/16 12:51 · vamsan
Example of using the ANY type

The pointer with the ANY type is most frequently used with the BLKMOV command, which copies data from one area to another indirectly. In the example below, the created data set is transferred to one of three mobile data areas, based on the location of the variable “assHMI”.Panel1ASS points:

CASE "assHMI".Panel1ASS OF
    1:  // ASS1 data to disp 1
        #state := BLKMOV(SRCBLK := P#db108.dbx0.0 BYTE 72, DSTBLK => P#db108.dbx216.0 BYTE 72);
    2:  // ASS1 data to disp 2
        #state := BLKMOV(SRCBLK := P#db108.dbx72.0 BYTE 72, DSTBLK => P#db108.dbx216.0 BYTE 72);
    3:  // ASS1 data to disp 3
        #state := BLKMOV(SRCBLK := P#db108.dbx144.0 BYTE 72, DSTBLK => P#db108.dbx216.0 BYTE 72);
    ELSE  // Statement section ELSE
        ;
END_CASE;

VARIANT type