LREAL_OF_BYTES, bin ich so richtig unterwegs?

Jochen

Level-1
Beiträge
131
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hoi,

wie im Titel zu erahnen, möchte ich mir gerade eine Funktion LREAL_OF_BYTES basteln. Ich bin zwar eigentlich sicher, dass es so gehen müsste, aber vielleicht verifiziert das gerade noch kurz jemand, das wär lieb:

Code:
LREAL_OF_BYTES := DWORD_TO_LREAL(SHL(DWORD_OF_BYTE(BIN7,BIN6,BIN5,BIN4),32)) OR DWORD_TO_LREAL(DWORD_OF_BYTE(BIN3,BIN2,BIN1,BIN0));

Oder hab ich nen Denkfehler?

Danke im Voraus

Gruß
Jochen

P.S.: Die Endianess von 7-0 ist gerade nur Nomenklatur, wie sie auf meine Eingangsbytes passt, das kann natürlich auch anders aufgereiht werden, je nach Plattform und Anordnung der Bytes.
 
Aber bei DWORD_TO_LREAL wird die Kommastelle immer .0 sein. Hast du evtl. das DWORD im IEEE754-Format?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Genau, ich bekomme über eine TCP-Verbindung 8 Bytes rein, die rückwärts aneinandergereiht eine IEEE754-Gleitkommazahl ergeben. Weiß jetzt nicht genau, wie die DWORD_TO_LREAL Funktion arbeitet. Wenn die natürlich noch was an der Bytefolge bzw deren Werte ändert, ists doof. Muss ich die Tage mal vor Ort testen, ob das geht.

Gruß
 
Also bei mir in PC Worx arbeitet das nicht nach den IEEE754-Format. Deswegen musste ich mir selber eine Funktion schreiben.
 
Ok, ist bei mir auch PC-Worx. Kannst Du mir sagen, wie Du es gemacht hast? Bin mit PC Worx immer noch nicht so ganz warm. Bei Simatic hätte ich wohl einfach eine kleine Funktion mit nem Pointer gebaut, die mir die Bytes nacheinander an die Speicherstellen des LREAL schreibt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja Pointer gibt es in PC Worx ja nicht. Ich meine ich hab da mit den *_TO_BUF Bausteinen gerabeitet. Ich schau mal heute Nachmittag zu Hause.
 
Aaallllssoo:

