Step 7 In SCL ein CHAR-Feld zu einem String zusammen fassen!

fabries

Level-1
Beiträge
9
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo SCL-Experten,

habe hier einen SCL-Baustein definiert, an dem ich den Fehler nicht finden kann.

Der Baustein soll eine definierte Länge von CHAR's zu einem STRING-Typ zusammen fassen. Die Ausgabe des Wertes funktioniert nicht ganz! :confused:
Als Eingabe für den CHAR-Speicher, ist am Eingang ein ANY-Zeiger verwendet ->z.B.: P#DB2000.DBX100.0 BYTE100
Am Ausgang wird einfach eine STRING-Variable angegeben.

Meine Vermutung ist, das es in der FOR-Schleife liegt, bei dem Aufruf -> WORD_TO_BLOCK_DB

Habe hier den SCL-Code aufgeführt:

Code:
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// UDT that mimics ANY pointer type. Used to construct an ANY pointer for DB access  
TYPE "ANYPOINTER"  
TITLE = DISSASEMBLED ANYPOINTER  
VERSION : 1.0  
AUTHOR  : 'FFF'  
NAME    : 'ANYPTR'  
FAMILY  : 'COMMON'  
    
    STRUCT  
        S7Code         : BYTE;   // Code for S7 = 0x10  
        DataType       : BYTE;   // Code for data type = 0x02 = byte 
        //DataType := 16#01; // For boolean access  
        //DataType := 16#02; // For byte access  
        //DataType := 16#03; // For char access  
        //DataType := 16#04; // For word access  
        //DataType := 16#05; // For int access  
        //DataType := 16#06; // For dword access  
        //DataType := 16#07; // For dint access  
        //DataType := 16#08; // For real access  
        Length         : INT;    // Repetition factor = Send/receive length  
        DBNumber       : INT;    // Data block Number  
        MemoryArea     : BYTE;   // Specified memory area = 0x84 = data block  
        //MemoryArea := 16#84; // For shared DB access  
        //MemoryArea := 16#85; // For instance DB access  
        ByteAddressMSB : BYTE;   // Byte address most significant bits  
        ByteAddressLSB : WORD;   // Byte address least significant bits  
    END_STRUCT;  
END_TYPE  
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
// This function puts a amount of Chars to one String
FUNCTION "CHAR_TO_STRNG" : STRING
VERSION : '1.0'  
AUTHOR  : FFF  
NAME    : CHR_STRG  
FAMILY  : COMMON  
VAR_INPUT
    //Pointer for DB informaton
    pSrcDB : ANY;     
END_VAR 
VAR_TEMP
    //control variable
    i, a : INT;     
    //String variables
    Temp_String : STRING[254];
    Sym_Name_View AT Temp_String : STRUCT
        _Str_Max_Len : BYTE;
        _Str_Akt_Len : BYTE;
        _Symb_Array : ARRAY[1..254] OF BYTE;
    END_STRUCT;
    temp_pSrcDB : ANY;
    // Define source datablock access ANY pointer         
    SrcDBAny AT temp_pSrcDB : "ANYPOINTER";   // ANY pointer data structure    
    u1Addr             : DWORD;        // Union pointer for calculation of byte offset address  
    u1 AT u1Addr: STRUCT               // This is equivalent to a union in 'c'. A dword goes in and word / byte LSB / byte MSB come out  
        ByteAddrLSBPad     : BYTE;         // Not Used  
        ByteAddrMSB        : BYTE;         // Byte address most significant bits  
        WordAddr           : WORD;         // Byte address least significant bits  
    END_STRUCT;  
    //u1Addr := INT_TO_DWORD(SRCDBADR * 16); // For word / int access  
    //u1Addr := INT_TO_DWORD(SRCDBADR * 32); // For dword / dint / real access 
    DBB_No : INT;
    Temp_Word : WORD;
