Zuviel Werbung? - > Hier kostenlos beim SPS-Forum registrieren

Ergebnis 1 bis 10 von 10

Thema: Element aus Array kopieren

  1. #1
    Registriert seit
    29.05.2008
    Beiträge
    9
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Hallo zusammen!

    Ich gebe es zu, ich habe von der nachfolgenden Thematik kaum eine Ahnung, aber ich möchte aus einem Array of UDT einen Datensatz, den ich über den Index (INT) referenziere kopieren.

    Konkret gibt es einen DB:

    AktuellerDS: UDT_DSTyp
    Datenbank: Array [1..10] of UDT_DSTyp

    Ich habe jetzt mit einem hier im Forum entdeckten Quelltext etwas experimentiert, scheitere aber an der Stelle dem SFC20 die Zieladresse zu übergeben.

    Vielleicht kann mich mal jemand unterstützen, der sich damit auskennt.

    Vielen Dank!
    Code:
    FUNCTION FC 2005 : INT
    TITLE = FC_COPY
    AUTHOR : Guido
    VERSION : 0.1
     
    VAR_INPUT
    SourceData : ANY ; //Datenbereich in dem die Parametersätze abgelegt sind
    SourceIndex : INT ; //Index des zu bearbeitenden Parametersatzes
    END_VAR
    VAR_OUTPUT
    DestinationData : ANY ; //Datenbereich in dem der Parametersatz kopiert werden soll 
    END_VAR
    VAR_TEMP
    AR1_TEMP : DWORD ; 
    AKT_DATENSATZ : DWORD ; 
    LAENGE_UDT : INT ; //Länge des Parametersatzes
    DB_UDT : INT ; //Nummer des DB
    STARTADRESSE : DWORD ; //Startadresse im DB = 1. Datensatz
    END_VAR
    BEGIN
    NETWORK
    TITLE =
    //*** AR1 sichern
    TAR1 #AR1_TEMP; 
    SET ; 
    SAVE ; 
    //*** Ergebnisse initialisieren
    L B#16#0; 
    T #RET_VAL; 
    //*** AR2 auf Datenbereich im DB
    L P##SourceData; 
    LAR2 ; 
    //*** ANY-Pointer zerlegen
    //*** wir brauchen nur die DB-Nr und Länge des UDT
    //*** sowie die Startadresse im DB (Bereichszeiger)
    L B [AR2,P#0.0]; // Syntax-ID, bei S7 immer 10hex
    L B [AR2,P#1.0]; // Datentyp
    L W [AR2,P#2.0]; // Anzahl von "Datentyp" = Länge des UDT
    T #LAENGE_UDT; // temporär ablegen
    L W [AR2,P#4.0]; // Nummer des DB [INT]
    T #DB_UDT; // temporär ablegen
    L D [AR2,P#6.0]; // Bereichszeiger = Startadresse
    T #STARTADRESSE; // Startadresse im DB = 1. Datensatz
    //*** Prüfe, ob DATENBEREICH vom Typ=Byte
    L B [AR2,P#1.0]; // Datentyp
    L B#16#2; // 02hex == BYTE
    ==I ; 
    L 1; // Fehler 1: DATENBEREICH nicht vom Typ BYTE
    SPBN ERR; // !!! Baustein bei Parameterfehler beenden !!!
    //*** Source-DB öffnen und Adressregister AR2 auf Bereichszeiger
    AUF DB [#DB_UDT]; // DB öffnen
    L #STARTADRESSE; // Bereichszeiger == Startadresse 1. Datensatz
    LAR2 ; // DATENBEREICH
    //*** Offset des aktuellen Datensatzes zu AR2 addieren
    L #SourceIndex; // Nummer des aktuellen Datensatzes (1..n) [INT]
    L 1; // beim 1. Datensatz ist Offset=0
    -I ; // Nummer des aktuellen Datensatzes (0..n-1) [INT]
    // Länge des UDT in BIT umrechnen, ohne Akku 2 zu verändern
    L #LAENGE_UDT; // Länge des UDT (Anzahl DWORD) [INT]
    SLW 5; // Länge des UDT (Anzahl BIT), (SLW 5 == *32)
    // Länge des UDT mit aktueller (Datensatznummer-1) multiplizieren
    *I ; 
    // Offset [BIT] zu AR2 addieren
    +AR2 ; // AR2 zeigt jetzt auf aktuellen Datensatz im DB
    //*** AR2 für späteres Zurückkopieren zwischenspeichern
    TAR2 #AKT_DATENSATZ; 
    //*** Den Datensatz kopieren
    CALL "BLKMOV" (
    SRCBLK := #AKT_DATENSATZ,
    RET_VAL := #RET_VAL,
    DSTBLK := MD 1000); //<- Hier sollte eigentlich #DestinationData stehen!
    //***************************************************************************************************
    // Ende
    //***************************************************************************************************
    //*** AR1-Register wiederherstellen
    LAR1 #AR1_TEMP; 
    BEA ; 
    //*** Fehler
    ERR: T #RET_VAL; 
    //*** AR1-Register wiederherstellen
    LAR1 #AR1_TEMP; 
    BE ; 
    END_FUNCTION
    Zitieren Zitieren Element aus Array kopieren  

  2. #2
    Registriert seit
    20.06.2003
    Ort
    Sauerland.NRW.Deutschland
    Beiträge
    4.850
    Danke
    78
    Erhielt 800 Danke für 543 Beiträge

    Standard

    der anyzeiger sieht so aus
    P#DB100.DBX 0.0 BYTE 2
    P#DB100.DBX 0.0 BOOL 13
    P#DB100.DBX 0.0 WORD 2

    guckst du hier
    http://www.sps-forum.de/showthread.php?t=12923
    .
    mfg Volker .......... .. alles wird gut ..

    =>Meine Homepage .. direkt zum Download

    Meine Definition von TIA: Total Inakzeptable Applikation

  3. #3
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.710
    Danke
    398
    Erhielt 2.397 Danke für 1.997 Beiträge

    Standard

    Wozu brauchst du in dem Zusammenhang den Block-Move ?
    Ich denke mal, es geht dir da drum, den jeweils indexierten UDT einem anderen Programm (oder so) zur Verfügung zu stellen ...
    Das kannst du doch auch mit einem Übergabe-Bereich machen, wo du die gewünschten Daten hinkopierst ...

  4. #4
    guidokk ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    29.05.2008
    Beiträge
    9
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Standard

    @Larry

    Alle Bausteine des restlichen Programmes greifen nur auf "AktuellerDS" im DB zu. Dieser wird aus einer "Datenbank" ausgewählt und in "AktuellerDS" hineinkopiert. Was meinst du mit Übergabebereich und wie kopiere ich die gewünschten Daten dort hin?

    @Volker

    Danke erst mal, dein Link ist sehr informativ ich arbeite daran...

  5. #5
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.710
    Danke
    398
    Erhielt 2.397 Danke für 1.997 Beiträge

    Standard

    Ich hatte das so gemeint, dass in deinem DB (?) z.B. als erstes der Übergabe-UDT liegt. In diesen schiebst du das jeweils gewünschte ARRAY-UDT hinein. Auf diese Weise kannst du m.E. auf die ANY-Pointer-Geschichte verzichten.

    Das heißt allerdings nicht, dass es nicht ganz sinnvoll ist sich mit dieser Thematik zu beschäftigen ...

  6. #6
    guidokk ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    29.05.2008
    Beiträge
    9
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Standard

    Genau das möchte ich doch damit erreichen. Der FC COPY hat als Eingangsparameter das erste Element des Arrays und den Index (als Integer) des gewünschten Arrayelementes. Ich möchte die Angabe des Index als Integer haben, damit der Bediener dies vom Bedienpanel vorgeben kann. Als Ausgangsparameter wird "AktuellerDS" angegeben, in dem das Arrayelement kopiert wird. Natürlich könnte ich das auch fest angeben, aber ich möchte den Baustein gerne flexibel verwenden.

    So ich bin jetzt (auch vom Verständnis) viel weiter.

    Code:
    FUNCTION "FC_LIB Copy" : INT
    TITLE =FC_LIB Copy
    AUTHOR : Guido
    VERSION : 0.1
    
    VAR_INPUT
      SourceData : ANY ; //Datenbereich der in dem die Parametersätze abgelegt sind
      SourceIndex : INT ; //Index des zu bearbeitenden Parametersatzes
    END_VAR
    VAR_OUTPUT
      DestData : ANY ; 
    END_VAR
    VAR_TEMP
      AR1_TEMP : DWORD ; 
      UDT_Length : INT ; //Länge des Parametersatzes
      UDT_DB : INT ; //Nummer des DB
      Source_Start : DWORD ; //Startadresse im DB = 1. Datensatz
      Source_SFC : ANY ; 
      Dest_SFC : ANY ; 
    END_VAR
    BEGIN
    NETWORK
    TITLE =
    //*** AR1 sichern
          TAR1  #AR1_TEMP; 
          SET   ; 
          SAVE  ; 
    //*** Ergebnisse initialisieren
          L     B#16#0; 
          T     #RET_VAL; 
    //*** AR2 auf Datenbereich im DB
          L     P##SourceData; 
          LAR2  ; 
    //*** Prüfe, ob DATENBEREICH vom Typ = BYTE
          L     B [AR2,P#1.0]; // Datentyp
          L     B#16#2; // 02hex == BYTE
          ==I   ; 
          L     1; // Fehler 1: DATENBEREICH nicht vom Typ BYTE
          SPBN  ERR; // !!! Baustein bei Parameterfehler beenden !!!
    //*** ANY-Pointer zerlegen
    //*** wir brauchen die DB-Nr und Länge des UDT
    //*** sowie die Startadresse im DB (Bereichszeiger)
          L     W [AR2,P#2.0]; // Anzahl von Datentyp
          T     #UDT_Length; 
          L     W [AR2,P#4.0]; // Nummer des DB
          T     #UDT_DB; 
          L     D [AR2,P#6.0]; // Bereichszeiger = Startadresse
          T     #Source_Start; // Startadresse im DB = 1. Datensatz
    //*** Adressregister AR2 auf Bereichszeiger
          L     #Source_Start; // Bereichszeiger == Startadresse 1. Datensatz
          LAR2  ; 
    //*** Offset des aktuellen Datensatzes zu AR2 addieren
          L     #SourceIndex; // Nummer des aktuellen Datensatzes (1..n)
          L     1; // beim 1. Datensatz ist Offset=0
          -I    ; // Nummer des aktuellen Datensatzes (0..n-1)
    //    Länge des UDT in BIT umrechnen, ohne Akku 2 zu verändern
          L     #UDT_Length; // Länge des UDT (Anzahl BYTE)
          SLW   3; // Länge des UDT (Anzahl BIT), (SLW 3 == *8)
    //    Länge des UDT mit aktueller (Datensatznummer-1) multiplizieren
          *I    ; 
    //    Offset [BIT] zu AR2 addieren
          +AR2  ; // AR2 zeigt jetzt auf aktuellen Datensatz im DB
    //*** AR2 als neue Startadresse sichern      
          TAR2  #Source_Start; 
    
    // Hier wird für die SFC_20 die Anfangsadresse und Datenlänge in den Pointer gelegt
          LAR1  P##Source_SFC; // Hier wir die Quelladresse für die SFC_20 in den Pointer gelegt
          L     B#16#10; //Syntax-ID
          T     LB [AR1,P#0.0]; 
          L     B#16#2; //Datentyp Byte
          T     LB [AR1,P#1.0]; 
          L     #UDT_Length; //Anzahl von Datentyp
          T     LW [AR1,P#2.0]; 
          L     #UDT_DB; //Nummer des DB
          T     LW [AR1,P#4.0]; 
          L     #Source_Start; //Bereichszeiger
          T     LD [AR1,P#6.0]; 
    //*** Den Datensatz kopieren
          CALL "BLKMOV" (
               SRCBLK                   := #Source_SFC,
               RET_VAL                  := #RET_VAL,
               DSTBLK                   := MD  1000);
    //***************************************************************************************************
    // Ende
    //***************************************************************************************************
    //*** AR1-Register wiederherstellen
          LAR1  #AR1_TEMP; 
          BEA   ; 
    //*** Fehler
    ERR:  T     #RET_VAL; 
    //*** AR1-Register wiederherstellen
          LAR1  #AR1_TEMP; 
          BE    ; 
    END_FUNCTION
    ABER! Warum kann ich den als Any deklarierten Output Parameter "DestData" nicht als DSTBLK am SFC20 anlegen???
    Geändert von guidokk (18.06.2008 um 09:58 Uhr)

  7. #7
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.710
    Danke
    398
    Erhielt 2.397 Danke für 1.997 Beiträge

    Standard

    Zitat Zitat von guidokk Beitrag anzeigen
    ABER! Warum kann ich den als Any deklarierten Output Parameter "DestData" nicht als DSTBLK am SFC20 anlegen???
    Denk-Fehler ...!
    Die Ziel-Adresse für deine Daten wird nicht von deinem Baustein erzeugt, sondern die gibst du ja (von außen) vor. Somit muß das ein IN-Parameter sein. Der SFC akzeptiert den OUT-Parameter aus dem Grund nicht ...

  8. #8
    guidokk ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    29.05.2008
    Beiträge
    9
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Standard

    Zitat Zitat von Larry Laffer Beitrag anzeigen
    Denk-Fehler ...!
    Die Ziel-Adresse für deine Daten wird nicht von deinem Baustein erzeugt, sondern die gibst du ja (von außen) vor. Somit muß das ein IN-Parameter sein. Der SFC akzeptiert den OUT-Parameter aus dem Grund nicht ...
    Ich habe das probiert, aber:

    Der Deklarationsbereich der Aktualseite VAR_INPUT passt nicht zum formalen Deklarationsbereich VAR_OUTPUT des Formalparameters DSTBLK

  9. #9
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.710
    Danke
    398
    Erhielt 2.397 Danke für 1.997 Beiträge

    Standard

    Stimmt ... habe ich schon wieder vergessen ...
    Du kannst einen ANY-Pointer nicht durchreichen ...
    Du mußt den Eingangs-Parameter zunächst in einem TEMP zwischen-speichern. Das geht allerdings nicht mit "L IN_ANY ... T TEMP_ANY" sondern du mußt den Doppelwort-weise (z.B.) über die Hilfsregister (AR1) auf deine TEMP-Variable bringen. Diese kannst du dann an den SFC übergeben.
    Code:
    L  P##Source_Data
    L AR1
     
    L P##Temp_ANY_Pointer
    L AR2
     
    L DBD [AR1,P#0.0]
    T DBD [AR2,P#0.0]
    usw.
    Anmerkung am Rande:
    man vergißt so Einiges, wenn man sich angewöhnt, solche Dinge in SCL zu programmieren ... Da wird einem schon Einiges abgenommen ...

  10. #10
    guidokk ist offline Neuer Benutzer
    Themenstarter
    Registriert seit
    29.05.2008
    Beiträge
    9
    Danke
    0
    Erhielt 1 Danke für 1 Beitrag

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Herzlichen Dank an die beiden Helfer, es funktioniert jetzt zufriedenstellend.

    Der Vollständigkeit halber meine Lösung:
    Code:
    FUNCTION "FC_LIB Copy" : VOID
    TITLE =FC_LIB Copy
    AUTHOR : Guido
    VERSION : 0.1
     
    VAR_INPUT
      SourceData : ANY ; //Erstes Datenelement des Quelldatenbereichs
      SourceIndex : INT ; //Index des Quelldatensatzes
      DestData : ANY ; //Erstes Datenelement des Zieldatenbereichs
      DestIndex : INT ; //Index des Zieldatensatzes
    END_VAR
    VAR_TEMP
      AR1_Temp : DWORD ; 
      SourceLength : INT ; //Länge des Parametersatzes
      SourceDB : INT ; //Nummer des DB
      SourceStart : DWORD ; //Startadresse im DB = 1. Datensatz
      SourceSFC : ANY ; 
      DestSFC : ANY ; 
      RET_VAL_SFC : INT ; 
      DestLength : INT ; 
      DestDB : INT ; 
      DestStart : DWORD ; 
    END_VAR
    BEGIN
    NETWORK
    TITLE =
    //*** AR1 sichern
          TAR1  #AR1_Temp; 
          SET   ; 
          SAVE  ; 
    //*** AR2 auf Quelldatenbereich
          L     P##SourceData; 
          LAR2  ; 
    //*** ANY-Pointer zerlegen
          L     W [AR2,P#2.0]; // Anzahl von Datentyp
          T     #SourceLength; 
          L     W [AR2,P#4.0]; // Nummer des DB
          T     #SourceDB; 
          L     D [AR2,P#6.0]; // Bereichszeiger = Startadresse
          T     #SourceStart; // Startadresse im DB = 1. Datensatz
    //*** Adressregister AR2 auf Bereichszeiger
          L     #SourceStart; // Bereichszeiger = Startadresse 1. Datensatz
          LAR2  ; 
    //*** Offset zu AR2 addieren
          L     #SourceIndex; // Nummer des aktuellen Index (1..n)
          L     1; // beim 1. Datensatz ist Offset=0
          -I    ; // Nummer des aktuellen Index (0..n-1)
    //    Länge in BIT umrechnen, ohne Akku 2 zu verändern
          L     #SourceLength; // Länge des UDT (Anzahl BYTE)
          SLW   3; // Länge des UDT (Anzahl BIT), (SLW 3 == *8)
    //    Länge aktuellem (Index-1) multiplizieren
          *I    ; 
    //    Offset [BIT] zu AR2 addieren
          +AR2  ; // AR2 zeigt jetzt auf aktuellen Datensatz im DB
    //*** AR2 als neue Startadresse sichern      
          TAR2  #SourceStart; 
    //*** Quellzeiger für SFC20 aufbauen
          LAR1  P##SourceSFC; 
          L     B#16#10; //Syntax-ID
          T     LB [AR1,P#0.0]; 
          L     B#16#2; //Datentyp Byte
          T     LB [AR1,P#1.0]; 
          L     #SourceLength; //Anzahl von Datentyp
          T     LW [AR1,P#2.0]; 
          L     #SourceDB; //Nummer des DB
          T     LW [AR1,P#4.0]; 
          L     #SourceStart; //Bereichszeiger
          T     LD [AR1,P#6.0]; 
    //*** AR2 auf Zieldatenbereich
          L     P##DestData; 
          LAR2  ; 
    //*** ANY-Pointer zerlegen
          L     W [AR2,P#2.0]; // Anzahl von Datentyp
          T     #DestLength; 
          L     W [AR2,P#4.0]; // Nummer des DB
          T     #DestDB; 
          L     D [AR2,P#6.0]; // Bereichszeiger = Startadresse
          T     #DestStart; // Startadresse im DB = 1. Datensatz
    //*** Adressregister AR2 auf Bereichszeiger
          L     #DestStart; // Bereichszeiger = Startadresse 1. Datensatz
          LAR2  ; 
    //*** Offset zu AR2 addieren
          L     #DestIndex; // Nummer des aktuellen Index (1..n)
          L     1; // beim 1. Datensatz ist Offset=0
          -I    ; // Nummer des aktuellen Index (0..n-1)
    //    Länge in BIT umrechnen, ohne Akku 2 zu verändern
          L     #DestLength; // Länge des UDT (Anzahl BYTE)
          SLW   3; // Länge des UDT (Anzahl BIT), (SLW 3 == *8)
    //    Länge aktuellem (Index-1) multiplizieren
          *I    ; 
    //    Offset [BIT] zu AR2 addieren
          +AR2  ; // AR2 zeigt jetzt auf aktuellen Datensatz im DB
    //*** AR2 als neue Startadresse sichern      
          TAR2  #DestStart; 
    //*** Zielzeiger für SFC20 aufbauen
          LAR1  P##DestSFC; 
          L     B#16#10; //Syntax-ID
          T     LB [AR1,P#0.0]; 
          L     B#16#2; //Datentyp Byte
          T     LB [AR1,P#1.0]; 
          L     #DestLength; //Anzahl von Datentyp
          T     LW [AR1,P#2.0]; 
          L     #DestDB; //Nummer des DB
          T     LW [AR1,P#4.0]; 
          L     #DestStart; //Bereichszeiger
          T     LD [AR1,P#6.0]; 
    //*** Den Datensatz kopieren
          CALL "BLKMOV" (
               SRCBLK                   := #SourceSFC,
               RET_VAL                  := #RET_VAL_SFC,
               DSTBLK                   := #DestSFC);
    //***************************************************************************************************
    // Ende
    //***************************************************************************************************
    //*** AR1-Register wiederherstellen
          LAR1  #AR1_Temp; 
          BE    ; 
    END_FUNCTION

  11. Folgender Benutzer sagt Danke zu guidokk für den nützlichen Beitrag:

    SIGGI (25.10.2008)

Ähnliche Themen

  1. Fügt ein neues Element in Array hinzu
    Von Gundam00 im Forum CODESYS und IEC61131
    Antworten: 21
    Letzter Beitrag: 28.09.2011, 08:12
  2. Array mit strukturierten Element Zur CSV-Datei
    Von ysh032 im Forum CODESYS und IEC61131
    Antworten: 0
    Letzter Beitrag: 14.09.2011, 14:23
  3. Array kopieren
    Von gloeru im Forum CODESYS und IEC61131
    Antworten: 5
    Letzter Beitrag: 05.03.2011, 20:06
  4. Array Element über Variable auslesen.
    Von FriedelM im Forum Simatic
    Antworten: 12
    Letzter Beitrag: 15.12.2010, 09:03
  5. byte in array kopieren [AWL]
    Von vierlagig im Forum Simatic
    Antworten: 14
    Letzter Beitrag: 17.11.2008, 22:55

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •