# Wertübergabe eines UDT an einer Funktion in SCL



## Hotsch (6 Januar 2009)

Guten Morgen,

ich habe folgende Problemstellung. An einem Funktionsbaustein wird ein DatenbausteinUDT mit mehreren Bool-Werten übergeben. Nun wollte ich diesen UDT an einer Funktion übergeben die in dem Baustein aufgerufen wird. Dies funktioniert nicht da beim kompilieren folgende Fehlermeldung erscheint:

```
[COLOR=black][FONT=Verdana]Hilfe zur Meldung 15:4664[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Beschreibung:[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Es liegt ein Aufruf eines (S)FC oder (S)FB vor, bei dem eine Parameterversorgung nicht im Anwenderprogramm abgebildet werden kann, obwohl der Parameter mit einem Objekt zulässigen Datentyps versorgt wird.[/FONT][/COLOR]
[FONT=Verdana][COLOR=black]In STEP 7 gibt es bestimmte Kombinationen von Parametern (Formalparameter) und Objekten (hier Aktualparameter genannt), die nicht abgebildet werden können und daher nicht erlaubt sind. Eine genauere Beschreibung dieser Kombinationen sollte der STEP 7-Dokumentation bzw. dem S7-SCL-Handbuch entnommen werden.[/COLOR][/FONT]
[COLOR=black][FONT=Verdana]Behebung:[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Wählen Sie für den betreffenden Aktualparameter, falls möglich, eine andere Objektklasse (z.B. lokale Variable statt globaler Datenbereich, lokale Variable statt FC-Eingangsparameter, Bausteinbezeichner statt Variable, ...) und übersetzen Sie erneut. Wenn Sie mit dieser Methode nicht nach wenigen Versuchen eine erlaubte Kombination finden, empfiehlt sich das Nachschlagen in der STEP 7-Dokumentation.[/FONT][/COLOR]
```
 
Gibt es eine elegante Methode in SCL um dies zu beheben? Zur Not muss ich jeden einzelnen Bool Wert separat an die Funktion übermitteln, dies wäre allerdings unschön.


----------



## jck0815 (6 Januar 2009)

Hallo,
ein UDT ist nur eine Beschreibung. Also sowas wie ein type in C. Willst Du da Daten reinschreiben, musst du erst ein DB vom Typ deines UDT anlegen. Diesen kannst Du dann auch in Funktionen hinein/ausgeben.

Grüsse
Jens


----------



## Hotsch (6 Januar 2009)

Ich hab mich vielleicht etwas blöd ausgedrückt, also probiere ich es noch mal.
Ich hab in einem Globalen DB ein UDT angelegt. Diesen Übergebe ich an einem FB. Soweit klappt es auch noch ohne Probleme. Nun wollte ich aber in diesem FB die Daten weiter an einem FC übergeben und da versagt dann SCL und die obige Fehlermeldung erscheint.


----------



## Hansruedi (6 Januar 2009)

Hallo
Hast du den DB als "DB vom Typ" UDT xy angelegt oder hast du in einem DB eine Variable varX vom Typ UDT xy angelegt?

Gruss Hansruedi


----------



## Ralle (6 Januar 2009)

Du kannst eine UDT nicht an weitere FB durchreichen. Was du evtl. probieren könntest, ist etwas aufwendig. Im FB die selbe UDT als STAT deklarieren. Dann die IN-UDT per Block-Move in die Stat-UDT und diese an den internen FB übergeben. Für den Blockmove mußt du ja eine Any zusammenbauen, schau dazu mal hier in der FAQ. Aber du könntest auch gleich auf die UDT verzichten, statt dessen einen Any-Pointer auf den gewünschten Bereich als IN-Parameter anlegen und diesen dann jeweils in dem FB, in welchem er gebraucht wird per Blockmove auf Temp oder Stat-Variablen kopieren, die dann deine einzelnen Bits enthalten.


----------



## Hotsch (6 Januar 2009)

Danke, für die Antwort. Ich hab befürchtet, dass das nicht geht. Ich werd meine Bemühungen jetzt wohl einstellen, da mir der Aufwand etwas zu groß ist nur um eine Handvoll BOOL Variablen zu übergeben.


----------



## Larry Laffer (6 Januar 2009)

Hallo,
es reicht, wenn du in dem FB den UDT anlegst - es geht sogar im TEMP-Bereich. Die Übertragung der Werte geht dann ganz einfach in dem du schreibst :
	
	



```
interne_UDT := IN_UDT ;
 
call FC100 (IN_UDT := interne_UDT) :
```
um das hin- und herkopieren der UDT-Inhalte mußt du dich innerhalb von SCL nicht kümmern. Das übernimmt SCL automatisch für dich.
Wichtig ist hier lediglich, dass SCL den Aufbau der UDT kennt und das IN_UDT und interne_UDT vom gleichen Typ sind ...

