# Scl-any Pointer



## johnij (1 November 2007)

Hallo zusammen,
noch einmal eine Frage zum Any Zeiger:
Beisp:

Quelle : ANY;
QuellPointer AT Quelle : STRUCT
SyntaxID : BYTE; 
Datentyp : BYTE;
db_Nummer : INT; // Das entspricht 2 Byte
BytePointer : DWORD;// Das entspricht 4 Byte
END_STRUCT; 

// D.h QuellPointer soll 1+1+2+4=8 Byte belegen ????

Begin 
Quelle:= DB2.DBX0.0

...
Ist es richtig in dem Fall zu sagen :
p#DB2.DBx0.0 Byte 8 (AWL-mäßig) und dass:
SyntaxID, Datentyp (Byte0,Byte1):=DB2.DBW0 [grob geschrieben]
db_Nummer :=DB2.DBW2
BytePointer :=DB2.DBW4
????????????

Danke im Voraus

johnij


----------



## Larry Laffer (1 November 2007)

Hallo,
wenn du an deinen Baustein per ANY-Pointer "P#DB2.DBX0.0" übergibst, dann steht :
im Byte 0 : 10h
im Byte 1 : 01h
im Byte 2,3 als WORD = 0
im Byte 4,5 als WORD = 02 (für DB 2)
im Byte 6 : 84h
im Byte 7,8,9 = 0 (für DBX 0.0)

besser erklären würde sich wenn du übergibst "P#DB2.DBX5.4 Byte 10"
Dann würdest du erhalten :
m Byte 0 : 10h
im Byte 1 : 01h
im Byte 2,3 als WORD = 10 (Anzahl der Bytes)
im Byte 4,5 als WORD = 02 (für DB 2)
im Byte 6 : 84h
im Byte 7,8 = 0 
 im Byte 9 = b#101100 (für DBX 5.4)


----------



## Ralle (1 November 2007)

johnij schrieb:


> Hallo zusammen,
> noch einmal eine Frage zum Any Zeiger:
> Beisp:
> 
> ...



Ähm, ich würde sagen falsch.
Scheint, du hast das noch nicht richtig verstanden. 
Der Any-Typ ist nur ein Zeiger auf einen Datenbereich, wobei er so universell ist, daß er Beginn, Länge, Typ gleich mit in sich enthält.
Du hast das so aufgeschrieben, als würde der Zeiger auf sich selbst zeigen, was man im Extremfalle natürlich machen kann, was aber auch wenig Sinn hat. 


Im Normalfall geht man so vor:

Anlegen eines Any als IN oder TEMP (was anderes geht auch nicht) eines FC oder FB.
Füllen der Daten des Any-Pointers, also 

SyntaxID : BYTE; 
Datentyp : BYTE;
db_Nummer : INT;
BytePointer : DWORD;

Aufruf z.Bsp des SFC20 (BlkMove), der diesen Typ als Input erwartet.


----------



## Larry Laffer (1 November 2007)

Ralle schrieb:


> Im Normalfall geht man so vor:
> 
> Anlegen eines Any als IN oder TEMP (was anderes geht auch nicht) eines FC oder FB.
> Füllen der Daten des Any-Pointers, ...



... oder wenn man mit SCL und dem Befehl AT herumspielen möchte, dann eine SCL-Function einen Pointer übergeben, ihn mit Hilfe von der AT-Sicht "zerhacken" in Einzel-Variablen und sich die zurückgeben lassen, damit man sieht, was daraus wird ...


----------



## johnij (1 November 2007)

Larry Laffer schrieb:


> Hallo,
> 
> besser erklären würde sich wenn du übergibst "P#DB2.DBX5.4 Byte 10"
> Dann würdest du erhalten :
> ...


----------



## Kai (1 November 2007)

johnij schrieb:


> Muss das nicht im Byte 1: 02 h (Datentyp= Byte) sein ???
> denn 01h= Datentyp BOOL
> Gruß


 
Richtig, siehe auch hier:

http://www.sps-forum.de/showthread.php?t=12923

Gruß Kai


----------



## johnij (2 November 2007)

