Siemens STL syntax

ADoozer

Member
Join Date
May 2013
Location
Albury,NSW
Posts
40
Hi all.

First off, I would like to say this is an excellent forum I have been browsing anonymously for years.

Secondly, I am Rockwell to the core.

Anyway, some background:

I recently inherited a project (Siemens) where a particular FC is causing issues (The FC works perfectly fine as is, but needs a slight modification to accommodate a change required in the complete system). The FC was written initially in SCL, but since its compilation date (October 2008) the SCL file has been "lost". Unfortunately the archives on site and in the office only span back to 2009 and do not contain the file.

I have been trying to reverse engineer the code, with varying success. (I am using the Siemens Simatic Statement List (STL) for S7-300 and S7-400 programming refernce manual [6ES7810-4CA10-8BW1]) and have managed to partially write some SCL which generates segments of the STL.

I know what the FC does, I also know that it is using SFC20 (or possibly SFC81) to copy whole DBs (the FC is basically a FIFO controller with a few bells and whistles).

And now, the question.

The following bold lines have me stumped:-

L W#16#44C <-this is a reference to DB <1100> (the "empty" DB)
T LW 28 <- what is LW?
OPN DB [LW 28] <-we are now opening DB1100 as a shared DB
L DBW 0 <- load 0 into ACCU 1
T #Clear <- sets temp variable #Clear to 0
L #Blk_1_Nr <- previously set to (last DB - count DBs + 1 e.g. 1101)
T LW 28 <- what is LW?
L #Bw_1_Nr <previously set to 18ITD
L L#8 <- what is L# (8 is for * to get bytes in DB I think)
*D
OPN DI [LW 28] <- open DB1101 as an instance DB
LAR1 <- assume this is now the pointer to DB1101.DBX18.0
L DIW [AR1,P#0.0] <- fetches the DB status word
T #Value1 <- copy to temp variable #Value1
A L 10.1 <- i think this is comparing #value1.1 (log complete)
A L 10.2
<-
i think this is comparing #value1.2 (data ready)
JCN A7d0 <- conditional jump if RLO is 0

The pseudo code goes something like:

If DB<1101>.DBX18.1 (Log_Complete) AND DB<1101>.DBX18.2 (Data_Ready)
SFC20 (or possibly SFC81) SRC: DB1100, DST DB<1101>


I think I can probably work out the code if I could just figure out the syntax.

Can anybody shed some light or point me to a comprehensive STL manual.

Many thanks in advance

Dave
 
I am no STL expert but I should be able to offer some assistance.

LW stands for Local Word, if you look in the interface for the FC and go to the Temp Section LW 28 corresponds to two bytes beginning at address 28.

L#8 stands for Long data type of value 8 e.g. a double word. You can also tell this as the next line is *D which is a double word multiply by #Bw_1_Nr.

L10.1 and L10.2 are again referencing temp data but only a single bit.
 
LeiconJames

Thank you for the quick reply. Any help is greatly appreciated.

I had a feeling LW was local however i do not have a temp variable at that location.

The data area is as follows:

IN
SRC_DB INT 0.0
DB_Qty INT 2.0
Length INT 4.0

OUT
ERR INT 6.0

TEMP
indx INT 0.0
indx1 INT 2.0
indx2 INT 4.0
RFID DWORD 6.0
Value1 WORD 10.0
Value2 WORD 12.0
TmpInt INT 14.0
Blk_1_Nr INT 16.0
Bw_1_Nr INT 18.0
Blk_2_Nr INT 20.0
Data1 WORD 22.0
Clear WORD 24.0

RETURN
Ret_Val 0.0

I have attached a pdf of the code.

Thanks again.
 
As I understand it you are still referencing the local memory stack even if it doesn't have a label assigned. It will still behave the same as any other temporary variable. If you create a word at address 28 of the temporary data you should see the code update to display that label when you save it.
 
LeiconJames

Thanks again for the speedy reply.

The attached PDF, is of the existing (missing SCL file) compilation.

If a variable was defined at address 28 would that not appear in the TEMP area?

Apologies for the nooby questions, but Siemens really isn't my forte.

kind regards
Dave
 
Yes it would, but you can still use it without having a label assigned.
It's the same as using a memory bit eg M20.1 or memory word MW28.
The M data exists even without assigning a symbol, if you do add a symbol in the symbol table you reference that instead of typing the explicit address.
It's the same for L data, if you have a label assigned you can reference that otherwise you can reference the address absolutely.
Local data is treated exactly the same as any other memory area the only thing you need to remember is it is cleared between block calls.
 
LeiconJames.

That makes sense.

My next question then will be.

In SCL what line of code would allow me to reference that particular address.

I tried: LW 28:=W#16#44C; but that obviously does not compile (with and without the space at LW).

Thanks again
 
Sorry I can't help with SCL, I've never used it.

I imagine though LW 28 is being used by some instruction in SCL by the Siemens compiler which is why there is no label.

It may be difficult to decompile the code to work out which instruction is using it but I'm sure some of the Siemens experts will be able to help.
 
No worries LeiconJames.

Thanks for your help, You have solved a few things for me.

As a side note, I just compiled some SCL that calls SFC20 and it created a line in the STL :-

UC "BLKMOV"

This line does not exist in the original code, so I am thinking that this function uses some other form of moving memory from DB<a> to DB<b>.

Thanks again

kind regards
Dave
 
The SCL compiler will allocate local data for intermediate variables and it will use the local data area after your named declarations (the ladder editor also does this if you view some ladder in STL).

Copy your SCL block to a library and post the archived library.

When reverse engineering SCL, I keep compiling/editing the SCL and compare the compiled code with the original until they start to merge. As you do this, you start to get a "feel" for what the compiler generates.
 
Hi L D[AR2,P#0.0].

Appreciate you taking the time to look at the code.

I have been doing as you say, write some SCL, compile and compare but am unsure on how the indirect referencing of the DB was done (and specifically how to code it) - my assumption (from go-ogling) is that an any pointer is needed somehow.

kind regards
Dave
 
Here is how you access the DB indirectly:

Code:
 //How to indirectly address DB1101?
    WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[BW_1_Nr]:= Value1;
 
L D[AR2,P#0.0].

would you believe I just found the following page moments before your post

http://www.automation.siemens.com/WW/forum/guests/PostShow.aspx?PageIndex=1&PostID=79446&Language=en

and was just in the process of testing it. :ROFLMAO:

SCL so far
Code:
FUNCTION FC1300 : VOID

// Block Parameters
VAR_INPUT
    // Input Parameters
    SRC_DB: INT; //data block number at bottom of stack
    DB_Qty: INT; // Number of data blocks
    Length: INT; //DB length in bytes
END_VAR

VAR_OUTPUT
    // Output Parameters
    ERR: INT;
END_VAR

VAR_IN_OUT
    // In Out Parameters
END_VAR

VAR_TEMP
    // Temporary Variables
    indx:INT; //index number
    indx1:INT; //index number
    indx2:INT; //index number
    RFID:DWORD; //RFID Temporary Memory
    Value1:WORD; //Temp word holds value of control word 1
    Value2:WORD; //Temp word holds value of control word 2
    TmpInt:INT; //Temp integer
    Blk_1_Nr:INT; //Destination block number
    Bw_1_Nr:INT; //Control block word number
    Blk_2_Nr:INT; //Source block number
    Data1:WORD; // Data to be transferred
    Clear:WORD; //clear set to 0 and used to clear data
END_VAR

    BW_1_Nr:=18;
    Blk_1_Nr:=SRC_DB-DB_Qty+1;  //1130-30+1 [1101] FIFO1_S1 DB
    Blk_2_Nr:=Blk_1_Nr+1;       //1101+1           FIFO1_S2 DB
    indx1:=0;
    Clear:=0;
    Err:=0;
    
    Clear:=WORD_TO_BLOCK_DB(INT_TO_WORD(1100)).DW[0];
    Value1:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[BW_1_Nr];
    
    //pseudo code
    //clear FIFOxSlot1 when data present and data log complete
    //Copy DB<Blk_1_Nr> WORD <BW_1_Nr> into Value1
    //IF Value1.1 AND Value1.2 THEN
    //    Copy DB1100 over DB<Blk_1_Nr>
    //END IF
    
    //move FIFO blocks up when preceding block is empty (not data present)
    //DO
    //    <Blk_2_Nr>=<Blk_1_Nr> + 1
    //    Copy DB<Blk_1_Nr> WORD <BW_1_Nr> into Value 1
    //    Copy DB<Blk_2_Nr> WORD <BW_1_Nr> into Value 2
    //    If Not Value1.2 AND Value2.2 THEN
    //        Copy DB<Blk_2_Nr> over DB<Blk_1_Nr>
    //        Copy DB1100 over DB<Blk_2_Nr>
    //    END IF
    //    <Blk_1_Nr>=<Blk_1_Nr>+1
    //WHILE <Blk_1_Nr> < DB_Qty
    
END_FUNCTION
Thanks again for the help

kind regards
Dave
 
Here's the first bit of pseudo code done:

Code:
FUNCTION FC1300 : INT
// Block Parameters
VAR_INPUT
    // Input Parameters
    SRC_DB: INT;
    DB_Qty: INT;
    Length: INT; 
END_VAR
VAR_OUTPUT
    // Output Parameters
    ERR: INT;
END_VAR
VAR_IN_OUT
    // In Out Parameters
END_VAR
VAR_TEMP
    // Temporary Variables
    indx:INT;
    indx1:INT;
    indx2:INT;
    RFID:DWORD;
    Value1:WORD;
    Value1bits AT Value1:ARRAY[0..15] OF BOOL;
    Value2:WORD;
    TmpInt:INT;
    Blk_1_Nr:INT;
    Bw_1_Nr:INT;
    Blk_2_Nr:INT;
    Data1:WORD;
    Clear:WORD;
END_VAR
    BW_1_Nr:=18;
    Blk_1_Nr:=SRC_DB-DB_Qty+1;  //1130-30+1 [1101] FIFO1_S1 DB
    Blk_2_Nr:=1+ Blk_1_Nr;      //1101+1           FIFO1_S2 DB
    indx1:=0;
    Clear:=0;
    Err:=0;
    
    Clear:=WORD_TO_BLOCK_DB(INT_TO_WORD(1100)).dw0;
    Value1:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[BW_1_Nr];
    IF Value1Bits[1] AND Value1Bits[2] THEN 
     REPEAT
      WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[Indx1]:=Clear;
      Indx1:=Indx1+2; 
     UNTIL indx1 = Length
     END_REPEAT; 
     Indx1:=0;
    END_IF;
    
    //move FIFO blocks up when preceding block is empty (not data present)
    //DO
    //    <Blk_2_Nr>=<Blk_1_Nr> + 1
    //    Copy DB<Blk_1_Nr> WORD <BW_1_Nr> into Value 1
    //    Copy DB<Blk_2_Nr> WORD <BW_1_Nr> into Value 2
    //    If Not Value1.2 AND Value2.2 THEN
    //        Copy DB<Blk_2_Nr> over DB<Blk_1_Nr>
    //        Copy DB1100 over DB<Blk_2_Nr>
    //    END IF
    //    <Blk_1_Nr>=<Blk_1_Nr>+1
    //WHILE <Blk_1_Nr> < DB_Qty
    
    FC1300:=100;
END_FUNCTION
 
Completed SCL:

Code:
FUNCTION FC1300 : void
// Block Parameters
VAR_INPUT
    // Input Parameters
    SRC_DB: INT;
    DB_Qty: INT;
    Length: INT; 
END_VAR
VAR_OUTPUT
    // Output Parameters
    ERR: INT;
END_VAR
VAR_IN_OUT
    // In Out Parameters
END_VAR
VAR_TEMP
    // Temporary Variables
    indx:INT;
    indx1:INT;
    indx2:INT;
    RFID:DWORD;
    Value1:WORD;
    Value1bits AT Value1:ARRAY[0..15] OF BOOL;
    Value2:WORD;
    Value2bits AT Value2:ARRAY[0..15] OF BOOL;
    TmpInt:INT;
    Blk_1_Nr:INT;
    Bw_1_Nr:INT;
    Blk_2_Nr:INT;
    Data1:WORD;
    Clear:WORD;
END_VAR
    BW_1_Nr:=18;
    Blk_1_Nr:=SRC_DB-DB_Qty+1;  //1130-30+1 [1101] FIFO1_S1 DB
    Blk_2_Nr:=1+ Blk_1_Nr;      //1101+1           FIFO1_S2 DB
    indx1:=0;
    Clear:=0;
    Err:=0;
    
    Clear:=WORD_TO_BLOCK_DB(INT_TO_WORD(1100)).dw0;
    Value1:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[BW_1_Nr];
    IF Value1Bits[1] AND Value1Bits[2] THEN 
     REPEAT
      WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[Indx1]:=Clear;
      Indx1:=Indx1+2; 
     UNTIL indx1 = Length
     END_REPEAT; 
     Indx1:=0;
    END_IF;
    
    RFID:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DD0;
    Value2:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_2_Nr)).DW[BW_1_Nr];
    IF NOT Value1Bits[2] AND Value2Bits[2] AND (RFID = dw#16#0) THEN
     REPEAT
      Data1:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_2_Nr)).DW[Indx1];
      WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[Indx1]:=Data1;
      WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_2_Nr)).DW[Indx1]:=Clear;
      Indx1:=Indx1+2; 
     UNTIL indx1 = Length
     END_REPEAT; 
     Indx1:=0;
    END_IF;
    
    Indx2:=2;
    WHILE Indx2 < DB_Qty DO
     Blk_1_Nr:=Blk_1_Nr+1;
     Blk_2_Nr:=Blk_2_Nr+1;
     Value1:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[BW_1_Nr];
     Value2:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_2_Nr)).DW[BW_1_Nr];
     IF NOT Value1Bits[2] AND Value2Bits[2] THEN
      REPEAT
      Data1:=WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_2_Nr)).DW[Indx1];
      WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_1_Nr)).DW[Indx1]:=Data1;
      WORD_TO_BLOCK_DB(INT_TO_WORD(Blk_2_Nr)).DW[Indx1]:=Clear;
      Indx1:=Indx1+2; 
     UNTIL indx1 = Length
     END_REPEAT; 
     Indx1:=0;

     END_IF;
     Value1:=w#16#0;
     Value2:=w#16#0;
     Indx2:=Indx2+1;
    END_WHILE;
END_FUNCTION
 

Similar Topics

Hi Siemens Experts, I am hoping someone can shed some light on my issue. I have uploaded the code from a S7-300 (317-2PN/DP) using Step 7...
Replies
9
Views
640
I'm having trouble trying to convert this code to ladder, anyone able to help me? A M4.0 A M4.1 A M117.0 AN M17.7 A ( A I38.6 AN I3.7 O ( A M4.5...
Replies
8
Views
1,202
Hello, I am still new to STL. But from what I understand is the JC mnemonic should jump if RLO = 1. If we review both pictures the M0bf RLO = 1...
Replies
5
Views
1,044
Hello, I am working on a project to upgrade some old S5-100U processors. The programs are all uploaded and I don't have descriptors...ugh. Be that...
Replies
4
Views
1,152
I really struggle with STL in Siemens Step 7 Classic. I'll learn chunks, but then I don't use it enough to retain and build on the knowledge. When...
Replies
17
Views
3,195
Back
Top Bottom