Float Variable wortweise swappen

Gast #4317155
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
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
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.
Gast
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
}
Gast
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
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
Also zumindest habe ich es mir irgendwie einfacher vorgestellt.
Danke mal an alle.
Ich muss jetzt den Code ganz in Ruhe durchgehen und verstehen.
Gast
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
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
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
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
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
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

Eine eigene Frage? Dieser Thread ist über 11 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.