Danke an alle,
ich habe bissel bei Siemens reingeguckt. Ich habe jetzt keine Angst mehr
vor dem ANY-Zeiger  .

Prima Forum.

Gruß johnij


----------



## Florian_Niedermaier (20 November 2007)

Ist es den nun möglich mit dem "AT" Befehl oder einem anderen Befehl Manipulationen im ANY vorzunehemen?

wie ist es beispielsweise möglich aus den DBX5.4 ein 7.0 zu machen?

Gruß
Flo


----------



## Ralle (20 November 2007)

Ja, das ist möglich, kann man doch aus den Beiträgen oben ersehen, oder? Zuerst muß man aber dazu wissen, wie man mit dem Any selbst umgehen kann (siehe dazu in unserer FAQ, da ist ein super Beitrag drin, der das erklärt). Dann nimmt man den AT-Befehl und legt damit eine Sicht auf seinen Any, schnappt sich die Variable Bytepointer und addiert da 12 dazu (von 5.4 bis 7.0 sind es 12 Bit, der Bytepointer stellt ja schon die Adresse inkl. Bits dar, siehe FAQ).


----------



## Kandiszucker (21 November 2007)

*AnyPointer in SCL*

Ich hab das mit dem AnyPoibter so gemacht (funktioniert tatsächlich).

Am Anfang hatte ich auch den ANY "von Hand" gefüllt - und mir fast jedesmal "einen abgebrochen". Das braucht manb gar nicht, der SCL-Compiler macht das alles automatisch 

Die Typen von Siemens kennen sich da teils auch überhaupt nicht aus ....


```
[FONT=Courier New]TYPE AnyPointer
    STRUCT
        byId    : BYTE;
        byTyp   : BYTE;
        iCount  : INT;
        iDbn    : INT;
        dwPtr   : DWORD;
    END_STRUCT;
END_TYPE
[/FONT]


.....
[FONT=Courier New]VAR_TEMP
    AnyPniRx  : AnyPointer;
    pAnyRx  AT AnyPniRx : ANY;
    
    pAnyRx := "Glob".TcpRxFsm.RxBuf.Daten;
                
    AG_RECV (ID      := 1,
             LADDR   := #16#0100,
             RECV    := pAnyRx,
             NDR     := bDone, 
             ERROR   := bError, 
             STATUS  := wStatus,
             LEN     := iLen
    );
```

[/FONT]


----------



## Larry Laffer (22 November 2007)

@Kandiszucker:
Das mit der TYPE-Deklaration in deinem Code-Beispiel finde ich interessant. Leider funktioniert das (bei mir) nicht.
Wo machst du diese Deklaration ?

Gruß
LL


----------



## Kandiszucker (22 November 2007)

*Hallo LarryLaffer!*

Was hast Du für Probleme mit dem Type?


Die TYPE Deklaration ist in SCL ja nichts anderes als die Deklaration eines UDT. 

Man muß natürlich in der Symboltabelle das Symbol eintragen.

Ansonsten hab ich das in einer eigenen SCL-Quelle gemacht, in der auch der Datenbereich "Glob" definiert wurde.

Durch die Zuweisung von 

pAnyRx := "Glob".TcpRxFsm.RxBuf.Daten

füllt der Compiler den AniPniRx mit *allen* Infos über (das Array) "Glob".TcpRxFsm.RxBuf.Daten, also DB, Länge, Typ usw.

Damit braucht man "von Hand" den AnyPointer nicht zu füllen.

Ich hab das probiert, man kann auch Datenbereiche im InstanzDB oder auch in den lokalen Variablen (also Stack) angeben.


Ich hab übrigens S7 SCL V5.3 SP3 (vor kurzem erst angeschafft).


----------



## Larry Laffer (22 November 2007)

Danke für die Rückmeldung ...
Leider hast du die Frage anscheinend nicht verstanden.
Du brauchst mir nicht zu erklären wie der AT-Befehl in SCL funktioniert und auch nicht wie man den ANY-Pointer auf diesem Weg anwendet oder zuweist. Selbstverständlich weis ich als alter Pascal-Programmierer auch, was TYPE bedeutet.

