Step 7 SCL Aufruf des SFC22

Also neuer Versuch :
Code:
   hDatenQuelle : ANY ;
   xDatenQuelle AT hDatenQuelle : STRUCT
              ID_Code   : BYTE ;  // 10h für S7
              DataTyp   : BYTE ;
              Anzahl    : WORD ;
              DB_Nr     : WORD ;
              SpeicherPtr : DWORD ;
              END_STRUCT ;
eine Variable vom Typ ANY anlegen, eine AT-Sicht, wie oben dargestellt darauf machen, und die gewünschten Inhalte in die AT-Sicht schreiben. Anschließend die ursprüngliche ANY-Variable für den Baustein verwenden ...

Gruß
Larry
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Also neuer Versuch :
Code:
   hDatenQuelle : ANY ;
   xDatenQuelle AT hDatenQuelle : STRUCT
              ID_Code   : BYTE ;  // 10h für S7
              DataTyp   : BYTE ;
              Anzahl    : WORD ;
              DB_Nr     : WORD ;
              SpeicherPtr : DWORD ;
              END_STRUCT ;
eine Variable vom Typ ANY anlegen, eine AT-Sicht, wie oben dargestellt darauf machen, und die gewünschten Inhalte in die AT-Sicht schreiben. Anschließend die ursprüngliche ANY-Variable für den Baustein verwenden ...

Gruß
Larry

ich wage zu behaupten, dass es soweit bereits klar war und es tatsächlich nur noch darum ging, wie man der Unmöglichkeit Herr wird, dass im letztem DWORD sowohl Datentyp als auch Adresse zu hinterlegen sind sind...

[EDIT]
und das ist jetzt ganz ehrlich auch SCL?
[/EDIT]
 
Naja ... man könnte ja die AT-Sicht auch anders aussehen lassen und das letzte DWORD dann anders auflösen - oder eine 2. AT-Sicht auf die gleiche Datenquelle machen ...

Ach ja ... und das ist tasächlich SCL ;)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... ich schrieb ja von einer 2. AT-Sicht - die könnte dann z.B. so aussehen :
Code:
   yDatenQuelle AT hDatenQuelle : STRUCT
              ID_Code   : BYTE ;  // 10h für S7
              DataTyp   : BYTE ;
              Anzahl    : WORD ;
              DB_Nr     : WORD ;
              Speicherbereich : ARRAY [0..3] OF BYTE ;
              END_STRUCT ;
Gruß
Larry
 
... ich schrieb ja von einer 2. AT-Sicht - die könnte dann z.B. so aussehen :
Code:
   yDatenQuelle AT hDatenQuelle : STRUCT
              ID_Code   : BYTE ;  // 10h für S7
              DataTyp   : BYTE ;
              Anzahl    : WORD ;
              DB_Nr     : WORD ;
              Speicherbereich : ARRAY [0..3] OF BYTE ;
              END_STRUCT ;
Gruß
Larry

vielleicht kann ich Deinem klugen Gedanken gerade nicht folgen ...

Es geht darum, dass in DWORD SpeicherPtr

Byte 0 den Speicherbereich
Byte 1, Byte 2 und (hier das Problem) 5(!) Bits von Byte 3 die Byteadresse
und 3Bit aus Byte3 die Bitadresse

beschreiben und tatsächlich fällt mir dazu keine andere schöne Möglichkeit ein, als die hier beschriebene: http://www.sps-forum.de/simatic/71807-scl-aufruf-des-sfc22-2.html#post498698
 
So ich hab in SCL mir nun auch diesen ansatz zur lösung überlegt das ich es wie in AWL ebenfalls um drei Stellen verschiebe.

Code:
Adress2:=SHL(IN:=INT_TO_DWORD(Adress1),N:=3);
OUT1:=Adress2 AND dw#16#84000000;

Hier liegt das Problem dabei das ich die beiden Werte nicht Addiert bekomme. Und weder eine AND oder OR oder XOR Funktion ist an der Stelle richtig.
Irgend wie muss das doch gehen...

Denkfehler mit einem OR müsste es doch gehen.
 
Zuletzt bearbeitet:
Der Fehler lautet Unzulässige Operandentypen. Aber wenn ich die Adition bereits mit der Variabele Adress1 ausführe dürfte es keine Probleme geben. Und am ende anstad des AND ein OR benutze.

Mann kann auch ganze DWÖRTER verunden oder verodern deshalb geht das.
 
Zuletzt bearbeitet:
[remove]OR funktioniert an der Stelle nicht! Ergebnis von AND und OR sind jeweils Bits.[/remove]

