Float Variable wortweise swappen

Gast #4317155
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
Gast #4317177
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!
Gast #4317189
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.
#4317199
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
}
Gast #4317202
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.
Gast #4317217
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.
Gast #4317788
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;
Gast #4317790
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;
Gast #4317791
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 ) );
Gast #4317796
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?
Gast #4317801
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.
Gast #4317826
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren