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

Seite 3 von 4 ErsteErste 1234 LetzteLetzte
Ergebnis 21 bis 30 von 32

Thema: Wertübergabe eines UDT an einer Funktion in SCL

  1. #21
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.846
    Danke
    402
    Erhielt 2.429 Danke für 2.025 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    Eine kleine Optimierung noch - du kannst bei dem Rückgabewert der Funktion auch schreiben :
    Code:
       MyFUNCTION := (MyARRAY1 <> MyARRAY2 ) ;

  2. #22
    Hotsch ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    04.07.2007
    Beiträge
    147
    Danke
    6
    Erhielt 13 Danke für 13 Beiträge

    Standard

    Guten Morgen,

    ich hab den Fehler jetzt etwas eingegrenzt. Die Wertübergabe mit BOOL scheint jetzt soweit zu funktionieren, aber bei der Übergabe mit DINT oder TIME gibt es noch ein Problem. Meine Function sieht im Moment so aus:
    Code:
    FUNCTION MYFunctionDINT : BOOL  
    VAR_INPUT
     TemptUDT:GlobalUDT;
     Array1 :DINT;
    END_VAR  
    VAR_IN_OUT     
     Array2 :DINT;
     Array3  :DINT
     DINT1   :DINT;
    END_VAR
    BEGIN
     IF TemptUDT.Option1 THEN
         Array2 :=DINT1;
     END_IF;
     IF TemptUDT.Option2 THEN
         Array3  :=DINT1;
     END_IF;    
     IF TemptUDT.Option3 THEN
         DINT1   :=Array2;
     END_IF;
     IF TemptUDT.Option4 THEN
         DINT1    := Array1;
         Array2   := Array1;
     END_IF;
     MYFunctionDINT:=(Array2 <> DINT1);
    END_FUNCTION
    Wenn ich jetzt an Array2 irgendeinen Wert des Arrays im FB übergebe mit dem Index größer 1, also z.B. MYArray[3] funktioniert das ganze so wie es soll. Bei MYArray[1] funktioniert die Option1, also die Übergabe vom DINT1 nach Array2 nicht, der Rest aber schon. Wenn ich den ganzen Vorgang beobachte, kann man erkennen dass der Wert in der Funktion geändert wird, aber die Übergabe an dem Array im FB funktioniert nicht. Zum Schluss hab ich den Code noch folgendermaßen geändert:

    Code:
    FUNCTION MYFunctionDINT : BOOL  
    VAR_INPUT
     TemptUDT:GlobalUDT;
     Array1 :DINT;
    END_VAR  
    VAR_OUTPUT
     Array2 :DINT;
    END_VAR
    VAR_IN_OUT         
     Array3  :DINT
     DINT1   :DINT;
    END_VAR
    BEGIN
     IF TemptUDT.Option1 THEN
         Array2 :=DINT1;
     END_IF;
     IF TemptUDT.Option2 THEN
         Array3  :=DINT1;
     END_IF;    
     IF TemptUDT.Option4 THEN
         DINT1    := Array1;
         Array2   := Array1;
     END_IF;
     MYFunctionDINT:=(Array2 <> DINT1);
    END_FUNCTION
    Dies funktioniert auch, aber da ich dann die Option3 nicht benutzen kann ist das keine endgültige Lösung.

  3. #23
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.846
    Danke
    402
    Erhielt 2.429 Danke für 2.025 Beiträge

    Standard

    eine schlaue Antwort habe ich da jetzt gerade nicht ...
    ich befürchte allerdings, dass das Problem jetzt aus dem aufrufenden FB kommt ...

    Das Beste wäre, wenn du dein Werk immer komplett postest ...

  4. #24
    Registriert seit
    27.05.2004
    Ort
    Thüringen/Berlin
    Beiträge
    12.299
    Danke
    545
    Erhielt 2.715 Danke für 1.962 Beiträge

    Standard

    Ich würde auf jeden Fall mal versuchen, nicht ein Element des Arrays zu übergeben, sondern dieses Element vorher an eine Temp-Variable des entsprechenden Typs übergeben und dann die Temp-Var an den FC legen.
    Gruß
    Ralle

    ... there\'re 10 kinds of people ... those who understand binaries and those who don\'t …
    and the third kinds of people … those who love TIA-Portal

  5. #25
    Hotsch ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    04.07.2007
    Beiträge
    147
    Danke
    6
    Erhielt 13 Danke für 13 Beiträge

    Standard

    Erstmal danke für eure Hilfe. Ich hab den Fehler jetzt auch gefunden. Ich übergebe die Arrays an die Funktion mit drei Indexvariablen. Jeweils eine für Array1, Array2 und Array3, wenn dieser Index gleich ist, dann ist z.B. Array1 = Array2 und dann funktioniert die Übergabe nicht.

    Jetzt hätte ich noch eine "kleine" Erweiterung meines Programms geplant, vielleicht könnt ihr mir dabei auch noch mal helfen. Im Moment hab ich vier Funktionen, jeweils eine für BOOL, DINT, INT und TIME. Der Code sieht so aus wie das was ich oben gepostet hab. Nun ist mein Plan das ich aus diesen vier Funktionen eine mache die dann sämtliche Datentypen verarbeiten kann. Ist so was mit Variablen vom Typ ANY möglich? Im Moment weigert sich der Compiler bei der Zeile:
    MYFunctionDINT:=(Array2 <> DINT1);
    Geändert von Hotsch (08.01.2009 um 10:25 Uhr)

  6. #26
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.846
    Danke
    402
    Erhielt 2.429 Danke für 2.025 Beiträge

    Standard

    ... das wäre mit dem ANY möglich. Du mußt diesen dann nur in deiner Funktion zerlegen und entsprechend auswerten um ann daraus wieder eine "greifbare" Variable zu machen. Dafür gibt es einen schönen Beitrag in der FAQ - ich habe da aber auch noch etwas, dass ich bei Bedarf posten könnte - das muss ich dann nur erst "rauskramen" ...

  7. #27
    Hotsch ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    04.07.2007
    Beiträge
    147
    Danke
    6
    Erhielt 13 Danke für 13 Beiträge

    Standard

    Wäre nett von dir, wenn du deine Sache mit dem Any-Zeiger posten könntest. Ich hab damit jetzt etwas rumgespielt, aber irgendwie klappt es nicht so, wie ich mir das vorstelle.

  8. #28
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.846
    Danke
    402
    Erhielt 2.429 Danke für 2.025 Beiträge

    Standard

    ... klar ... kein Problem
    Code:
    FUNCTION FC399 : VOID
    Title   = 'UP Any-Pointer zerlegen'  // UP Any-Pointer zerlegen
    AUTHOR  : 'Larry'
    VERSION : '0.1'
    
    //     Bausteinparameter
    VAR_INPUT
       // Eingangsparameter
       DatenQuelle : ANY ;
    END_VAR
    
    VAR_OUTPUT
       // Ausgangsparameter
       Daten_Mem : STRING [4] ;
       Daten_Typ : STRING [4] ;
       Daten_DB  : WORD ;
       Daten_Ptr : DWORD ;
       Daten_1W  : INT ;
       Daten_Len : INT ; 
    //   Inhalt : INT ;
    END_VAR
    
    VAR_TEMP
       // temporäre Variablen
       hDatenQuelle : ANY ;
       xDatenQuelle AT hDatenQuelle : STRUCT
                  ID_Code   : BYTE ;  // 10h für S7
                  DataTyp   : BYTE ;
                  Anzahl    : WORD ;
                  DB_Nr     : WORD ;
                  SpeicherPtr : DWORD ;
                  END_STRUCT ;
       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 ;
    END_VAR
    
    // --------------------------------------------------------------------------------------
    //     Anweisungsteil 
    // --------------------------------------------------------------------------------------
     
    BEGIN
       hDatenQuelle := DatenQuelle ;
       
       IF    xDatenQuelle.DataTyp = w#16#00 THEN Daten_Typ := 'Nil' ;   // Nil
       ELSIF xDatenQuelle.DataTyp = w#16#01 THEN Daten_Typ := 'X' ;     // Bool
       ELSIF xDatenQuelle.DataTyp = w#16#02 THEN Daten_Typ := 'B' ;     // Byte
       ELSIF xDatenQuelle.DataTyp = w#16#03 THEN Daten_Typ := 'Char' ;  // Char
       ELSIF xDatenQuelle.DataTyp = w#16#04 THEN Daten_Typ := 'W' ;     // Word
       ELSIF xDatenQuelle.DataTyp = w#16#05 THEN Daten_Typ := 'Int' ;   // Integer
       ELSIF xDatenQuelle.DataTyp = w#16#06 THEN Daten_Typ := 'DW' ;    // Double-Word
       ELSIF xDatenQuelle.DataTyp = w#16#07 THEN Daten_Typ := 'DInt' ;  // Double-Integer
       ELSIF xDatenQuelle.DataTyp = w#16#08 THEN Daten_Typ := 'Real' ;  // Real
       ELSIF xDatenQuelle.DataTyp = w#16#09 THEN Daten_Typ := 'Date' ;  // Date
       ELSIF xDatenQuelle.DataTyp = w#16#0A THEN Daten_Typ := 'TOD' ;   // Time-of-Day
       ELSIF xDatenQuelle.DataTyp = w#16#0B THEN Daten_Typ := 'Time' ;  // Time
       ELSIF xDatenQuelle.DataTyp = w#16#0C THEN Daten_Typ := 'S5T' ;   // S5Time
       ELSIF xDatenQuelle.DataTyp = w#16#0E THEN Daten_Typ := 'DT' ;    // Date-and-Time
       ELSIF xDatenQuelle.DataTyp = w#16#13 THEN Daten_Typ := 'Str' ;   // String
       END_IF ;
       IF    yDatenQuelle.Speicherbereich[0] = w#16#81 THEN Daten_Mem := 'E' ;   //Eingänge
       ELSIF yDatenQuelle.Speicherbereich[0] = w#16#82 THEN Daten_Mem := 'A' ;   // Ausgänge
       ELSIF yDatenQuelle.Speicherbereich[0] = w#16#83 THEN Daten_Mem := 'M' ;   // Merker
       ELSIF yDatenQuelle.Speicherbereich[0] = w#16#84 THEN Daten_Mem := 'DB' ;  // DB
       ELSIF yDatenQuelle.Speicherbereich[0] = w#16#85 THEN Daten_Mem := 'DI' ;  // Instanz-DB
       ELSIF yDatenQuelle.Speicherbereich[0] = w#16#86 THEN Daten_Mem := 'L' ;   // Lokaldaten
       ELSIF yDatenQuelle.Speicherbereich[0] = w#16#87 THEN Daten_Mem := 'LV' ;  // vorherige Lokaldaten
       END_IF ;
       Daten_DB  := xDatenQuelle.DB_Nr ;  
       Daten_Len := WORD_TO_INT (xDatenQuelle.Anzahl) ;
       Daten_Ptr := xDatenQuelle.SpeicherPtr AND dw#16#00FF_FFFF ;
       Daten_1W  := DWORD_TO_INT(SHR (IN:=Daten_Ptr , n:=3)) ;
    // --------------------------------------------------------------------------------------
    END_FUNCTION
    Dieses Script ist einfach nur ein Zerlege-Script. Es hat weiter keinen Sinn. Ich denke aber, dass du es für Versuche und als Basis für Weiteres gut hernehmen kannst ...

    Gruß
    LL

  9. #29
    Hotsch ist offline Erfahrener Benutzer
    Themenstarter
    Registriert seit
    04.07.2007
    Beiträge
    147
    Danke
    6
    Erhielt 13 Danke für 13 Beiträge

    Standard

    Was ich nicht ganz kapiere ist, wie ich den Inhalt von einem Anyzeiger auf einen anderen übertrage. Ich nehme mal an dies würde in deinem Programm mit der "xDatenQuelle.SpeicherPtr" geschehen. Aber als ich das bei mir ausprobiert hab mit:

    AnyPointer1.SpeicherPtr:=AnyPointer2.SpeicherPtr;

    ist die SPS in stopp gewechselt und die entsprechende Fehlermeldung war dann DB 4103 nicht geladen.

  10. #30
    Registriert seit
    22.03.2007
    Ort
    Detmold (im Lipperland)
    Beiträge
    11.846
    Danke
    402
    Erhielt 2.429 Danke für 2.025 Beiträge

    Standard


    Zuviel Werbung?
    -> Hier kostenlos registrieren
    ... das geht so nicht ...

    Du musst dir aus dem Ganzen wieder eine "richtige" Adresse "bauen".

    Also z.B. :
    Code:
    if Daten_Mem = 'M" then myWord := MW[Daten_1W] ; end_if ;
    Wenn du von einem Pointer auf den anderen übertragen willst dann könntest du auch Blockmove verwenden - das wäre dann deutlich schneller.

    ----------------

    Ich glaube nicht, dass du auf diese Weise wirklich das erhälst, was du vorhast. Vielleicht solltest du einfach mal deine komplette "Aufgabenstellung" offen legen. Dann könnte man sich gemeinsam dazu etwas einfallen lassen ...

    Gruß
    LL

Ähnliche Themen

  1. Funktion eines Impulsformers
    Von BennyK im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 25.03.2013, 22:15
  2. Pointer als Rückgabewert einer Funktion
    Von kai86 im Forum Simatic
    Antworten: 13
    Letzter Beitrag: 12.04.2010, 12:07
  3. OB1 mit Aufruf einer Funktion in SCL
    Von pinolino im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 29.04.2009, 17:18
  4. Länge eines String mit der LEN-Funktion auslesen
    Von baggerandy im Forum Simatic
    Antworten: 3
    Letzter Beitrag: 10.04.2009, 16:13
  5. Alle gesetzten Merker einer Funktion zurücksetzen
    Von dominik_Thesis im Forum Simatic
    Antworten: 15
    Letzter Beitrag: 25.11.2008, 13:07

Lesezeichen

Berechtigungen

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