Ich habe dein TYPE-Beispiel mal in einen FB von mir eingebaut. Wenn ich das dann übersetze erhalte ich die Meldung "Der neue Bausteinbeginn ist vor dem Bausteinende. Baustein: xAnyPointer".
xAnyPointer ist dem dem Fall mein TYPE.

Vielleicht haber ich mich jetzt klarer ausgedrückt ...


----------



## Kandiszucker (22 November 2007)

*Hallo Larry!*

Was ist denn das für eine merkwürdige Meldung 

"Der neue Bausteinbeginn ist vor dem Bausteinende. Baustein: xAnyPointer".

Damit kann ich nun nix anfangen.

Ich hab den Codeauschnitt so aus meinem Prog rauskopiert. Hier nochmal komplett:


```
FUNCTION TcpFSM : VOID
VAR_TEMP
    AnyPniRx  : AnyPointer;
    pAnyRx  AT AnyPniRx : ANY;
    
    AnyPniTx  : AnyPointer;
    pAnyTx  AT AnyPniTx : ANY;
    
    bDone   : BOOL;
    bError  : BOOL;
    wStatus : WORD;
    iLen    : INT;
    ch      : CHAR;
    i       : INT;
        
END_VAR
VAR
END_VAR
........
```

Deine Fehlermeldung kann ich mir nun wirklich nicht erklären. Tut mir leid ....


----------



## kiestumpe (22 November 2007)

Hallo Larry,

du musst deine Type-Definition(en) vor der Definition des FB's machen, dann funktioniert's auf jeden Fallen - nicht innerhalb !


----------



## Kandiszucker (22 November 2007)

*Kiestumpe, Larry!*

Ähhhmmmm......

Durch:


> Ansonsten hab ich das in einer eigenen SCL-Quelle gemacht, in der auch der Datenbereich "Glob" definiert wurde.



hatte ich das vorausgesetzt.


----------



## Larry Laffer (22 November 2007)

...?
Selbstverständlich habe ich BEIDE Varianten schon einmal ausprobiert.
So schnell gebe ich auch nicht auf ...
Wie deklarierst du deinen TYPE denn symbolisch ? Vielleicht ist das ja der Schlüssel ...

Gruß
LL


----------



## Kandiszucker (22 November 2007)

*Larry!*

Hallo Larry,

symbolisch definiere ich das im Symboleditor als UDT 2, siehe Anhang.

Müßte normalerweise kein Problem sein.... 

Wenn ich das Symbol nicht definiert habe, kriege ich eine andere Fehlermeldung als Du: "Symbolischer Bausteinname nicht bekannt..." oder ähnlich.

Welche SCL-Version benutzt Du denn? Vielleicht liegts da dran?
Benutzt Du denn überhaupt TYPEs?

Am Anfang hatte ich in etwa auch folgendermassen rumexperimentiert. Den AnyPointer muss man nicht unbedingt als TYPE definieren.
(In Wirklichkeit ist der Anypointer eigentlich eine struct, m.E.) Den Funktionen wird eigentlich ein Pointer auf so eine struct übergeben (aus C Sichtweise heraus)



```
//------------------------------------------------------------------------------------------------------
//
//  NumberOfElements
//
//  Liefert Anzahl Arraykomponenten zurück.
//
//------------------------------------------------------------------------------------------------------
FUNCTION NumberOfElements : INT     //sizeof FC90
VAR_INPUT
    pArrayName:ANY;
END_VAR
VAR_TEMP
    pAny : ANY;
    MyAny AT pAny : STRUCT
            ID  : BYTE;
            TYP : BYTE;
            NUM : INT;
            DBN : INT;
            PTR : DWORD;
        END_STRUCT;
END_VAR
BEGIN
    pAny := pArrayName;
    NumberOfElements := Myany.NUM;
END_FUNCTION
```


----------



## Larry Laffer (22 November 2007)

Kandiszucker schrieb:


