Wie aus Byte-Array in ein Float-Array?



  • Kommt drauf an:
    War sizeof(float)==4 auf dem System, auf welchem das Bytearray erzeugt wurde und ist die Float-Bytefolge/Endian auf Quell- und Zielsystem gleich, dann geht:

    unsigned char bp[16]= ... ;
    float *fp = (float*)bp;
    printf("%f %f %f %f",fp[0],fp[1],fp[2],fp[3]);
    

    Falls nicht, besorge dir eine für dein Quell- und Zielsystem passende Funktion ntof (nicht ANSI C), dann etwas komplizierter:

    unsigned char bp[16]= ... ;
    printf("%f %f %f %f",ntof(bp+0),ntof(bp+4),ntof(bp+8),ntof(bp+12));
    

    Evtl. geht statt ntof auch ntol, welche öfter zu finden sein könnte.



  • Hallo, also ich versuche mein Problem nochmal etwas besser zu beschreiben. Es ist so, dass ich die Software WINCC benutze und auf eine SPS S7 zugreife. Drücke ich einen Button bei WINCC sollen Werte aus einem Datenbaustein der S7 eingelesen werden. Dies kann man in WINCC durch eine C-Aktion machen mit einer zusätzlichen Funktion GetTagRaw. Wichtig bei meinem Problem ist das ich diese Funktion benutzen muß. Diese Funktion GetTagRaw liefert ein Bytearray zurück. Die Werte in meinem Datenbaustein sind allerdings von Typ REAl also 4 Byte. Am Beispiel von 4 Werten erhalte ich also ein Bytearray mit 16 Werten. Ich möchte allerdings die ursprünglichen 4 Werte zurückerhalten, muß also die ersten 4 Byte des Arrays nehmen und 5-8,9-12 etc. Ich bin persönlich leider nicht besonders bewandert in C-Programmierung.



  • Hallo, also ich versuche mein Problem nochmal etwas besser zu beschreiben.
    ...

    Sollen wir daraus schliessen, dass der Cast nach float (Wutzzeile 2) nichts gebracht hat?
    🙂



  • Ja der cast hat leider nichts gebracht. Kann ich die einzelnen Bytes nicht einfach irgendwie aneinanderfügen? Also eine Funktion schreiben die das macht? Gibt es sonst vielleicht auch die Möglichkeit zu sagen die floatvariable sei der Adressbereich von array[0] bis array[3] irgendwie über pointer oder so? Hab da leider persönlich echt wenig Ahnung wie ich das genau programmieren müsste.



  • LordNikon schrieb:

    Gibt es sonst vielleicht auch die Möglichkeit zu sagen die floatvariable sei der Adressbereich von array[0] bis array[3] irgendwie über pointer oder so?

    Das ist eigentlich das, was Wutz dir gezeigt hat (er hat aus einem unsigned char Zeiger einen float-Zeiger gemacht)...

    Mach uns doch mal bitte ein kleines Beispiel fertig mit 4 Byte-Werten in einem Array, die eigentlich einen float-Wert darstellen (am besten mit echten Werten).



  • Da scheinen mir aber größere Probleme vorzuliegen, als fehlende Programmiererfahrungen, z.B. Unkenntnis der Schnittstelle.

    Lasse dir mal die ersten 4 Bytes ausgeben (unter der Voraussetzung, dass deine SPS wirklich einen <float> in 4 Bytes packt), z.B.

    printf("%02x %02x %02x %02x", (int)bp[0],(int)bp[1],(int)bp[2],(int)bp[3] );
    

    Dann ermittle mal irgendwie, welchen Floatwert deine SPS gesendet hatte.
    Daraus kannst du die Bytefolge ermitteln, und unter der Voraussetzung, dass deine SPS immer dasgleiche Format benutzt, kannst du dir dann deine Konvertierungsfunktion schreiben (wir können dir dann dabei auch helfen).



  • Also wenn ich folgenden Wert:200000 in den Datenbaustein schreibe wird dort 30d40 angezeigt, also Hexadezimal. Gebe ich die ersten 4 Elemente des Arrays mit deiner printf Anweisung aus erhalte ich eben diese 0,3,0d,40. gebe ich sie mit Variablen vom Typ Float aus erhalte ich 0,3,13,64. also im Prinzip das gleiche. Nun frage ich mich wie ich den Wert z.B berechnen könnte, da ich ja eigentlich 0*16^0 + 4*16^1 + 13*16^2 etc rechnen müsste. Gruß



  • Nach Deinen Angaben ist das dann aber kein float-Wert, sondern ein einfacher int-Wert, byteweise übertragen.

    0x30d40 -> 200000 (dezimal)

    Ein einfacher Cast nutzt auch nichts, weil die Daten Big-Endian sind. Außer Dein Host arbeitet auch so.

    Die einfachste und sicherste Lösung hast Du Dir ja schon selbst gegeben:

    LordNikon schrieb:

    ...da ich ja eigentlich 0*16^0 + 4*16^1 + 13*16^2 etc rechnen müsste. Gruß

    Also, so etwas in der Art:

    int result = ( bp[0] << 24 ) | ( bp[1] << 16 ) | ( bp[2] << 8 ) | bp[3];
    

    Grüße



  • cmdev schrieb:

    int result = ( bp[0] << 24 ) | ( bp[1] << 16 ) | ( bp[2] << 8 ) | bp[3];
    

    Besser

    unsigned result = ( bp[0] << 24 ) | ( bp[1] << 16 ) | ( bp[2] << 8 ) | bp[3];
    

    bzw. sogar

    unsigned long result = ( bp[0] << 24 ) | ( bp[1] << 16 ) | ( bp[2] << 8 ) | bp[3];
    

    je nach Compiler.



  • Kommt natülich auf den

    LordNikon schrieb:

    ... Datenbaustein ...

    an. LordNikon muß wissen, ob man da auch negative Werte eingeben kann.



  • Vielen Dank Männer es klappt.


Anmelden zum Antworten