Forum: Mikrocontroller und Digitale Elektronik Float Variable wortweise swappen


von C-Anfänger (Gast)


Lesenswert?

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

von Peter II (Gast)


Lesenswert?

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.

von C-Anfänger (Gast)


Lesenswert?

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!

von Peter II (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von C-Anfänger (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von C-Anfänger (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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
}

von Michael B. (laberkopp)


Lesenswert?

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.

von Gerhard (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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

von Gerhard (Gast)


Lesenswert?

Gerhard schrieb:
> hier ein Beispiel, wie es funktionieren könnte:

uff, viel zu langsam ;-)

von C-Anfänger (Gast)


Lesenswert?

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.

von C-Anfänger (Gast)


Lesenswert?

Also zumindest habe ich es mir irgendwie einfacher vorgestellt.
Danke mal an alle.
Ich muss jetzt den Code ganz in Ruhe durchgehen und verstehen.

von C-Anfänger (Gast)


Lesenswert?

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;

von helfer (Gast)


Lesenswert?

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;

von Peter II (Gast)


Lesenswert?

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 ) );

von C-Anfänger (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.