> Am Anfang hatte ich in etwa auch folgendermassen rumexperimentiert. Den AnyPointer muss man nicht unbedingt als TYPE definieren.
> (In Wirklichkeit ist der Anypointer eigentlich eine struct, m.E.) Den Funktionen wird eigentlich ein Pointer auf so eine struct übergeben.


 
... so habe ich das bisher auch gehandhabt. Das mit dem TYPE hatte mir ganz gut gefallen und da dachte ich "da hak' doch mal nach ...".
Das Ding als UDT in der Symbolik zu hinterlegen ist mir natürlich noch nicht eingefallen ...

SCL habe ich übrigens wie du ...

Gruß
LL


----------



## Kandiszucker (22 November 2007)

Hat's denn nun geklappt oder kriegst Du die Fehlermeldung immer noch?


----------



## kiestumpe (22 November 2007)

*Type und Struct*

Hallo Larry und Kandis,

ich glaub, da liegt ein Verständnisproblem zwischen den beiden Begriffen vor.
Ein Type bzw. ein user-defined-type setzt sich aus einem struct oder einem nativen Datentyp zusammen. Der Vorteil des UDT's besteht jedoch darin, dass man Variablen dieser Struktur im ganzen Projekt wieder anlegen kann.
Macht man das, wie oben jedoch explizit in der Variablendeklaration, so hat man nur eine Variable mit genau dieser Struktur definiert - und müsste dann per copy-paste das anderweitig mitziehen - kein guter Stil.

Was ich mit ausserhalb meinte sieht so aus:

(Das Symbol muss man in der Tat in der Symboltabelle anlegen, will Step7 im SCL-Editor nicht)

(Die beiden Typen haben was mit dem ppo3-Protokoll von Umrichtern zu tun-daher auch die Definition mit UDT1300 anstatt dem Symbol)

TYPE UDT1300

  STRUCT
  //  Typbeschreibung
  // High-Byte Bit 8-15
    Jog1_Ein :BOOL; // Festdrehzahlen-Par1
    Jog2_Ein : BOOL; // Festdrehzahlen-Par2
    Daten_Ok : BOOL; // 0 = Daten ungültig
    Freq_Korr_auf : BOOL; 
    Freq_Korr_ab : BOOL;
    Param_lsb : BOOL;
    Param_msb: BOOL;
    Reversierung : BOOL;
// Low-Byte   Bit 0-7 
    EIN1: BOOL;// 0 = Rampenstopp
    EIN2: BOOL;// 0 = Motorfreilaufstopp
    EIN3: BOOL; // 0= Schnellstop mit Rampenzeit
    kein_Freilauf : BOOL; // 0 = Freilauf
    Rampe : BOOL; // 0 = Schnellstop
    Rampe_benutzen : BOOL; // 0 = Frequenz speichern (freeze)
    Start : BOOL; // 0 = Rampenstopp
    Reset : BOOL;

  END_STRUCT
END_TYPE

TYPE UDT1302

  STRUCT
//  Typbeschreibung
// High-Byte Bit 8-15
     Drehzahl_eq : BOOL;
    Bus :BOOL;
    FrequenzLim_Ok : BOOL;
    Betrieb : BOOL;
    gestoppt : BOOL;
    Spannung_nok : BOOL;
    Moment_nok: BOOL;
    Timer_nok : BOOL;
// Low-Byte  Bit 0-7 

    CNTRL_OK: BOOL;
    FU_OK: BOOL;
    Aktiv: BOOL;
    Abschalten: BOOL;
    EIN_2 : BOOL;
    EIN_3 : BOOL;
    Start_NOK : BOOL;
    Warnung : BOOL;

  END_STRUCT
END_TYPE


FUNCTION_BLOCK FB1202
....

VAR_INPUT
  // Eingangsparameter
    STW : WORD ; // Steuerword
    ppo3_STW AT STW: UDT1300 ; //
....


----------



## Larry Laffer (23 November 2007)

Kandiszucker schrieb:


> Hat's denn nun geklappt oder kriegst Du die Fehlermeldung immer noch?


 
... ist OK, so würde es gehen ...
Leider ist es nicht so ganz das, was ich mir erhofft habe :
TYPE-Deklaration nur innerhalb der FC , FB ohne den TYPE noch anderweitig bekannt zu machen. So könnte ich den ANY-Pointer auch gleich als UDT in mein Projekt einfügen - wird es ja letztendlich auch.
Schade ... aber trotzdem Danke ...

