Hallo Leute. Ich will einen float Wert zu einem anderen µC übertragen. Ich hatte vor den float auf meinem stm32 byteweise auf den anderen controller zu schieben. Soweit kein Problem. Das problem ist, der empfangende Controller ist kein STm32/ kein ARM!!. Somit muss ich wissen nach welchem schema der Compiler den Float abspeichert. Weiß jemand was? Ps: Wie ein Double gespeichert wird würde mich auch interessieren :)
Gut, zu wissen was es alles nicht ist. Aber was ist es?
>Somit muss ich wissen >nach welchem schema der Compiler den Float abspeichert. Nimm deinen Debugger, speichere 1.2345f irgendwo als volatile float ab und vergleiche den Inhalt im Speicher.
Da der keine FPU hat hängt das vom Compiler ab. Dessen Handbuch wird es wissen. ARM hat IEEE754 Format, STM32 little endian.
A. K. schrieb: > Da der keine FPU hat hängt das vom Compiler ab. Der Stm32f4 hat eine FPU! A. K. schrieb: > ARM hat IEEE754 Format, STM32 little endian. Der STM32 ist ein ARM??!?!?!?!?!
>Der Stm32f4 hat eine FPU!
Der dsPic aber nicht. Also nochmal meinen Post oben
lesen, dann weisst du ganz genau ob die beiden zusammenpassen.
holger schrieb: > Der dsPic aber nicht. Also nochmal meinen Post oben > lesen, dann weisst du ganz genau ob die beiden zusammenpassen. Ok. Dann lese ich mich mal in IEEE754 ein. Den dsPIC hab ich schon :) bzw. Weiß wo ich die Info herbekomm Danke
>Der Stm32f4 hat eine FPU!
Double kann die übrigends nicht. Das wird in Software gemacht.
Jetzt frage ich mich nur noch weshalb man ein float
von einem Zahlenmonster zum anderen verschicken will.
holger schrieb: > Double kann die übrigends nicht. Das wird in Software gemacht. Spielt in dieser Frage keine Rolle, da das Format von ARM im ABI festgelegt sein dürfte, unabhängig davon, wie es implementiert wird. Nur die Byteorder ist dann vom exakten ARM abhängig.
M. H. schrieb: > Der STM32 ist ein ARM??!?!?!?!?! Die STM32 haben Cortex-M Cores, und die sind von ARM.
M. H. schrieb: > Den dsPIC hab ich schon :) bzw. Weiß wo ich die Info herbekomm Doku vom Compiler vermutlich. Evtl. ABI Doku, falls es die vom Microchip separat gibt. Von ARM gibt es die.
:
Bearbeitet durch User
A. K. schrieb: > M. H. schrieb: >> Der STM32 ist ein ARM??!?!?!?!?! > > Die STM32 haben Cortex-M Cores, und die sind von ARM. Das weiß ich auch.. Ich glaube wenn man das nicht wüsste siehts schlecht aus mitm Programmieren :) Ich hab nur den Kontext der Aussage verramscht. Mein Satz war eine Feststellung, mit verwirrtem Hintergrund
M. H. schrieb: > Somit muss ich wissen > nach welchem schema der Compiler den Float abspeichert. Weiß jemand was? Guck's dir einfach an. Leg dir ein float Variable in den Speicher, setzt sie auf 1.0 und dann guck dir an, was im Speicher passiert, wenn du sie in einer Schleife immer weiter durch 2 teilst bzw. mit 2 multiplizierst. Damit siehst du schnell wie der Exponent incl. Vorzeichen liegt. Und dann ist der Rest einfach die Mantisse. Wegen der Normalisierung ist das erste Bit langweiig und wird meist weg gelassen.
Die einzig wirklich robuste und portable Option wäre es wohl die float bzw. double Zahl in einen String (oder ein anderes "standardisiertes" Format) zu bringen, und anschließend dieses zu übertragen. Das ist zwar mit Overhead verbunden (printf, scanf, usw.), dafür aber unabhängig von der verwendeten Hardware und verschiedenen Software Implementierungen. Wie kommunizieren die beiden Mikrocontroller denn eigentlich? UART? SPI? I2C? Mit freundlichen Grüßen, Karol Babioch
:
Bearbeitet durch User
Eine exakte Serialisierung ohne printf bekommt man fast schon mit Standardmitteln hin:
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <inttypes.h> |
4 | #include <math.h> |
5 | |
6 | // double = sign * mant * 2 ^ (ex - __DBL_MANT_DIG__)
|
7 | typedef struct |
8 | {
|
9 | int sign, ex; |
10 | uint64_t mant; |
11 | char s_mant[2 + __DBL_MANT_DIG__ /* GCC */]; |
12 | } double_t; |
13 | |
14 | void d2d (double x, double_t *d) |
15 | {
|
16 | uint64_t mant = 0; |
17 | d->sign = copysign (1.0, x) < 0.0 ? -1 : 1; |
18 | double r = frexp (copysign (x, 1.0), & d->ex); |
19 | char *s = d->s_mant; |
20 | |
21 | *s++ = '.'; |
22 | for (int i = 0; i < __DBL_MANT_DIG__ /* GCC */; i++) |
23 | {
|
24 | r = ldexp (r, 1); |
25 | unsigned b = r >= 1.0; |
26 | r -= b; |
27 | mant = (mant << 1) | b; |
28 | *s++ = '0' + b; |
29 | }
|
30 | *s++ = '\0'; |
31 | d->mant = mant; |
32 | }
|
33 | |
34 | |
35 | int main() |
36 | {
|
37 | int mdig = __DBL_MANT_DIG__; // GCC |
38 | double x = -1.000000000000001; |
39 | double_t d; |
40 | for (int i = 0; i < 10; i++) |
41 | {
|
42 | d2d (x, &d); |
43 | printf ("%.16f = %c0b0%s * 2^%d\n", x, |
44 | d.sign > 0 ? '+' : '-', d.s_mant, d.ex); |
45 | x = nextafter (x, HUGE_VAL); |
46 | }
|
47 | |
48 | return EXIT_SUCCESS; |
49 | }
|
Gibt:
1 | -1.0000000000000011 = -0b0.10000000000000000000000000000000000000000000000000101 * 2^1 |
2 | -1.0000000000000009 = -0b0.10000000000000000000000000000000000000000000000000100 * 2^1 |
3 | -1.0000000000000007 = -0b0.10000000000000000000000000000000000000000000000000011 * 2^1 |
4 | -1.0000000000000004 = -0b0.10000000000000000000000000000000000000000000000000010 * 2^1 |
5 | -1.0000000000000002 = -0b0.10000000000000000000000000000000000000000000000000001 * 2^1 |
6 | -1.0000000000000000 = -0b0.10000000000000000000000000000000000000000000000000000 * 2^1 |
7 | -0.9999999999999999 = -0b0.11111111111111111111111111111111111111111111111111111 * 2^0 |
8 | -0.9999999999999998 = -0b0.11111111111111111111111111111111111111111111111111110 * 2^0 |
9 | -0.9999999999999997 = -0b0.11111111111111111111111111111111111111111111111111101 * 2^0 |
10 | -0.9999999999999996 = -0b0.11111111111111111111111111111111111111111111111111100 * 2^0 |
Wie man sieht zählt die Mantisse in jedem Schritt brav um 1 LSB hoch. Hinzu kommt dann noch Behandlung von NaN, Inf, Denormals, +/-0, etc. Wem die Schleife zu unbequem ist oder keine String-Darstellung braucht kann auch einfach
1 | d->mant = ldexp (r, __DBL_MANT_DIG__); |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.