Hallo zusammen, ich hoffe, dass ich im richtigen Forum bin. Ich bin noch nicht so die Leuchte in C. Eventuell stellt euch mein Problem vor keine großen Herausforderungen, aber ich stehe noch am Anfang. Ich möchte eine Float Variable wortweise swappen und ich weiß nicht wie. Also so: Von von (Byte1,Byte2,Byte3,Byte4) nach (Byte3,Byte4,Byte1,Byte2). Wie bekomme ich das bei Float hin. Bei einem 32 Bit unsigned integer kann ich es mir noch vorstellen. Aber wie geht es bei Float-Variablen? Danke für eure Hilfe
memcopy in ein Byte Array und dann zurück. Aber die große Frage: Warum sollte man das tun? Float ist üblicherweise auf jeder Plattform gleich.
Danke. Ich kenne memcopy noch nicht, muss mich damit beschäftigen. Ich dachte schon an eine union, geht das auch? Manche Modbus Geräte wollen es anders herum. Es ist mir auch nicht so klar warum!
C-Anfänger schrieb: > Ich dachte schon an eine union, geht das auch? geht oft auch, aber ist dafür nicht gedacht und kann Nebenwirkungen haben.
C-Anfänger schrieb: > Manche Modbus Geräte wollen es anders herum. > Es ist mir auch nicht so klar warum! dort sendest du es doch auch byteweise oder nicht? Dann kannst du doch dort einfach die Bytes tauschen.
Eigentlich ist Modbus Wort-orientiert. Man sendet eigentlich nur 16 Bit-Werte. Es ist meines Wissens nicht genau definiert wie float übertragen werden (also 2 Wörter). Daher macht es auch nicht jeder Hersteller gleich. Die Anzeige die ich ansteuern will macht es halt anders herum.
C-Anfänger schrieb: > Eigentlich ist Modbus Wort-orientiert. Man sendet eigentlich nur 16 > Bit-Werte. dann tausche doch einfach die beiden Words beim senden und empfangen. Dafür musst du doch nicht die Float umdrehen.
Jetzt weiß ich was du meinst. Mein Problem ist: Ich habe eine Float Varibale: z.B. float x; Wie zerpflücke ich die Variable in zwei einzelne 16 Bit Werte.
Ich hab sowas auch für den CAN-Bus gebraucht. Hier die nötigen Funktionen:
1 | uint32_t swap_order( uint32_t val ) // LSB first -> MSB first |
2 | {
|
3 | union{ |
4 | uint32_t u32; |
5 | uint8_t u8[4]; |
6 | } in, out; |
7 | in.u32 = val; |
8 | out.u8[0] = in.u8[3]; |
9 | out.u8[1] = in.u8[2]; |
10 | out.u8[2] = in.u8[1]; |
11 | out.u8[3] = in.u8[0]; |
12 | return out.u32; |
13 | }
|
14 | |
15 | static inline uint32_t mkp_u32( float val ) // make pointer from float to uint32_t |
16 | {
|
17 | union{ |
18 | uint32_t u32; |
19 | float f; |
20 | } out; |
21 | out.f = val; |
22 | return out.u32; |
23 | }
|
24 | |
25 | static inline float mkp_fl( uint32_t val ) // make pointer from uint32_t to float |
26 | {
|
27 | union{ |
28 | uint32_t u32; |
29 | float f; |
30 | } out; |
31 | out.u32 = val; |
32 | return out.f; |
33 | }
|
C-Anfänger schrieb: > Ich möchte eine Float Variable wortweise swappen Warum solltest du ? Der Wert geht dabei kaputt. Du tauscht einige Mantissenbits mit Exponentenbits, aus 3.14526e+4 wird vielleicht -9.887e-25 oder was anderes.
Hallo, hier ein Beispiel, wie es funktionieren könnte:
1 | union convert_t // union to access the same memory location as float or byte array |
2 | {
|
3 | float fValue; // float ist auf meinem System 4 Byte lang |
4 | int32_t lValue; |
5 | uint32_t ulValue; |
6 | uint8_t bValue[sizeof(float)]; |
7 | };
|
und später im Programm:
1 | uint8_t c; |
2 | float f; |
3 | union convert_t Conv_value; |
4 | f = 1.2345; |
5 | Conv_value.fValue = f; |
6 | c = Conv_value.bValue[3]; |
7 | Conv_value.bValue[3] = Conv_value.bValue[4]; |
8 | Conv_value.bValue[4] = c; |
9 | f = Conv_value.fValue; |
ich schließe mich aber meinem Vorredner an: Erklär lieber, warum du es machen willst. Little <==> Big Endian Konvertierung für floats? Gerhard PS: statt uint8_t kannst du sicher auch char nehmen.
C-Anfänger schrieb: > Wie zerpflücke ich die Variable in zwei einzelne 16 Bit Werte.
1 | float f = 3.14f; |
2 | word[2] tmp; |
3 | |
4 | memcpy( &tmp, %f, sizeof( float ) ); |
5 | send( tmp[1] ); |
6 | send( tmp[0] ); |
Union finde ich unsauber
Michael B. schrieb: > Du tauscht einige Mantissenbits mit Exponentenbits, > aus 3.14526e+4 wird vielleicht -9.887e-25 oder was anderes. Genau das will ich machen! Natürlich geht der Wert kaputt, aber wenn der Busteilnehmer es eben so will. Das Display interpretiert es eben falsch herum.
Also zumindest habe ich es mir irgendwie einfacher vorgestellt. Danke mal an alle. Ich muss jetzt den Code ganz in Ruhe durchgehen und verstehen.
Hallo. Ich hab mir jetzt nochmal ein paar Gedanken gemacht. Geht es auch so?
1 | float u1, u1_swap; |
2 | |
3 | union{ |
4 | char c[4]; |
5 | float f; |
6 | } in, out; |
7 | |
8 | in.f = u1; |
9 | |
10 | out.c[0] = in.c[3]; |
11 | out.c[1] = in.c[2]; |
12 | out.c[2] = in.c[1]; |
13 | out.c[3] = in.c[0]; |
14 | |
15 | u1_swap = out.f; |
Wenn, dann so:
1 | float u1, u1_swap; |
2 | |
3 | union{ |
4 | char c[4]; |
5 | float f; |
6 | } in, out; |
7 | |
8 | in.f = u1; |
9 | |
10 | out.c[0] = in.c[2]; |
11 | out.c[1] = in.c[3]; |
12 | out.c[2] = in.c[0]; |
13 | out.c[3] = in.c[1]; |
14 | |
15 | u1_swap = out.f; |
C-Anfänger schrieb: > Geht es auch so? Standardkonform geht es mit Union nicht, sie ist nicht dafür gedacht. Warum willst du immer noch die float umdrehen, sende die beiden words einfach in andere Reihenfolge. Dafür braucht man keine Union, das sind 3 Zeilen fürs senden und noch mal 3 Zeilen fürs empfangen. Portabel und allgemein gültig. Senden:
1 | float f = 3.14f; |
2 | |
3 | word[2] tmp; |
4 | memcpy( &tmp, &f, sizeof( float ) ); |
5 | send( tmp[1] ); |
6 | send( tmp[0] ); |
empfangen:
1 | float f; |
2 | word[2] tmp; |
3 | read( tmp[1] ); |
4 | read( tmp[0] ); |
5 | memcpy(&f, &tmp sizeof( float ) ); |
helfer schrieb: > Wenn, dann so: Du hast recht. Sorry! Peter II schrieb: > Dafür braucht man keine Union, das sind 3 Zeilen fürs senden und noch > mal 3 Zeilen fürs empfangen. Portabel und allgemein gültig. Du hast ja auch recht. Aber ich kannte die Union vorher nicht wirklich. Jetz möchte ich sie einfach verstehen. Peter II schrieb: > Standardkonform geht es mit Union nicht, sie ist nicht dafür gedacht. Für was ist sie dann gedacht?
C-Anfänger schrieb: > Für was ist sie dann gedacht? um Speicher zu sparen. Man sollte/darf nur die variabel auslesen die man vorher auch geschrieben hat. Dann kann es noch Probleme bei Alignment gehen, auf einigen System muss float an gewissen Speicheradressen ausgerichtet sein, das geht dann bei einer Union nicht mehr.
Peter II schrieb: > Warum willst du immer noch die float umdrehen, sende die beiden words > einfach in andere Reihenfolge. Üblicher Weise bastelt man erst ein komplettes Paket und übergibt der Sendefunktion nur den Pointer darauf. Es können ja mehrere Tasks gleichzeitg senden wollen.
Peter D. schrieb: > Üblicher Weise bastelt man erst ein komplettes Paket und übergibt der > Sendefunktion nur den Pointer darauf. Es können ja mehrere Tasks > gleichzeitg senden wollen. wenn man genug speicher hat ja, wenn man mehre stellen hat die Senden können muss mit sperren arbeiten. Aber auch dann kann man es genau machen, statt Send() füllt man man sein puffer-byte-Array ab.
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.