Gruß
LL


----------



## Larry Laffer (23 November 2007)

... Nachtrag ...
Nachdem ich meinen Beitrag verfasst und abgesendet hatte konnte ich auch auf einmal den Beitrag von Kiestumpe sehen, der zwar in der Rubrik "Simatic" die ganze Zeit schon als vorhanden aufgelistet wurde, für mich aber irgendwie nicht zugänglich war.
Nun denn - Im Grunde schreibt Kiestumpe genau das, was ich eben auch schon geschrieben habe ...


----------



## Zefix (23 November 2007)

Larry Laffer schrieb:


> ... Nachtrag ...
> Nachdem ich meinen Beitrag verfasst und abgesendet hatte konnte ich auch auf einmal den Beitrag von Kiestumpe sehen, der zwar in der Rubrik "Simatic" die ganze Zeit schon als vorhanden aufgelistet wurde, für mich aber irgendwie nicht zugänglich war.
> Nun denn - Im Grunde schreibt Kiestumpe genau das, was ich eben auch schon geschrieben habe ...


 
Jaja, ich kenn das, meistens so nach 5-6 Bier


----------



## Larry Laffer (23 November 2007)

@Zefix:
Du bist ja böse ... aber was solls, ich sehe gerade, dass du heute Geburtstag hast und da darf man das ...
Also auf diesem Wege dann :
:sm20: 
Herzlichen Glückwunsch zum Geburtstag ... und gönn dir das oben genannte, damit du auch bei allen Beiträgen klar siehst ...

Gruß
LL


----------



## kiestumpe (23 November 2007)

Ich hatte meinen Beitrag definitiv auch nicht gesehen - inzwischen ist er drin.
Muss mal den Wirt am nächsten Donnerstag-mittag fragen, was das für ein Bier war, das ich da zu Mittag bekommen habe


----------



## TempeltonPeck (24 Februar 2017)

Hallo,

Ich greife das Thema mal wieder auf. Ich möchte mir eine Funktion schreiben die mir ein beliebigen Speicherbereich von A nach B kopiert. Als Input Variable gibt der Nutzer den Datentyp, Speicherbereich usw. für die Quelle und das Ziel an. Wahlweise soll auch ein kompletter DB kopiert werden können.


```
TYPE "Pointer"VERSION : 0.1
   STRUCT
      SyntaxID : Byte; 
      DataTyp : Byte;  
      Laenge : Int;
      DB_Nr : Int;
      "Pointer" : DWord;
   END_STRUCT;


END_TYPE


FUNCTION "FC138_Kopieren" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      DatenTyp : Byte;
      Quell_Speicherbereich : DWord;
      Quell_Bereich : UInt;
      Laenge : UInt; 
      Ziel_Speicherbereich : DWord;
      Ziel_Bereich : UInt;
      Quell_DB_Nr : UInt; 
      Ziel_DB_Nr : UInt;  
      DB_Komplett : Bool;
   END_VAR


   VAR_TEMP 
      Adr_max : UInt;
      ATTR_DB : Byte;
      P_Quelle : "Pointer";
      Any_P_Quelle AT P_Quelle : Any;
      P_Ziel : "Pointer";
      Any_P_Ziel AT P_Ziel : Any;
      RetVal_BKLM : Int;
      RetVal_ATTR_DB : Int;
      RetVal_BLKMOV : Int;
   END_VAR




BEGIN
    
    #P_Quelle.SyntaxID := b#16#10;
    #P_Ziel.SyntaxID := b#16#10;
    
    #P_Quelle.DataTyp := #DatenTyp;
    #P_Ziel.DataTyp := #DatenTyp;
    
    #P_Quelle."Pointer" := #Quell_Speicherbereich;
    #P_Ziel."Pointer" := #Ziel_Speicherbereich;
    
    #P_Quelle.Laenge := #Laenge;
    #P_Ziel.Laenge := #Laenge;
    
    #P_Quelle.DB_Nr := #Quell_DB_Nr;
    #P_Ziel.DB_Nr := #Ziel_DB_Nr;
    
    // Wenn DB-Bereich und Komplett kopieren gewählt
    IF #DB_Komplett = TRUE AND #Quell_DB_Nr >= 0 THEN
        #RetVal_ATTR_DB := ATTR_DB(REQ := TRUE, DB_NUMBER := #Quell_Bereich, DB_LENGTH => #Adr_max, ATTRIB => #ATTR_DB); // Atribute des Quell DB lesen
        #P_Quelle.Laenge := #Adr_max;
        #P_Ziel.Laenge := #Adr_max;
    END_IF;
    
    #Any_P_Quelle := #P_Quelle;
    #Any_P_Ziel := #P_Quelle;
    
    // Kopieren
    #RetVal_BLKMOV := BLKMOV(SRCBLK := #Any_P_Quelle, DSTBLK => #Any_P_Ziel);
END_FUNCTION
```