END_VAR
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////
BEGIN  
Temp_String := '0';
temp_pSrcDB := pSrcDB;
//Set up DB numbers  
Temp_Word := INT_TO_WORD(SrcDBAny.DBNumber);
//Obtain the source DB address for ANY pointer  
//load the beginning data block BYTE 
u1.ByteAddrMSB := SrcDBAny.ByteAddressMSB;  
u1.WordAddr := SrcDBAny.ByteAddressLSB ;  
// Address of the beginning Byte of the source data block
DBB_No := DWORD_TO_INT(SHR(IN := u1Addr, N := 3));   
// Copy the data from ARRAY of CHAR to STRING 
FOR i := 1 TO SrcDBAny.Length BY 1 DO 
    Sym_Name_View._Symb_Array[i] := WORD_TO_BLOCK_DB(INT_TO_WORD(SrcDBAny.DBNumber)).DB[i];  
END_FOR;
//FOR a := 1 TO SrcDBAny.Length BY 1 DO 
//  ;//"DB_String".Test[a] := Sym_Name_View._Symb_Array[a]; 
//END_FOR;
//Write the length for the Output string
Sym_Name_View._Str_Max_Len := INT_TO_BYTE(SrcDBAny.Length);
Sym_Name_View._Str_Akt_Len := INT_TO_BYTE(SrcDBAny.Length);
//Output string
"CHAR_TO_STRNG" := Temp_String;     
END_FUNCTION
///////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////

Hoffe, dass mir jemand weiterhelfen kann.

Danke
Fabries
 
Hallo,
deine DB-Nummer ergibt sich (für mich) aus SrcDBAny.DBNumber.
Dein erstes Byte in dem DB errechnet sich aus (SrcDBAny.ByteAddressMSB * 65536 + SrcDBAny.ByteAddressLSB) / 8 - passende Casts bitte berücksichtigen.
Die Schleife müßte dann in etwa so aussehen :
Code:
FOR i := 0 TO SrcDBAny.Length-1 BY 1 DO 
    Sym_Name_View._Symb_Array[i] := WORD_TO_BLOCK_DB(INT_TO_WORD(SrcDBAny.DBNumber)).DB[i+myByteOffset];  // Formel für myByteOffset siehe oben ...
END_FOR;
Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Muß das unbedingt mit dieser rechenaufwendigen Schleife sein?
Man könnte SFC20 BLKMOV nutzen:
Code:
FUNCTION "CHAR_TO_STRNG" : STRING
VERSION : '1.0'  
AUTHOR  : FFF  
NAME    : CHR_STRG  
FAMILY  : COMMON  
VAR_INPUT
    pSrcDB : ANY;     
END_VAR
VAR_TEMP
    Temp_String : STRING[254];
    Sym_Name_View AT Temp_String : STRUCT
        _Str_Max_Len : BYTE;
        _Str_Akt_Len : BYTE;
        _Symb_Array : ARRAY[1..254] OF BYTE;
    END_STRUCT;
    temp_pSrcDB : ANY;
    SrcDBAny AT temp_pSrcDB : "ANYPOINTER";   // ANY pointer data structure
    Temp_Int : INT ;
END_VAR
BEGIN

Temp_String := '';     //Sym_Name_View._Str_Max_Len := 254 ; Sym_Name_View._Str_Akt_Len := 0 ;
temp_pSrcDB := pSrcDB; //for access DataType and Length in the ANY

IF SrcDBAny.DataType = 16#02 THEN //only if DataType = 16#02 = BYTE
  // Copy the data from ARRAY of CHAR to STRING
  [COLOR="#0000FF"]Temp_Int := BLKMOV(SRCBLK := pSrcDB, DSTBLK := Sym_Name_View._Symb_Array );[/COLOR]

  //Write the length for the Output string
  Sym_Name_View._Str_Max_Len := INT_TO_BYTE(SrcDBAny.Length);
  Sym_Name_View._Str_Akt_Len := Sym_Name_View._Str_Max_Len;
END_IF;

//Output string
"CHAR_TO_STRNG" := Temp_String;     
END_FUNCTION
Der Code ist ungetestet.
Vermutlich sollte man noch testen/ausschließen, daß der INPUT-ANY auf den Bereich 16#86 (L-Stack) zeigt. Und eventuell auch 16#87 Vorgänger-Lokaldaten ausschließen?

Harald
 
Zurück
Oben