Gruß
LL


----------



## Ralle (6 Januar 2009)

Ah ja, da hat Larry natürlich recht, wie immer hab ich die AWL-Variante hingeschrieben. In SCl ist das weniger aufwändig, das Prinzip aber das Selbe.


----------



## Hotsch (7 Januar 2009)

Die Wertübergabe funktioniert jetzt soweit einwandfrei, aber nun bin ich auf ein neues Problem gestoßen.
Also ich rufe eine Funktion mehrfach in einem FB auf. Der Funktion wird jeweils der oben genannte UDT übergeben, sowie einzelne BOOL Werte eines Arrays (z.B. MyArray[3]) als INOUT Variable. Nun werden die Rückgabewerte der Funktionen in einer if Anweisung abgefragt. Das Setzen der Array Variablen funktioniert nur unzuverlässig. Also bei einigen Arrays funktioniert es, bei anderen nicht. Ich denke mir dies ist so weil Step 7 wohl ein Problem damit hat, dass man Funktionen vom gleichen Typ mehrfach aufruft. Gibt es hierfür irgendeine einfache Möglichkeit um diese Geschichte zu realisieren. Als Beispiel hänge ich noch mal den prinzipiellen Code an, wie ich mir das gedacht habe.

```
[COLOR=black][FONT=Verdana]FUNCTION_BLOCK MYFUNCTIONBLOCK[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]VAR INPUT[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  UDT1    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
VAR
   MYARRAY:ARRAY[1..50] OF BOOL;
END_VAR
[COLOR=black][FONT=Verdana]VAR_TEMP[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  UDT2    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]BEGIN[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]UDT2:=UDT1;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]...[/FONT][/COLOR]
 
[COLOR=black][FONT=Verdana]IF (    [/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[2],Array2:=MYARRAY[4])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]   (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[30],Array2:=MYARRAY[32])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]   (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[34],Array2:=MYARRAY[36]))[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]) then[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]WERT:=TRUE;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_IF;[/FONT][/COLOR]
 
[COLOR=black][FONT=Verdana]END_FUNCTION_BLOCK[/FONT][/COLOR]
```


----------



## Larry Laffer (7 Januar 2009)

Hallo,
ein Mehrfach-Aufruf, wie du ihn beschrieben hast, funktioniert grundsätzlich. Was mich ein hier stört ist, dass du UDT2 im Temp-Bereich des FB's erstellt hast. Das könnte zu den beschriebenen Zufalls-Ergebnissen führen.
Es würde mich aber auch interessieren, was MyFunction intern so macht ... Das wäre dann die nächste Möglichkeit ...

Gruß
LL


----------



## Ralle (7 Januar 2009)

Hm, aber er füllt ja die Temp-UDT am Anfang bit den Daten der UDT aus dem Input. Mehrfachaufruf gerade von Funktionen sollte gehen, aber ich habe schon Probleme gehabt, wenn Inputs an den Funktionen gemischt aus unterschiedlichen Quellen (z.Bsp. unterschiedliche DB und Temp) angelegt wurden. Hatte dann den Eindruck, daß die DB wild durcheinander beschrieben wurden. Kann man denn mal versuchsweise UDT2 als Stat anlegen?

PS: Wird in der Funktion evtl. mit dem AR2 gearbeitet? Auf jeden Fall ist es sinnvoll am Anfang der Funktion AR1 und AR2 zu sichern und am Ende diese wieder zu restaurieren.


----------



## Larry Laffer (7 Januar 2009)

Ralle schrieb:


> Hm, aber er füllt ja die Temp-UDT am Anfang bit den Daten der UDT aus dem Input.


 
Das ist (denke ich) das Problem ... 
Wir wissen ja gar nicht, was MyFunction nun wirklich tut ... Vielleicht ergänzt es auch nur den UDT2 mit den neuen Werten ... oder ... oder ... oder ...


----------



## vierlagig (7 Januar 2009)

ich hätte da mal sone einfache, strukturelle anmerkung:

- ich würde myfunction nicht als bedingung sondern als funktion vor der if-abfrage aufrufen, dass darf dann auch mehrfach sein.

- dadurch gehst du sicher, dass alle werte verarbeitet werden und brauchst am ende nur noch die elemente deines arrays in einer einfachen logischen verknüpfung verdaddeln, kannst dir also das IF sparen

- wenn du das nicht machen willst, so empfehle ich dir aber mindestens einen else-zweig in dem wert (der wahrscheinlich im stat, inout oder out liegt) auf false gesetzt wird.


----------



## Hotsch (7 Januar 2009)

