# S7 REAL Datenformat



## cidex (8 August 2007)

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????


----------



## maxi (8 August 2007)

Vielleicht hilfreich


guckst du: http://www.geophysik.uni-koeln.de/s...rechner2/vorlesung/material/fortran_55_75.pdf


----------



## repök (8 August 2007)

*littel endian/ big endian*

soll heissen : du must byteweise tauschen

byte1 -> byte 4
byte2 -> byte 3
byte3 -> byte 2
byte4 -> byte 1


----------



## Steve81 (8 August 2007)

repök schrieb:


> soll heissen : du must byteweise tauschen
> 
> byte1 -> byte 4
> byte2 -> byte 3
> ...


 
Dazu passt auch dieses Thema:
http://www.sps-forum.de/showthread.php?t=14251

@cidex:
Schreib doch mal deine Ergebnisse in bin hier rein die du bekommst.


----------



## cidex (8 August 2007)

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;
}

*
*


----------



## cidex (8 August 2007)

Hab grad den Link zur powerpoint verfolgt. Da wäre es gestanden.:???:

Aber was solls. So hab ich eien Nerd ein Paar minuten beschäftigt.


----------



## Ralle (8 August 2007)

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:


```
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.


----------



## cidex (9 August 2007)

*Danke*

Danke für die rasche Hilfe. Hab ja jetzt ein bischen Auswahl.


----------



## baumtho (13 Januar 2021)

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;
}


----------