REAL_TO_IEEE754
Code:
REAL_TO_BUF_1(REQ:=xReq,BUF_FORMAT:=FALSE,BUF_OFFS:=DINT#0,BUF_CNT:=DINT#4,SRC:=IN,BUFFER:=aTmp);
IN := REAL_TO_BUF_1.SRC;
aTmp := REAL_TO_BUF_1.BUFFER;
    
IF IN <> rINLast THEN
    xReq := TRUE;
END_IF;
    
IF REAL_TO_BUF_1.DONE THEN
    xReq := FALSE;
END_IF;
    
dwTmp.B0 := aTmp[0];
dwTmp.B1 := aTmp[1];
dwTmp.B2 := aTmp[2];
dwTmp.B3 := aTmp[3];
    
OUT := dwTmp;
    
rINLast := IN;


IEEE754_TO_REAL

Code:
BUF_TO_REAL_1(REQ:=xReq,BUF_FORMAT:=FALSE,BUF_OFFS:=DINT#0,BUF_CNT:=DINT#4,BUFFER:=aTmp,DST:=OUT);
aTmp := BUF_TO_REAL_1.BUFFER;
OUT:=BUF_TO_REAL_1.DST;
      
IF IN <> dwINLast THEN
      xReq := TRUE;
END_IF;
      
IF BUF_TO_REAL_1.DONE THEN
      xReq := FALSE;
END_IF;
      
aTmp[0] := IN.B0;
aTmp[1] := IN.B1;
aTmp[2] := IN.B2;
aTmp[3] := IN.B3;
      
dwINLast := IN;

Die Deklarationen der Variablen findest du im Anhang.

Als Datentyp musst du dannoch diesen hier anlegen:
Code:
TYPE
      ARRAY_OF_BYTE_0_3 : ARRAY [0..3] OF BYTE;
END_TYPE
 

Anhänge

  • IEEE754.jpg
    IEEE754.jpg
    60,4 KB · Aufrufe: 17
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke schonmal,

Das mit nem normalen REAL zu machen, geht so, wie du schreibst. Ich habe aber leider ein 64-bit Double. Und ein LREAL_TO_BUF gibt es ja nicht.

Ich denke ich werde es händisch machen müssen. Also Exponent, Vorzeichen und Mantisse trennen. Die Mantisse dann mit der vorkommastelle halt auf 22 bit beschneiden, um ein normales Real zu bekommen. Wüsste nicht, wie es sonst gehen sollte.

Gruß
 
Hatte mir schon gedacht, dass das nicht klappt. Aber evtl. als Hilfestellung. Ob das mit dem beschneiden dann geht, bezweifel ich. Der Exponent bei LREAL ist 11 Bit groß. Beim REAL ist er 8 Bit.
 
Klar, aber das ist ja kein Problem:

Ich nehme mir den Exponenten mit seinen 11Bit als Integer raus, ziehe den Bias von 1023 ab. Ich erhalte dann einen Exponenten, auf den ich wieder einen Integer von 127 (Bias einer 32-Bit-Realzahl) draufaddieren kann.

Den schreibe ich in erstmal in ein DWORD und shifte ihn um 23 nach links.

Dann nehme ich das letzte Byte aus dem Bytestrom raus, also Byte 7, verodere es mit 80h, das gibt mir das Vorzeichenbit. Wenn das ungleich 0 ist, kommt das Ergebnisbyte dann in ein DWORD und wird um 24 nach links geshiftet und mit dem Exponenten-DWORD verodert.

Nun zur Mantisse: Meine Bytes kommen rückwärts im TCP Buffer an. Daher nehme ich dann Byte sechs, fünf, vier und drei in ein DWORD. Darin stehen dann ja quasi die letzten 4 Exponentenbits, die letzten 23 Mantissenbits und noch 5 Bits von der großen Mantisse. Das DWORD also 4 mal Links und dann 9 mal rechts shiften. Dann das ganze mit dem obigen DWORD verodert und ein DWORD_TO_REAL drauf angewendet, sollte mir meine 32 Bit Fließkommazahl liefern.

Jetzt muss ich das nur noch in Code packen ;-)
 
Zuletzt bearbeitet:
Das berichte ich nächste Woche,

ich bin jetzt erstmal eine Woche im Klausurstress und habe daher Urlaub.
Nächsten Donnerstag wieder im Büro, dann teste ich das.

Gruß

JOchen
 
So es hat nun etwas länger gedauert, aber ich habe es jetzt fertig und es funktioniert auch:

Code:
TYPE

(* Result structure *)


TCP_RESULT_STRUCT :
	STRUCT
	ERCL : BYTE;
	ERCD0 : BYTE;
	ERCD1 : BYTE;
	RSLT0 : BYTE;
	RSLT1 : BYTE;
	RSLT2 : BYTE;
	RSLT3 : BYTE;
	RSLT4 : BYTE;
	RSLT5 : BYTE;
	RSLT6 : BYTE;
	RSLT7 : BYTE;
	END_STRUCT;




(* Result Array *)
TCP_RESULT_ARRAY : ARRAY[0..13] OF TCP_RESULT_STRUCT;


TCP_RECEIVE_RESULTS :
	STRUCT
	PHOENIX_DLEN : WORD;
	REST : BYTE;
	MSID0 : BYTE; 
	MSID1 : BYTE; 
	SICM0 : BYTE;
	SICM1 : BYTE;
	OFST0 : BYTE;
	OFST1 : BYTE;
	CCNT0 : BYTE;
	CCNT1 : BYTE;
	RESD : TCP_RESULT_ARRAY;
	END_STRUCT;


END_TYPE


VAR_OUTPUT
realOut	: REAL;
END_VAR


VAR_INPUT
lrealStructIn :	TCP_RESULT_STRUCT;
END_VAR


VAR
exponent11 : INT;	
workingDword : DWORD;	
mantissa23 : DWORD;	
exponent8 : INT;	
workingDword1 : DWORD;	
realOutDword : DWORD;	
DW_TO_REAL_1 : DW_TO_REAL;	
END_VAR


(* 11 Bit exponent to 8 bit Exponent *)
exponent11:=WORD_TO_INT(SHR(SHL(WORD_OF_BYTE(lrealStructIn.RSLT7,lrealStructIn.RSLT6),1),5))-1023;
exponent8:=exponent11+127;


(* Shift exponentent to second front bit *)
workingDword1:=SHL(INT_TO_DWORD(exponent8),23);


(* Sign Bit *)
workingDword:=(workingDword1 OR SHL(BYTE_TO_DWORD(lrealStructIn.RSLT7),30));


(* Cut Mantissa *)
mantissa23:=SHR(SHL(DWORD_OF_BYTE(lrealStructIn.RSLT6,lrealStructIn.RSLT5,lrealStructIn.RSLT4,lrealStructIn.RSLT3),4),9);


realOutDword:=workingDword or mantissa23;
DW_TO_REAL_1(X:=realOutDword);
realOut:=DW_TO_REAL_1.DW_TO_REAL;
 
Danke, kenne das Codebeispiel.
Baue das natürlich entsprechend noch aus.
Aber das eigentliche Problem ist halt behoben.
Wobei ich nicht immer noch nicht verstehe, wieso das doofe PC-Worx es nicht checkt, einen TCP-Buffer byteweise in eine passende UDT-Struktur mit LREALS einzulesen. Die CPU kann ja LREAL.

Gruß
 
Schön, dass es jetzt endlich funktioniert und Hauptsache es funktioniert. Ich denke mal der Grund warum das einlesen nicht klappt, ist einfach nur der, das wohl LREAL nicht ganz implementiert wurde sowie die anderen Typen. Wenn es mehr Kunden wünschen würden, würde es wahrscheinlich auch dann mal ganz einsatzfähig sein, ohne irgendwelche Workarounds. Genau wie bei mir mit dem DWORD_TO_IEEE754 und umgekehrt.
 
Zurück
Oben