Scl-any Pointer

Zuviel Werbung?
-> Hier kostenlos registrieren
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 ; //
....
 
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
 
Zuviel Werbung?
-> Hier kostenlos registrieren
... 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 ...
 
... 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 :ROFLMAO:
 
@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
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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 ;)
 
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.

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

Code:
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?
 
Zum testen wollte ich von ein Byte von MB5 nach MB7 kopieren.

Code:
DatenTyp : b#16#2
      [COLOR="#FF0000"]Quell_Speicherbereich : b#16#83
      Quell_Bereich : 5;[/COLOR]
      Laenge : 1 
      [COLOR="#FF0000"]Ziel_Speicherbereich : b#16#83
      Ziel_Bereich : 7[/COLOR]
      Quell_DB_Nr : 0
      Ziel_DB_Nr : 0 
      DB_Komplett : FALSE;

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


Code:
[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
 
Zuviel Werbung?
-> Hier kostenlos registrieren
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



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

Harald


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.
 
Zuletzt bearbeitet:
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.

Code:
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
 
Zurück
Oben