Ein Modbus Slave liefert eine 32-bit Fließpunktzahl die in zwei 16-bit Register aufgeteilt ist. Beispiel: Reg 30001: 0x43FA Reg 30002: 0x9B9A Diese beiden aneinandergereihten Zahlen sollen als 0x43FA9B9A in eine IEEE-754 Fließpunktzahl umgeandelt werden, sodaß dies wie in diesem Fall 501.21 als float ergibt. Git es für den gcc eine lib? Oder wie macht man das am einfachsten?
Fragestellender schrieb: > Oder wie macht man das am einfachsten? wenn deinen CPU intern auch IEEE-754 verwendet kannst du es einfach verwenden.
1 | unsigned char tmp[2]; |
2 | tmp[0] = 0x43FA; |
3 | tmp[1] = 0x9B9A; |
4 | |
5 | float f; |
6 | memcpy( &f, &tmp, sizeof( float ) ); |
eventuell die Reihenfolge tauschen.
In welchem Format speichert denn Dein gcc floats? Was geschieht, wenn Du folgendes ausprobierst:
1 | uint16_t eins = 0x43fa; |
2 | uint16_t zwei = 0x9b9a; |
3 | |
4 | uint32_t beides; |
5 | float wert; |
6 | |
7 | |
8 | beides = eins << 16; |
9 | beides += zwei; |
10 | |
11 | wert = *(float *) &beides; |
Was steht jetzt in "wert"?
Rufus Τ. F. schrieb: > wert = *(float *) &beides; hatten wir doch gerade: Beitrag "uint32_t => float (32) ohne cast!" das ist so nicht zulässig (auch wenn es oft funktioniert)
korrektur: [c] uint16_t tmp[2]; tmp[0] = 0x43FA; tmp[1] = 0x9B9A; float f; memcpy( &f, &tmp, sizeof( float ) );
Peter II schrieb: > das ist so nicht zulässig Akademisch gesehen ja, hier aber ist es so ziemlich die einzige Möglichkeit. Man könnte natürlich die Funktion, die das Modbus-Telegramm interpretiert, so umbasteln, daß es den ankommenden Bytestrom gleich passend in float verpackt, aber das ist effektiv genau das gleiche in grün.
Rufus Τ. F. schrieb: > Akademisch gesehen ja, hier aber ist es so ziemlich die einzige > Möglichkeit. was gefällt dir an meiner Lösung nicht?
Autor: Rufus Τ. Firefly (rufus) (Moderator) schrieb:
>Was steht jetzt in "wert"?
Hat funktioniert. Danke!
Das erste Beispiel von Peter II ging nicht, da kam nur 0.0000 raus.
Fragestellender schrieb: > Das erste Beispiel von Peter II ging nicht, da kam nur 0.0000 raus. das kann nicht sein.
Wenn die Endianess des Systems passt, geht auch folgendes:
1 | uint16_t reg0; |
2 | uint16_t reg1; |
3 | uint32_t u; |
4 | float f; |
5 | |
6 | reg0 = 0x43FA; |
7 | reg1 = 0x989A; |
8 | |
9 | u = (reg0 << 16) | reg1; |
10 | f = *(float *)(&u); |
11 | |
12 | printf("u: %08X f: %.2f\n", u, f); |
Peter II schrieb: > Fragestellender schrieb: >> Das erste Beispiel von Peter II ging nicht, da kam nur 0.0000 raus. > > das kann nicht sein. ok kann doch sein, wie oben geschrieben die Reihenfolge tauschen.
1 | #include <stdio.h> |
2 | #include <stdint.h> |
3 | #include <string.h> |
4 | |
5 | int main() |
6 | {
|
7 | uint16_t tmp[2]; |
8 | tmp[1] = 0x43FA; |
9 | tmp[0] = 0x9B9A; |
10 | |
11 | float f; |
12 | memcpy( &f, tmp, sizeof( float ) ); |
13 | |
14 | printf("test=%f\n", f ); |
15 | }
|
Joe F. schrieb: > Wenn die Endianess des Systems passt, geht auch folgendes: auch hier ist der unzulässig cast vorhanden.
Peter II schrieb: > auch hier ist der unzulässig cast vorhanden. wieso unzulässig? Nachtrag: ah ok. habe mir den Thread Beitrag "uint32_t => float (32) ohne cast!" zu spät angesehen. gcc auf OSX macht's zwar richtig, aber kann Zufall sein. Nehme daher meinen Vorschlag zurück.
:
Bearbeitet durch User
Autor: Peter II (Gast) schrieb um 14:57:
1 | #include <stdio.h> |
2 | #include <stdint.h> |
3 | #include <string.h> |
4 | |
5 | int main() |
6 | { |
7 | uint16_t tmp[2]; |
8 | tmp[1] = 0x43FA; |
9 | tmp[0] = 0x9B9A; |
10 | |
11 | float f; |
12 | memcpy( &f, tmp, sizeof( float ) ); |
13 | |
14 | printf("test=%f\n", f ); |
15 | } |
Interessant ist, daß wenn man tmp[1] und tmp[0] vertauscht, -0.0000 rauskommt... hihi... was nach IEEE-754 Notation durchaus richtig ist. Es soll mal jemand bei der US-Marine als Geschwindigkeit -0.0 Knoten in den Rechner eines Zerstöres eingegeben haben, worauf der Zentralrechner abstürzte und das Schiff für zwei Stunden lahmlegte.
Fragestellender schrieb: > -0.0 Knoten in > den Rechner eines Zerstöres eingegeben haben, worauf der Zentralrechner > abstürzte und das Schiff für zwei Stunden lahmlegte. Das war bestimmt der gleiche Zerstörer, der einen spanischen Leuchtturm per Funk zum ausweichen zwingen wollte... https://www.youtube.com/watch?v=_VHXRYXzEVU (Satire!)
:
Bearbeitet durch User
Man sollte auf jeden Fall beachten, wie die Bytes angeordnet werden (Big- oder Little-Endian)
Peter II schrieb: > was gefällt dir an meiner Lösung nicht? Das ist das gleiche, nur anders verpackt. Zulässiger im akademischen Sinne ist es auch nicht.
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.