Also MYFunction ist nur eine Abfolge von IF Anweisungen. Die Vergleichen die UDT Werte auf TRUE und schieben dann je nach Fall die Werte von MYArray[x] in MYArray[y] oder umgekehrt. 

```
FUNCTION MYFUNCTION :BOOL
VAR INPUT
      UDTFUNCTION:GLOBALUDT
end_VAR
VAR INOUT
      ARRAY1:BOOL;
      ARRAY2:BOOL;
end_VAR
BEGIN
if UDTFUNCTION.TEACH then
  ARRAY1:=ARRAY2;
end_IF;
if MYARRAY1<>MyARRAY2 then
   MYFUNCTION:=TRUE;
else MYFUNCTION:=FALSE;
end_function
```
Wenn ich diese IF Anweisungen direkt in dem FB Aufrufe dann funktioniert das ganze Programm auch genau so wie es soll, aber sobald ich Funktionen einsetzte wird es für mich nicht mehr nachvollziehbar.

Ich hab den UDT2 jetzt auch in den statischen Speicher verlegt, aber leider ohne Erfolg.


----------



## Larry Laffer (7 Januar 2009)

Sorry,
ich reviediere mich. Der Fehler ist, dass das UDT2 in IN-Parameter ist. Es müßte ein IN_OUT-Parameter sein, da ja mit den veränderten Werten im nächsten Zyklus weitergearbeitet werden soll ...



```
[COLOR=black][FONT=Verdana]FUNCTION_BLOCK MYFUNCTIONBLOCK[/FONT][/COLOR]
[FONT=Verdana][COLOR=red][B]VAR INOUT[/B][/COLOR][/FONT]
   [COLOR=black][FONT=Verdana] UDT1    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
VAR
   MYARRAY:ARRAY[1..50] OF BOOL;
END_VAR
[COLOR=black][FONT=Verdana]VAR_TEMP[/FONT][/COLOR]
[COLOR=black][FONT=Verdana] UDT2    :GLOBALUDT;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_VAR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]BEGIN[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]UDT2:=UDT1;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]...[/FONT][/COLOR]
 
[COLOR=black][FONT=Verdana]IF (    [/FONT][/COLOR]
[COLOR=black][FONT=Verdana] (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[2],Array2:=MYARRAY[4])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[30],Array2:=MYARRAY[32])) OR[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]  (MYFUNCTION(MYUDT:=UDT2, Array1:=MYArray[34],Array2:=MYARRAY[36]))[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]) then[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]WERT:=TRUE;[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]END_IF;[/FONT][/COLOR]
 
[FONT=Verdana][COLOR=red][B]UDT1:=UDT2;[/B][/COLOR][/FONT]
[COLOR=black][FONT=Verdana]END_FUNCTION_BLOCK[/FONT][/COLOR]
```
Wie sieht es jetzt aus ?

Gruß
LL


----------



## Hotsch (7 Januar 2009)

Ich hab mich da vertippt, UDT1 ist als INOUT deklariert und die letzte Zeile UDT1:=UDT2 hab ich auch vergessen. Sorry


----------



## Larry Laffer (7 Januar 2009)

hat es funktioniert ?


----------



## Hotsch (7 Januar 2009)

Nein, es hat nicht funktioniert. Was ich meinte ich hatte das schon bei der ersten Version so drin, hab nur vergessen das bei dem Code oben einzufügen.


----------



## Hotsch (7 Januar 2009)

Dann hätte ich noch eine andere Frage, wäre es egal wenn ich statt Array vom Typ BOOL, Arrays vom Typ TIME,DINT oder INT verwende? Oder gibt es da Beschränkungen die man beachten muss? Also die Funktion würde dann so aussehen:

```
FUNCTION MYFUNCTION :BOOL
VAR INPUT
      UDTFUNCTION:GLOBALUDT
end_VAR
VAR INOUT
      ARRAY1:[B]TIME[/B];
      ARRAY2:[B]TIME[/B];
end_VAR
BEGIN
if UDTFUNCTION.TEACH then
  ARRAY1:=ARRAY2;
end_IF;
if MYARRAY1<>MyARRAY2 then
   MYFUNCTION:=TRUE;
else MYFUNCTION:=FALSE;
end_function
```


----------



## Larry Laffer (7 Januar 2009)

Du kannst erstmal grundsätzlich jeden Variablentyp übergeben.

Zu deinem Problem nochmal :
Bist du sicher, dass deine Function korrekt funktioniert ?
Was ist der Sinn derselben ? Das habe ich aus dem Code nicht nachvollziehen können ...


----------



## Larry Laffer (7 Januar 2009)

Eine kleine Optimierung noch - du kannst bei dem Rückgabewert der Funktion auch schreiben :
	
	



