# 4 Byte in ein REAL zusammenführen



## JandeFun (4 Dezember 2011)

Hallo

ich habe das folgende Problem. Ich möchte über eine Profibus Verbindung Daten aus einem Gerät auslesen. Die Verbindung steht und die Daten werden auch übermittelt.
Leider liegt auf der ersten Adresse ein Wert im Byte und folgend, dazu mehrere Werte im Float Format.
Byte Byte Adresse: 0
Float Byte Adresse: 1-4
Float Byte Adresse: 5-6
etc. 

Über den System Manager kann ich leider nur 8 / 16 / 32 Word Blöcke zum auslesen des Gerätes konfigurieren, wodurch meine komplette Adressierung um genau ein Byte verrutscht. Damit werden die Float Werte nicht richtig angezeigt.

Ich übernehme die Werte in ein Array in der Größe 0..123 Byte, da ich nun 62 Word konsistent vom Gerät einlese.
Im PLC wollte ich nun aus den einzelnen Bytes die jeweiligen REAL Werte wieder mittels eines Pointers zusammensetzen, was mir allerdings nicht so ganz gelingt.
Scheinbar lässt sich der Pointer nicht um eine Byte Breite erhöhen.

ptOINTER TO WORD;
testarray: ARRAY [0..3] OF BYTE := 10,20,30,40;
testREAL: REAL;

pt := ADR(testREAL);
pt^ := testarray [0];
pt := (pt + 1);
pt^ := testarray [1];
pt := (pt + 1);
pt^ := testarray [2];
pt := (pt + 1);
pt^ := testarray [3];
pt := (pt + 1);
testREAL;

Was ist das dem Code Schnipsel falsch? Gibt es eine andere Möglichkeit die Werte ins richtige Format zu bekommen?

Vielen Dank für eure Antworten.

Sytem: Twin Cat 32 / Build: 2014


----------



## Nitrozin (4 Dezember 2011)

Hi,

schau die mal die OSCAT.LIB an, ich meine da sind solche Funktionen drin.
http://www.oscat.de/

Gruß Nitro


----------



## StructuredTrash (4 Dezember 2011)

Warum übernimmst Du die Daten nicht in eine STRUCT-Variable, die den Aufbau Deiner Daten exakt abbildet?

```
TYPE stProfiBusData
STRUCT
   Var1:BYTE;
   Var2:REAL;
   Var3:REAL;
(* usw. *)
END_STRUCT
END_TYPE
```


----------



## JandeFun (4 Dezember 2011)

Vielen Dank

Das funktioniert schon mal offline ohne Fehler.

Trotzdem würde ich gerne verstehen, warum der erste Code nicht funktioniert.

Ist vielleicht die erhöhung um 1 nicht mit einem *Byte *gleichzusetzen?


----------



## Neals (4 Dezember 2011)

Ein REAL besteht aus Mantisse und Exponent:
http://de.wikipedia.org/wiki/Fließkommazahl#Mantisse

Mit deinem Code könntest du ggf. die 4 Byte in ein DWORD kopieren und dieses dann in REAL wandeln...


----------



## StructuredTrash (5 Dezember 2011)

JandeFun schrieb:


> Trotzdem würde ich gerne verstehen, warum der erste Code nicht funktioniert.


Sieht so aus, als ob der Code TestArray[1] bis [3] mit 0 füllt. Das sollte er sicher nicht tun, aber was dann?


----------



## JandeFun (5 Dezember 2011)

Neals schrieb:


> Ein REAL besteht aus Mantisse und Exponent:
> http://de.wikipedia.org/wiki/Fließkommazahl#Mantisse
> 
> Mit deinem Code könntest du ggf. die 4 Byte in ein DWORD kopieren und dieses dann in REAL wandeln...



Grundsätzlich sollte es doch total egal sein, um welches Zahlenformat es sich handelt. Alle Zahlenwerte werden letztendlich im 2er Komplement in einem Bitmuster dargestellt. Die Anzeige des Zahlenwertes, ob REAL oder INT ist nur eine Interpretation des Bit Musters.
Wenn ich eine Real Zahl in 4 Byte zerlege, das Bitmuster nicht verändere und sie dann in der gleichen Reihenfolge wieder zusammensetze muss auch die gleiche Zahl wieder herauskommen, wenn die Interpretation des Bitmusters wieder REAL ist. Richtig?


----------



## JandeFun (5 Dezember 2011)

pt := Pointer TO Word => muss natürlich Pointer TO REAL heißen.

Das komische ist, wenn ich den Pointer das erste mal um eine Byte Adresse erhöhe, kommt eine Zahl heraus, die überhaupt nicht dem Pointer Format ähnlich ist, wie nach dem Befehl

pr := ADR(TestREAL);

Muss ich die 1 zur Erhöhung vielleicht anders deklarieren?


----------



## StructuredTrash (5 Dezember 2011)

JandeFun schrieb:


> Das komische ist, wenn ich den Pointer das erste mal um eine Byte Adresse erhöhe, kommt eine Zahl heraus, die überhaupt nicht dem Pointer Format ähnlich ist, wie nach dem Befehl
> 
> pr := ADR(TestREAL);


Das ist schon seltsam, bei mir funktioniert das wie erwartet. Was kommt denn für eine Adresse heraus, wenn Du
pt:=ADR(testarray[1]); schreibst?


----------



## JandeFun (13 Dezember 2011)

Hallo 

nun funktioniert es auch bei mir. Ich hatten den "Pointer To REAL" deklariert. Durch die erhöhung des Pointers um 1 hat das System scheinbar um 4 Byte erhöht ( REAL Breite).

Richtig muß es heißen:

VAR
TestCounter: REAL;
pt0: *POINTER TO BYTE*;(*Hier lag der Fehler*)
pt: *POINTER TO BYTE*;(*Hier lag der Fehler*)
BereichLeistungsmessungRohwerte: ARRAY [0..3] OF BYTE;
LEISTUNGSMESSUNG_DATEN_TEST: REAL;
END_VAR

TestCounter := TestCounter + 1.111564;

(* Werte in 4 Byte teilen*)
pt0 := ADR (TestCounter);
BereichLeistungsmessungRohwerte [0] := pt0^;
pt0 := (pt0 + 1);
BereichLeistungsmessungRohwerte [1] := pt0^;
pt0 := (pt0 + 1);
BereichLeistungsmessungRohwerte [2] := pt0^;
pt0 := (pt0 + 1);
BereichLeistungsmessungRohwerte [3] := pt0^;

(*Wert aus 4 Byte zusammensetzen*)
pt := ADR (LEISTUNGSMESSUNG_DATEN_TEST);
pt^ := BereichLeistungsmessungRohwerte [0];
pt := (pt + 1);
pt^ := BereichLeistungsmessungRohwerte [1];
pt := (pt +1);
pt^ := BereichLeistungsmessungRohwerte [2];
pt := (pt +1);
pt^ := BereichLeistungsmessungRohwerte [3];

LEISTUNGSMESSUNG_DATEN_TEST;


----------