Zum testen wollte ich von ein Byte von MB5 nach MB7 kopieren.


```
DatenTyp : b#16#2
      Quell_Speicherbereich : b#16#83
      Quell_Bereich : 5;
      Laenge : 1 
      Ziel_Speicherbereich : b#16#83
      Ziel_Bereich : 7
      Quell_DB_Nr : 0
      Ziel_DB_Nr : 0 
      DB_Komplett : FALSE;
```

Leider wird das kopieren nicht ausgeführt und Blockmove gibt mir keinen Fehler zurück (RetVal = 0).

Hat jemand einen Tipp für mich?


----------



## PN/DP (24 Februar 2017)

TempeltonPeck schrieb:


> Zum testen wollte ich von ein Byte von MB5 nach MB7 kopieren.
> 
> 
> ```
> ...



Quell_Bereich und Ziel_Bereich verwendet Dein Code gar nicht.
Quell_Speicherbereich und Ziel_Speicherbereich müssten DW#16#83000000 sein

#Quell_Speicherbereich muß sein: DW#16#83000000 + #Quell_Bereich * 8
#Ziel_Speicherbereich muß sein : DW#16#83000000 + #Ziel_Bereich * 8



TempeltonPeck schrieb:


> ```
> [COLOR="#FF0000"]    #Any_P_Quelle := #P_Quelle;
> #Any_P_Ziel := #P_Quelle;[/COLOR]
> ```


Die Zuweisungen sind überflüssig, weil die Variablen schon per "AT" auf den selben Adressen liegen und deshalb den selben Inhalt haben.

Harald


----------



## TempeltonPeck (25 Februar 2017)

PN/DP schrieb:


> Quell_Bereich und Ziel_Bereich verwendet Dein Code gar nicht.
> Quell_Speicherbereich und Ziel_Speicherbereich müssten DW#16#83000000 sein
> 
> #Quell_Speicherbereich muß sein: DW#16#83000000 + #Quell_Bereich * 8
> ...




Danke für die Tipps. Werde ich testen wenn ich wieder im Büro bin.
 #Any_P_Quelle := #P_Quelle;
 #Any_P_Ziel := #P_Quelle;

Das diese eigentlich überflüssig ist dachte ich mir schonaber ohne diese ging die CPU in den Stopp da auf ein nicht existenten Speicherbereich zu gegriffen wurde. Das die Eingangsparameter da ran schuld sind dachte ich mir auch, ich wusste nur nicht welcher.


----------



## TempeltonPeck (27 Februar 2017)

So. Habe es getestet und es funktioniert super! Sowohl bei verschiedenen Datentypen, Speicherbereichen und auch als komplett DB. Nochmals vielen Dank Harald!

Hier nochmal mein Quellcode mit Kommentaren. Vielleicht hilft es jemanden. Fragen nach SCL-Pointern tauchen hier ja oft auf. Es wäre bestimmt sinnvoll wenn ein Mod den Code in den FAQ Bereich packen könnte.


```
TYPE "Pointer"
VERSION : 0.1
   STRUCT
      SyntaxID : Byte;   // Für S7 immer HEX 10h
      DataTyp : Byte;   // Datentyp Bool,Byte usw.
      Laenge : Int;
      DB_Nr : Int;
      PTR : DWord;   // Speicherbereich DB, Merker usw.
   END_STRUCT;


