S7 REAL Datenformat

cidex

Level-1
Beiträge
15
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich schreibe gerade ein Programm das Daten von einer beliebigen S7 300/400 per TCP/IP
auslesen kann. Das ganze funktioniert auch ganz gut, inclusive Motorola auf Intel usw.

Ich kann auch REAL (32bit, fließkommazahlen) von der SPS lesen, jedoch kann ich sie nicht darstellen. Die Daten sind in ordnung wenn ich sie in Hex oder Bin
anzeige sind die Werte die ich mit dem SimaticManager lese und die die mein Programm ließt gleich.
Allerdings weiß ich nicht wie ich die Bits darstellen muss.

Auch die Norm nach der Siemens angeblich arbeitet hilft mir nicht weiter
(IEEE 754). diese definiert nur wo Vorzeichen(1bit), Exponent(8) und Mantise(23) stehen aber nicht wie diese codiert sind.
Die Unterschiede zwischen zwei Zahlen bei denen sich nur der Exponent
ändern sollte sind Wahnsinn!

Bsp.:
5.0 entspricht Hex 42480000(bei Simens)
50.0 entspricht Hex 40A00000(bei Simens)

5 entspricht normalerweise 0101 in Bin, aber das kommt im bitmuster gar nie vor! :twisted:

An alle ehemaligen oder aktuellen Mittarbeiter von Siemens.
Wie codiert Siemens die REALs????:confused:
 
Zuletzt bearbeitet:
Danke ein Freund von mir hats in 20 min geknackt.
das mit den Bytes tauschen ist convertierung von Motorola in Intel

Bsp:

zahl 5.0 in Siemens REAL als bin:
0100 0000 1010 0000 0000 0000 0000 0000

*1. bit vorzeichen 0 -> +, 1->-
*nächste 8 bit exponent -> 100 0000 1bin -> 129dec
127dec ist max darstellbar
129-127 = 2 dec
2^2 ist exponene 4 dec

*
restliche 23 bits ergeben 2097152 dec
div durch 2^23
ist 0,25 +1 = 1,25

+(1,25 * 4) = 5.0


hier als C++ funktion falls es jem. braucht:

float decryptReal(long s7REAL)
{
//algorithm by Georg alias "the brain" and "Rossi" coded by "criss"

bool sign = ((s7REAL & 0x80000000) >> 31);
float fsign = 1;

if(sign)
fsign = -1;
else
fsign = 1;

short exp = ((s7REAL & 0x7F800000) >> 23);
exp = (exp - 127);
exp = pow(2,exp);

long mant = ((s7REAL & 0x007FFFFF));
float mantf = (mant / pow(2,23));
mantf += 1;

float fresult = fsign * mantf * exp;

return fresult;
}


 
Irgendwie eigenartig, ich hatte das auch mal so kompliziert gelöst, von Zottel bekam ich dann folgenden Code gepostet, allerdings hab ich ihn nur für Delphi, da nutze ich ihn genau so und das funktioniert prima:

Code:
function S7_Float(Daten: Integer): Real;
var
  fiu: single;
begin
  move(Daten,fiu,4); { bloß keine impliziten Rechenoperationen durch casts! }
  S7_Float := fiu;
end;
Das ist nichts weiter als ein "Typecast", da man die Daten sonst immer als Integer serviert bekommt und diese in eine Real kopiert, bringt tatsächlich nur Schrott raus. Sollte genauso auch in C gehen, hab leider den Ursprungscode von Zottel nicht gefunden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier ist ein Fehler drin, der sich schwer finden lässt. Der Faktor, der den Exponenten repräsentiert, ist float! Dies macht sich erst bei kleinen Zahlen (z.B. -0,018) bemerkbar.
korrigiert:
double DecryptReal(uint8_t* pS7Real)
{
//algorithm by Georg alias "the brain" and "Rossi" coded by "criss",
// fixes 2021-01-13 by baumtho
const uint32_t s7Real = ((uint32_t)pS7Real[0] << 24) | ((uint32_t)pS7Real[1] << 16) | ((uint32_t)pS7Real[2] << 8) | ((uint32_t)pS7Real[3] << 0);
const bool isSign = 0 != (0x80000000 & s7Real);
const double fsign = isSign ? -1.0 : 1.0;


short exp1 = (short)((s7Real & 0x7F800000) >> 23);
exp1 -= 127;
// fix 2021-01-13 by baumtho: This must be float (was short)!
double expFact = pow(2, exp1);


const long mant = ((s7Real & 0x007FFFFF));
double mantf = (mant / pow(2, 23));
mantf += 1.0;


return fsign * mantf * expFact;
}
:p
 
Zurück
Oben