Step 7 SCL: 4 Byte TO Real - Pointer in Funktion

artofautomation

Level-1
Beiträge
39
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

von einem Profibusgerät bekomme ich eine Real Variable. Leider sind die 4 Bytes aus denen das Real besteht vertauscht. Also hab ich mir versucht (auch mit der hilfe hier eine Funktion zu schreiben, die die vier Bytes in einen Real wandelt. Da ich aus der Backhoff Welt komme, verstehe ich gar nicht warum ich keinen pointer deklarieren kann. Wie soll ich das denn sonst lösen?


Code:
FUNCTION FC_4BYTE_TO_REAL : REAL
VAR_INPUT
    b1  : BYTE;
    b2  : BYTE;
    b3  : BYTE;
    b4  : BYTE;
END_VAR

VAR_TEMP
    // temporäre Variablen
    pt          : POINTER TO BYTE;
    temp_real   : REAL;
END_VAR

    // Anweisungsteil
    (*Wert aus 4 Byte zusammensetzen*)
    pt := ADR(temp_real);
    pt^ := b2;
    pt := (pt+1);
    pt^ := b1;
    pt := (pt+1);
    pt^ := b4;
    pt := (pt+1);
    pt^ := b3;

    FC_4BYTE_TO_REAL := temp_real;
END_FUNCTION

Fehler: Deklaration einer Aufrufinstanz oder verwendeter Parameterdatentyp in diesem Vereinbarungsblock nicht zulässig.

WTF?

Auch das hier https://support.industry.siemens.co...ointer-zusammengestellt-werden?dti=0&lc=de-WW beschriebene Any Pointer Construct aus dem Bild 01 lässt sich nicht übersetzen? Ich habe Simatic Manager V5.3 SP6 Upd2. Wurde da was geändert am Compiler? Pointer nur noch im TIA oder so?

Kann mich bitte jemand erleuchten?
AWL ist leider nicht so meins. Wenn es nicht anders geht, nehm ich auch das, dann aber bitte nachsichtig sein.

Vielen Dank
 
SCL und Pointer ist bei Step 7 Classic nicht gerade der Brüller.

Mit AWL lässt sich dein Vorhaben eigentlich recht einfach bewerkstelligen.

Deinen obigen SCL-Code mit "Pointer To Byte" und "^" versteht der Step 7 Compiler vermutlich auch nicht - das geht so nur mit Codesys, Beckhoff, etc.

Pointer mit SCL geht nur mit AT-Sicht, und die geht wiederum nur im VAR_INPUT Bereich.

Schau dir mal folgenden Thread an, da hatte jemand ein ähnliches Problem - vielleicht hilft dir das weiter: http://www.sps-forum.de/simatic/24511-pointer-scl-kein-any-2.html


 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier noch ein AWL-FC, der die Bytes in einem DWord tauscht:

Code:
FUNCTION "SwapBytesDWord" : VOID
TITLE =
//Change Byteorder in DWord
AUTHOR : xy
VERSION : 1.0


VAR_INPUT
  InDataDWord : DWORD ;    //Indata DWord
END_VAR
VAR_OUTPUT
  OutDataDWord : DWORD ;    //Outdata DWord
END_VAR
VAR_TEMP
  SaveAR1 : DWORD ;    
  TempInDWord : ARRAY  [0 .. 3 ] OF BYTE ;    
  TempOutDWord : DWORD ;    
END_VAR
BEGIN
NETWORK
TITLE =

      TAR1  #SaveAR1; //Adressregister sichern

      L     P##TempInDWord; //Zeiger auf lokales Datenarray
      LAR1  ; 

      L     #InDataDWord; //Eingangs DWord auf Array umkopieren
      T     LD [AR1,P#0.0]; 

      L     P##TempOutDWord; 
      LAR1  ; 

      L     #TempInDWord[0]; 
      T     LB [AR1,P#3.0]; 

      L     #TempInDWord[1]; 
      T     LB [AR1,P#2.0]; 

      L     #TempInDWord[2]; 
      T     LB [AR1,P#1.0]; 

      L     #TempInDWord[3]; 
      T     LB [AR1,P#0.0]; 

      L     #TempOutDWord; 
      T     #OutDataDWord; 

      LAR1  #SaveAR1; //Adressregister wiederherstellen


END_FUNCTION


Da kannst du dir bestimmt auch ein bisschen was abschauen, und auf deine Bedürfnisse anpassen.
 
Step7-Classic SCL ist für einen Beckhoff-Umsteiger sicher ungewöhnlich...
Wie uncle_tom schon schrieb gibt's "^" in der SCL-Syntax nicht, mit Pointern auf Adressen an sich arbeitet man eigentlich in der Praxis kaum.
Hier 3 Varianten...

Variante 1: Am häufigsten genutzt und wohl am elegantesten: AT-Sicht
Code:
FUNCTION FC60 : REAL
VAR_INPUT
    BY1 : BYTE;
    BY2 : BYTE;
    BY3 : BYTE;
    BY4 : BYTE;
END_VAR
VAR_TEMP
    BYStruct : STRUCT
    BY1 : BYTE;
    BY2 : BYTE;
    BY3 : BYTE;
    BY4 : BYTE;
    END_STRUCT;
    REAL_AT AT BYStruct : REAL;   
END_VAR


BYStruct.BY1 := BY1;
BYStruct.BY2 := BY2;
BYStruct.BY3 := BY3;
BYStruct.BY4 := BY4;


FC60 := REAL_AT;


END_FUNCTION

Variante 2: Auch ganz nett und gar und "neumodische" indirekte Adressierung und Pointer-Zeugs...
Code:
FUNCTION FC61 : REAL
VAR_INPUT
    BY1 : BYTE;
    BY2 : BYTE;
    BY3 : BYTE;
    BY4 : BYTE;
END_VAR
VAR_TEMP
   OutVAR : DWORD; 


END_VAR


OutVar := BY1;
OutVar := SHL(IN:=OutVar, N:=8) OR BY2;
OutVar := SHL(IN:=OutVar, N:=8) OR BY3;
OutVar := SHL(IN:=OutVar, N:=8) OR BY4;


FC61:= DWORD_TO_REAL(OutVar);


END_FUNCTION

Variante 3: Diesmal mit ANY-Pointer auf Struct und BLKMOV (schlechter Ersatz für AT)
Code:
FUNCTION FC62 : REAL
VAR_INPUT
    BY1 : BYTE;
    BY2 : BYTE;
    BY3 : BYTE;
    BY4 : BYTE;
END_VAR
VAR_TEMP
    BYStruct : STRUCT
    BY1 : BYTE;
    BY2 : BYTE;
    BY3 : BYTE;
    BY4 : BYTE;
    END_STRUCT;  
    ANY_Ptr : ANY;
    SFC20_RetVal : INT;
    rTMp : REAL;
END_VAR


BYStruct.BY1 := BY1;
BYStruct.BY2 := BY2;
BYStruct.BY3 := BY3;
BYStruct.BY4 := BY4;


ANY_Ptr := BYStruct;
SFC20_RetVal := BLKMOV(SRCBLK := ANY_PTr, DSTBLK := rTmp); 


FC62 := rTmp;


END_FUNCTION

... viele Wege führen nach Rom...
 
Hier noch ein AWL-FC, der die Bytes in einem DWord tauscht:

Code:
[...]
      TAR1  #SaveAR1; //Adressregister sichern

      L     P##TempInDWord; //Zeiger auf lokales Datenarray
      LAR1  ; 

      L     #InDataDWord; //Eingangs DWord auf Array umkopieren
      T     LD [AR1,P#0.0]; 

      L     P##TempOutDWord; 
      LAR1  ; 

      L     #TempInDWord[0]; 
      T     LB [AR1,P#3.0]; 

      L     #TempInDWord[1]; 
      T     LB [AR1,P#2.0]; 

      L     #TempInDWord[2]; 
      T     LB [AR1,P#1.0]; 

      L     #TempInDWord[3]; 
      T     LB [AR1,P#0.0]; 

      L     #TempOutDWord; 
      T     #OutDataDWord; 

      LAR1  #SaveAR1; //Adressregister wiederherstellen
OK, ein Beispiel, wie man indirekte Adressierung mit AR-Register machen kann...
Um die Byte-Reihenfolge in einem DWord umzukehren tät dasselbe auch dieser 3-Zeiler:
Code:
      L     #InDataDWord;
      TAD;
      T     #OutDataDWord;


Beim TE soll aber nicht die Byte-Reihenfolge im DWord umgekehrt werden, sondern die Byte-Reihenfolge in Words. Aus der Byte-Reihenfolge 1234 soll 2143 werden.

Wenn der Swap-FC 4 einzelne Eingangsbytes verarbeiten soll, dann kann man das durchaus in SCL machen, z.B. wie in RONINs Variante 1 mit der AT-Sicht (noch anpassen zur richtigen Bytefolge).

Wenn ich unterstelle, daß die 4 Bytes direkt aufeinanderfolgen, dann würde ich das wohl so machen:
Code:
FUNCTION "FC_4BYTE_TO_REAL" : REAL
TITLE =
VERSION : 0.1

VAR_INPUT
  pt4Bytes : POINTER ; //Pointer auf 4 aufeinanderfolgende Bytes
END_VAR
VAR_TEMP
  DBnr : WORD ;
END_VAR
BEGIN
NETWORK
TITLE =

      L     P##pt4Bytes;     //Adresse des Pointers auf 4 aufeinanderfolgende Bytes
      LAR1  ; 
      L     W [AR1,P#0.0]; 
      T     #DBnr; 
      L     D [AR1,P#2.0]; 
      UD    DW#16#FFFFFFF8;  //vorsichtshalber P#x.y --> P#x.0
      LAR1  ; 
      AUF   DB [#DBnr];      //DBNO+AR1 zeigt nun auf die 4 Bytes

      L     D [AR1,P#0.0];   //die 4 aufeinanderfolgenden Bytes
      TAD   ;                //1234 --> 4321
      RLD   16;              //              --> 2143
      T     #RET_VAL; 

END_FUNCTION

Harald
 
OK, ein Beispiel, wie man indirekte Adressierung mit AR-Register machen kann...
Um die Byte-Reihenfolge in einem DWord umzukehren tät dasselbe auch dieser 3-Zeiler:
Code:
      L     #InDataDWord;
      TAD;
      T     #OutDataDWord;


Beim TE soll aber nicht die Byte-Reihenfolge im DWord umgekehrt werden, sondern die Byte-Reihenfolge in Words. Aus der Byte-Reihenfolge 1234 soll 2143 werden.

Wenn der Swap-FC 4 einzelne Eingangsbytes verarbeiten soll, dann kann man das durchaus in SCL machen, z.B. wie in RONINs Variante 1 mit der AT-Sicht (noch anpassen zur richtigen Bytefolge).
[...]

Dann nimm dich statt TAD TAW, das ist beträchtlich kürzer ;-)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Ronin,

bin jetzt erst wieder von der Baustelle zurück :D.

Für die Variante 1 habe ich mich entschieden. Funktioniert wunderbar, auch rückwärts nach dem selben Prinzip. Danke.

Auf Variante 2 hätte ich auch kommen können. In der richtigen Reihenfolge nach links schieben und verodern. Eigentlich ganz einfach. War bloß zu verbort was meine Pointer angeht. Danke.

Variante 3: hab ich auch ausprobiert, funktioniert. Anypointer auf Struktur und BLKMOVE. Danke.

Großer Daumen nach oben.

An alle anderen: Danke für die AWL Vorschläge. Um AWL mache ich aber nach Möglichkeit einen Bogen.
 
Zurück
Oben