bringe die zu verknüpfenden Variablen in das selbe Format DINT um sie zu addieren ( ist wie ODER )
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das habe ich mir auch schon überlegt aber die Anweisund
Code:
DWORD_TO_INT(dw#16#84000000);
Klapt nicht des halb dachte ich mit dem OR geht das wie unter FUP mit dem Befehl WOR_DW aber den Zahn kann ich mir wohl ziehn...
 
Das habe ich mir auch schon überlegt aber die Anweisund
Code:
DWORD_TO_[SIZE=5][COLOR=#FF0000][B]D[/B][/COLOR][/SIZE]INT(dw#16#84000000);
Klapt nicht des halb dachte ich mit dem OR geht das wie unter FUP mit dem Befehl WOR_DW aber den Zahn kann ich mir wohl ziehn...

kannst aber auch gleich mit -2080374784 arbeiten ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn man in SCL Bytes, Words oder DWs mit "AND" oder "OR" verknüpft, wird die Verknüpfung bitweise durchgeführt und das Ergebnis ist ein Byte, Word oder DW.
Gruß
Erich

sicher? ich meine ... sicher?

und ja, stimmt ... die Hilfe jetzt doch mal gelesen:

Das Ergebnis des Ausdrucks ist entweder TRUE oder FALSE bei der
Verknüpfung von booleschen Operanden oder
ein Bitmuster nach der Bitverknüpfung
zwischen den beiden Operanden.

Addition geht aber trotzdem auch ;)
 
...Addition geht aber trotzdem auch ;)
In dieser Anwendung: Ja!
Das klappt aber immer nur dann, wenn man sicher ist, dass nicht an einer oder mehreren Bitpositionen in beiden Operanden die Bits gesetzt sind.
Dann passiert nämlich beim Addieren ein Überlauf ins nächsthöhere Bit und das Resultat ist anders als beim bitweisen OR.
Gruß
Erich
 
Guten Tach auch.
ist soweit fertig. Wenn jemand noch Ideen hat was ich häte anders machen können immer raus damit. Der Baustein den ich Programmiert habe hat die Funktion ein Schieberegister selbst zu erstellen mit einstellbarer Länge.

Meine Lösung: (Läuft auch)
Code:
FUNCTION_BLOCK FB30
VAR_INPUT
    GD:INT; //Größe pro Datensatz in Bayte.
    AD:INT; //Anzahl der Datensätze
    S:BOOL; //POS. Flanke zum Schiben.
    DB_Nr:INT; //Nummer des DBs der erschtellt werden soll.
    DB_er:BOOL; //DB erstellen POS. Flanke
    DATA:ANY; //Pointer auf die Daten
        END_VAR
VAR        
    G:WORD; //Gesamtgröße
    DB_erstellt:BOOL; //DB ist bereits erstellt.
    Schieben:BOOL; //Schieben läuft.
    ND:INT; //Nächster Datesatz. Zum Schieben.
    ND_DWORD:DWORD; //Nächster Datesatz. Zum Schieben als DWORD
    NZ:INT; //Nächstes Ziel beim Schieben.
    NZ_DWORD:DWORD; //Nächstes Ziel beim Schieben als DWORD
    DUMY_Nr:WORD; //Nummer Des Erstellten DBs.
    SFC22_INT:INT; //Rückgabe Wert DB Erstellem
    BLKMOV_INT:INT; //Rückgabe Wert Block Move.
END_VAR
VAR_OUTPUT
    // Hife VAR zur Diagnose
    OUT1:INT;
    OUT2:DWORD;
    OUT3:DWORD;
    OUT4:DWORD;
    END_VAR
VAR_TEMP
    // Struckturen für beide ANY Pointer
Quelle: STRUCT // Queladresse für Block Move
        ANY_id: BYTE;
        DataType: BYTE;
        Laenge: WORD;
        DB_Nr: WORD;
        Byte_Pointer: DWORD;
    END_STRUCT;
    
    Ziel: STRUCT // Ziel Adresse für Block Move
        ANY_id: BYTE;
        DataType: BYTE;
        Laenge:WORD;
        DB_Nr:WORD;
        Byte_Pointer:DWORD;
    END_STRUCT;
    
    // Zuweisen des Structes auf den ANY Pointer
    Quelle_ANY AT Quelle:ANY;
    Ziel_ANY AT Ziel:ANY;