```
MyFUNCTION := (MyARRAY1 <> MyARRAY2 ) ;
```


----------



## Hotsch (8 Januar 2009)

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:

```
[COLOR=black][FONT=Verdana]FUNCTION MYFunctionDINT : BOOL  [/FONT][/COLOR]
[FONT=Verdana][COLOR=black]VAR_INPUT[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] TemptUDT:GlobalUDT;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] Array1 :DINT;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]END_VAR  [/COLOR][/FONT]
[FONT=Verdana][COLOR=black]VAR_IN_OUT     [/COLOR][/FONT]
[FONT=Verdana][COLOR=black] Array2 :DINT;[/COLOR][/FONT]
[COLOR=black][FONT=Verdana] Array3  :DINT[/FONT][/COLOR]
[COLOR=black][FONT=Verdana] DINT1   :DINT;[/FONT][/COLOR]
[FONT=Verdana][COLOR=black]END_VAR[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]BEGIN[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] IF TemptUDT.Option1 THEN[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]     Array2 :=DINT1;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] END_IF;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] IF TemptUDT.Option2 THEN[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]     Array3  :=DINT1;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] END_IF;    [/COLOR][/FONT]
[FONT=Verdana][COLOR=black] IF TemptUDT.Option3 THEN[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]     DINT1   :=Array2;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] END_IF;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] IF TemptUDT.Option4 THEN[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]     DINT1    := Array1;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]     Array2   := Array1;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] END_IF;[/COLOR][/FONT]
[FONT=Verdana][COLOR=black] MYFunctionDINT:=(Array2 <> DINT1);[/COLOR][/FONT]
[FONT=Verdana][COLOR=black]END_FUNCTION[/COLOR][/FONT]
```
 
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:


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


----------



## Larry Laffer (8 Januar 2009)

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 ...


----------



## Ralle (8 Januar 2009)

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.


----------



## Hotsch (8 Januar 2009)

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);


----------



## Larry Laffer (8 Januar 2009)

... 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" ...


----------



## Hotsch (8 Januar 2009)

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.


----------



## Larry Laffer (8 Januar 2009)

... klar ... kein Problem
	
	



```
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


----------



## Hotsch (8 Januar 2009)

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.


----------



## Larry Laffer (8 Januar 2009)

... das geht so nicht ...

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

Also z.B. :
	
	



```
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


----------



## Ralle (9 Januar 2009)

Ich hatte das auch mal probiert, also einen Inputparameter für unterschiedliche Variablen nutzen. Leider geht das, wenn überhaupt nur mit Any, denn der Parametertyp kann nicht zur Laufzeit Bool, Int oder Real sein. Ich hatte gemeint irgendwann genau das aber mal bei einem Siemens-Baustein gesehen zu haben, fand diesen aber nicht mehr, der war wohl auch nicht in AWL oder SCL programmiert worden! Hab das dann so gelöst, daß ich dem Baustein 3 Eingänge verpaßt habe und ihm dann mit einem 4. Eingang mitgeteilt habe, welchen er nutzen soll. War auch nicht so doll, denn mit einem Output hat man dann evtl. wieder das selbe Problem.


----------



## Hotsch (10 Januar 2009)

Nochmal als Erklärung was ich überhaupt bezweckt habe. 
Ich wollte mir ein einfaches Array-Handling basteln. Im Moment sieht das Programm so aus das ich fünf unterschiedliche IF Anweisungen hab und je nach dem Zustand der Variablen in meinem UDT wird die Entsprechende IF Anweisung aufgerufen und Daten werden innerhalb eines Arrays kopiert. Da ich dies mit mehren Arrays machen, werden die IF Anweisungen recht lang und blöd zu handeln. Nun war meine Idee, dass ich eine Funktion für jedes Array aufrufe. Dieser Funktion wird das UDT, sowie der allererste Array wert übergeben (z.B. MyArray[1]), außerdem noch weitere int Variablen die dann festlegen was kopiert werden soll (z.B. Index1 :=3, Index2:=6, daraus folgt dann MyArray[6]:=MyArray[3]). Mein Haupthindernis im Moment ist das ich den Inhalt auf dem der Anypointer zeigt, nicht vergleichen kann. Außerdem müsste ich dann noch die Adresse des Arrays je nach Index anpassen und dem Anypointer übergeben. Da der Umgang mit Pointern in Step7 meiner Meinung nach sehr zu wünschen übrig lässt, werden ich das Vorhaben wohl aufgeben. Da selbst wenn ich die Funktion irgendwie hin bekomme, sie wahrscheinlich so umfangreich und langsam ist das es nicht wirklich einen Vorteil bringt. Aber zumindest habe ich was daraus gelernt .


----------