END_TYPE




FUNCTION "FC138_Kopieren" : Void
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      DatenTyp : Byte;   // Datentyp (Bool,Byte usw.)
      Quell_Speicherbereich : DWord;   // Quell Speicherbereich (Merker, DB usw.)
      Quell_Bereich : UInt;   // Beginn Quell des Speicherbereichs
      Laenge : UInt;   // Speicherbereichsgroeße
      Ziel_Speicherbereich : DWord;   // Ziel Speicherbereich (Merker, DB usw.)
      Ziel_Bereich : UInt;   // Beginn des Ziel Speicherbereichs
      Quell_DB_Nr : UInt;   // Quell_DB_Nr. sonst 0
      Ziel_DB_Nr : UInt;   // Ziel_DB_Nr. sonst 0
      DB_Komplett : Bool;
   END_VAR


   VAR_TEMP 
      Adr_max : UInt;
      ATTR_DB : Byte;
      P_Quelle : "Pointer";
      Any_P_Quelle AT P_Quelle : Any;
      P_Ziel : "Pointer";
      Any_P_Ziel AT P_Ziel : Any;
      RetVal_BKLM : Int;
      RetVal_ATTR_DB : Int;
      RetVal_BLKMOV : Int;
   END_VAR




BEGIN
	
	// Aufbau Pointer
	// Bit    |15..         ..8 | 7..         ..0 |
	// Byte 0 |   10h für S7    |    Datentyp     | Byte 1
	// Byte 2 |             Laenge                | Byte 3
	// Byte 4 |         DB-Nummer (oder 0)        | Byte 5
	// Byte 6 | Speicherbereich | 0 0 0 0 0 B B B | Byte 7
	// Byte 8 | B B B B B B B B | B B B B B b b b | Byte 9
	
	// Syntax ID bei S7 immer h10
	#P_Quelle.SyntaxID := b#16#10;
	#P_Ziel.SyntaxID := b#16#10;
	
	// DatenTyp ID in HEX
	// 00 NIL     01 BOOL     02 BYTE
	// 03 Char    04 WORD     05 INT
	// 06 DWord   07 DINT     08 REAL
	// 09 Date    0A TOD      0B TIME
	// 0C S5Time  0E DT       13 STRING
	
	#P_Quelle.DataTyp := #DatenTyp;
	#P_Ziel.DataTyp := #DatenTyp;
	
	// Speicherbereich ID in HEX
	// 81 Eingänge        82 Ausgänge     83 Merker
	// 84 Datenbaustein   85 Instanz-DB   86 Lokal daten (L-Stack)
	// 87 Vorherige Lokal daten
	
	#P_Quelle."PTR" := #Quell_Speicherbereich + (#Quell_Bereich *8);
	#P_Ziel."PTR" := #Ziel_Speicherbereich + (#Ziel_Bereich * 8);
	
	#P_Quelle.Laenge := #Laenge;
	#P_Ziel.Laenge := #Laenge;
	
	#P_Quelle.DB_Nr := #Quell_DB_Nr;
	#P_Ziel.DB_Nr := #Ziel_DB_Nr;
	
	// Wenn DB-Bereich und Komplett kopieren gewählt
	IF #DB_Komplett = TRUE AND #Quell_DB_Nr >= 0 THEN
	    #RetVal_ATTR_DB := ATTR_DB(REQ := TRUE, DB_NUMBER := #Quell_DB_Nr, DB_LENGTH => #Adr_max, ATTRIB => #ATTR_DB); // Atribute des Quell DB lesen
	    #P_Quelle.Laenge := #Adr_max;
	    #P_Ziel.Laenge := #Adr_max;
	    #P_Quelle."PTR" := #Quell_Speicherbereich; // Quell- und Zielbereich = 0
	    #P_Ziel."PTR" := #Ziel_Speicherbereich;
	END_IF;
	
	// Kopieren
	#RetVal_BLKMOV := BLKMOV(SRCBLK := #Any_P_Quelle, DSTBLK => #Any_P_Ziel);
END_FUNCTION
```


----------