END_VAR

    IF DB_er THEN  
         
         G:=INT_TO_WORD(GD*AD);         //Errechnen der Gesamten Größe des DBs.
        //Erstellen des Datenbausteines mit Hilfe des SFC22.
        
         SFC22_INT:=CREAT_DB(LOW_LIMIT := INT_TO_WORD(DB_Nr)  // IN: WORD
                 ,UP_LIMIT := INT_TO_WORD(DB_Nr) // IN: WORD
                 ,COUNT := G // IN: WORD
                 ,DB_NUMBER := DUMY_Nr // OUT: WORD
                 ); // INT
        
    ELSE
        
        IF WORD_TO_INT(DUMY_Nr) > 0 THEN    //Ermitteln ob der DB erstellt wurde.
        DB_erstellt:=TRUE;
        END_IF;
    
        
    IF DB_erstellt & S THEN
        
        //Berechnen der Adresse des Ersten zu schiebenden Datensatzes
        ND:=WORD_TO_INT(G)-(2*GD);
        //Berechnen der Adresse des Ersten zu schiebenden Zieles
        NZ:=WORD_TO_INT(G)-(GD);
        
        //Zusammen setzen des Quell Pointers
        ND_DWORD:=SHL(IN:=INT_TO_DWORD(ND),N:=3); //Schiebe Wert ND um 3 Stellen nach Links.
        ND_DWORD:= ND_DWORD OR 16#84000000; // Ergenzen des Wertes 16#84000000 dies steht für Datenbaustein
        
        //Zusammen setzen des Ziel Pointers
        NZ_DWORD:=SHL(IN:=INT_TO_DWORD(NZ),N:=3); //Schiebe Wert NZ um 3 Stellen nach Links.
        NZ_DWORD:= NZ_DWORD OR dw#16#84000000;  // Ergenzen des Wertes 16#84000000 dies steht für Datenbaustein
        
        //Zusammen Setzen des Quell ANY Pointers.       
        Quelle.ANY_id:=16#10;
        Quelle.DataType:=16#2;
        Quelle.Laenge:=INT_TO_WORD(GD);
        Quelle.DB_Nr:=DUMY_Nr;
        Quelle.Byte_Pointer:= ND_DWORD ;
        
        Out2:=ND_DWORD;
        //Zusammen Setzen des Ziel ANY Pointers.
        Ziel.ANY_id:=16#10;
        Ziel.DataType:=16#2;
        Ziel.Laenge:=INT_TO_WORD(GD);
        Ziel.DB_Nr:=DUMY_Nr;
        Ziel.Byte_Pointer:= NZ_DWORD ;
        Out3:=NZ_DWORD;
        
    WHILE ND >= 0 DO  // Schleife beenden wen alle werte geschoben wurden.
        
        //Schieben der Werte mit Block Move.
        
        BLKMOV_INT:= BLKMOV(SRCBLK := Quelle_ANY // IN: ANY
               ,DSTBLK := Ziel_ANY // OUT: ANY
             ); // INT
             
        // Errechnen der nächste Quell und Ziel Adresse.
             
        ND:=ND-GD;
        NZ:=NZ-GD;     
        
        //Zusammen setzen des Quell Pointers     
        ND_DWORD:=SHL(IN:=INT_TO_DWORD(ND),N:=3);
        ND_DWORD:= ND_DWORD OR dw#16#84000000;
         
        //Zusammen setzen des Ziel Pointers
        NZ_DWORD:=SHL(IN:=INT_TO_DWORD(NZ),N:=3);
        NZ_DWORD:= NZ_DWORD OR dw#16#84000000;  
        
        //Werte in den ermitttelten werte in den ANY Pointer übertragen.
        Quelle.Byte_Pointer:= ND_DWORD ;
        Ziel.Byte_Pointer:= NZ_DWORD ;         
        ;
    END_WHILE;    
    
        //Neu Werte auf die erste Adresse Setzen.
        Ziel.Byte_Pointer:=dw#16#84000000;    
        BLKMOV_INT:= BLKMOV(SRCBLK := DATA // IN: ANY
               ,DSTBLK := Ziel_ANY // OUT: ANY
             ); // INT
              
    ELSE
        
        ;//ENDE!
        
    END_IF;
    END_IF;
    ;
END_FUNCTION_BLOCK

Eine weitere Funktion die ich noch einbauen will ist wen der Befehl kommt DB erstellen der Allte DB wenn vorhanden gelöscht wird. Und das Ausgeben eines Belibigen Datensatzes.
 
Es ist hoffentlich kein Problem wenn ich weiter Hier rein schreibe.

Und zwar ist mein Aktuelles Problem das der SFC22 nur DBs mit einer Graden anzahl an Bytes erstellen kann. Jetzt ist mein Plan das ich erst abfrage ob die Anzahl an Bytes grade ist wenn nicht +1. Wie ermittel ich in SCL ob ein Wert grade oder ungrade ist. Muss ich das so lösen: Wert/2 wenn ein Rest vorhanden ist, ist die Zahl ungerade.

Oder gibt es in SCL auch die Möglichkeit das Niderwertigste Bit agzufragen? Weil ist dieses 1 ist die Zahl ungerade. Bei einem INT im MW0 wäre das Bit was abgefragt werden soll M1.0. aber in SCL benutze ich Variabelen. Gibt es dort eine Möglichkeit?

Die zweite Variante wäre mir lieber.
 
Zurück
Oben