Forum: Mikrocontroller und Digitale Elektronik 2 x uint16 in 1x uint32 und als float in einen String schreiben??


von Tuxi (Gast)


Lesenswert?

Huhu Forum,
ich habe hier wohl gerade einen Denkfehler:
Ich bekomme über SPI 2 x uint16 Werte geliefert. Diese möchte ich nun 
lesbar in ASCII Format in eine Textdatei schreiben. Dazu baue ich zuerst 
einmal die beiden uint16 in eine uint32 Variable um und habe dann 
versucht diese mit snprintf in einen String als Float zu schreiben. Aber 
irgendwie stimmt da was nicht.
Wenn ich z.B. 0xFAFA, 0xAFAF gesendet bekomme und das dann zu uint32 
mache habe ich 0xFAFAAFAF das sagt mir auch der Debugger. Aber in meinem 
Sring_Mess_Data_Convert habe ich nicht den richtigen Float Wert stehen. 
Nach : 
http://www.binaryconvert.com/result_float.html?hexadecimal=FAFAAFAF
müssten es -6.50818750621392972857946860736E35 bzw. nur 6 Stellen nach 
dem Komma. Aber ich bekomme : -1.76264e-05.

Wo liegt mein Denkfehler?
1
k = snprintf (String_Mess_Data_Convert, MAX, "%g",(rx_buffer[j + 1] +((uint32_t) rx_buffer[j] << 16)));
Habe es auch schonmal so probiert, war aber auch quatsch:
k = snprintf (String_Mess_Data_Convert, MAX, "%g",(float)(rx_buffer[j + 
1] +((uint32_t) rx_buffer[j] << 16)));
[/c]

von Tuxi (Gast)


Lesenswert?

Achja mit (float) kommt : 4.21073e+09

von Jim M. (turboj)


Lesenswert?

Welcher Mikrocontroller ist das?

von Karl H. (kbuchegg)


Lesenswert?

Tuxi schrieb:
> Achja mit (float) kommt : 4.21073e+09

Drehs mal um.
Du kennst den Zahlenwert, der rauskommen müsste?

Wenn ja, dann lass dir den mal in seine Bytes zerlegt ausgeben und 
vergleich mit deinen Bytes, die du per SPI bekommst. Wahrscheinlich hast 
du einfach nur die falsche Bytereihenfolge beim Zusammensetzen.

von Tuxi (Gast)


Lesenswert?

Ist ein Embedded Linux auf einem AM3352.

von H.Joachim S. (crazyhorse)


Lesenswert?

Ich weiss es nicht genau, aber ich glaube %g macht keine Wandlung in 
float, sondern interpretiert die 32bit-Zahl nur als solche, und das ist 
dann falsch.
mit nem cast sollte das passen:
k = snprintf (String_Mess_Data_Convert, MAX, "%g",(float)(rx_buffer[j + 
1] +((uint32_t) rx_buffer[j] << 16)));

von Karl H. (kbuchegg)


Lesenswert?

H.Joachim Seifert schrieb:
> Ich weiss es nicht genau, aber ich glaube %g macht keine Wandlung in
> float, sondern interpretiert die 32bit-Zahl nur als solche, und das ist
> dann falsch.

Dann wäre aber etwas grausllich falsch.
%g ist die Version von %f, die wissenschfatliche Notation in der Ausgabe 
bevorzugt. Beide Formatangaben sind ok für double/float.

von oggy (Gast)


Lesenswert?

H.Joachim Seifert schrieb:
> mit nem cast sollte das passen:
> k = snprintf (String_Mess_Data_Convert, MAX, "%g",(float)(rx_buffer[j +
> 1] +((uint32_t) rx_buffer[j] << 16)));

der übergebene typ spielt überhaupt keine rolle. es gibt in c ja auch 
keine reflektions. die funktion kennt den typ also eh nicht und 
interpretiert den übergebenen wert anhand des formatstrings.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:
> H.Joachim Seifert schrieb:
>> Ich weiss es nicht genau, aber ich glaube %g macht keine Wandlung in
>> float, sondern interpretiert die 32bit-Zahl nur als solche, und das ist
>> dann falsch.
>
> Dann wäre aber etwas grausllich falsch.
> %g ist die Version von %f, die wissenschfatliche Notation in der Ausgabe
> bevorzugt. Beide Formatangaben sind ok für double/float.

Ach entschuldigung.
Ich hatte gar nicht bemerkt, dass der TO im Eröffnungsposting 2 
Versionen hatte. Eine ohne Cast und eine mit Cast. Die 'mit Cast' ist, 
geauso wie deine, korrekt.
Ohne Cast ist deswegen nicht sinnvoll, weil hier noch ein impliziter 
Cast von float auf double nachfolgt, nachfolgen muss und niemand weiß, 
ob double dieselbe Anzahl an Bytes benötigt wie ein float. Bzw. ob das 
überhaupt 4 sind.

von Dirk B. (dirkb2)


Lesenswert?

Es muss aber ein double sein, da printf keine kleineren 
Fließkommaformate kennt.
Bzw. wandelt der Compiler dann ein float in ein double.

Der Cast  mit dem (float) macht aber keine binäre Wandlung sondern eine 
numerische.

(float)(4) ergibt 4.0 und nicht die (IEEE 754) Representation für 
00000000 00000000 00000000 00000100 (was 5.6E-45 ist)

Daher musst du den Umweg über Zeiger gehen.
1
*(*float)(rx_buffer+j)

von Tuxi (Gast)


Lesenswert?

Danke Dirk!
Das war es. Mit dem umweg über nen PTR geht es einwandfrei :-)

Wieder was gelernt mit dem numerischen cast.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.