Entwickler-Ecke

Basistechnologien - BitConverter.ToSingle wie wird eine float Variable erstellt?


C# - Di 29.04.14 18:09
Titel: BitConverter.ToSingle wie wird eine float Variable erstellt?
Hey Leute,

ich habe gerade ein Problem mit einer Floatkonvertierung. Ich habe einen Mikrocontroller der mir via COM-Port Daten schickt. Klappt alles soweit ganz gut. Wenn ich jetzt aber eine float Variable übertrage, erhalte ich nur mist, sowohl bei little, als auch big endian. Ich weis leider nicht genau wie eine float Variable aufgebaut ist. Im Controller (ATMega88) erzeuge ich das Bytearray via

Quelltext
1:
2:
3:
4:
void FloatToBytes(float val, byte* target)
{
  memcpy(target, &val, sizeof(float));
}

Jetzt weiß ich aber nicht ob ich das so einfach machen kann. Im Internet habe ich auch keine andere Konvertierungsmethode gefunden, da Bitshifting leider nicht geht bei Gleitkomma.
Weiß jemand wie ich da die float wieder richtig zurückgewandelt bekomme?


Th69 - Di 29.04.14 18:44

Hallo C#,

Float-Zahlen sollten eigentlich auch beim ATMega nach dem IEEE 754 [http://de.wikipedia.org/wiki/IEEE_754]-Format aufgebaut sein, also so wie auch in der .NET-Welt.

Daher sollte eigentlich die Konvertierung mittels BitConverter.ToSingle richtig sein.

PS: Hast du denn im C-Code auch genügend Speicher für das byte-Array bereitgestellt, also byte target[sizeof(float)]?


C# - Di 29.04.14 21:00

Jup genau so mach ichs...

Quelltext
1:
2:
3:
4:
5:
6:
void SendFloat(float data, byte eventID)
{
  byte arr[sizeof(float)];
  FloatToBytes(data, arr);
  SendBlock(arr, eventID);
}


NACHTRAG
Kann es sein, dass der SerialPort irgendwie Probleme hat? Ich merke nämlich gerade, dass ich immer nur 2 der 4 Bytes empfange :gruebel:

Ich habe den Port so initialisiert:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
if (port != null && port.IsOpen) port.Close();

      port = new SerialPort
      {
        PortName = portName,
        BaudRate = BaudRate,
        StopBits = StopBits.One,
        DataBits = 8,
        ReceivedBytesThreshold = 1,
        Parity = Parity.None
      };

      port.DataReceived += DataReceived;
      port.Open();

Gibt das ein Problem, wenn ich den Empfangspuffer auf 1 Byte lege?

NACHTRAG 2
Vergesst dass wieder. Strings und Integer werden voll empfangen. Nur die verdammten floats nicht...


Th69 - Di 29.04.14 21:32

Ist denn sizeof(float) auf dem Mikroboard wirklich 4?

Und könntest du mal ein Beispiel hier posten, was du als float schickst (am besten mal eine einfache Zahl wie 1.0 oder 2.0 o.ä.) und was dabei als byte-Array dann empfangen wird?


C# - Di 29.04.14 21:44

Also wenn ich SendFloat(2.0, EVENT_DISTANCE_UPDATED); sende, erhalte ich 0 0 (2 bytes). Hmm bei 1.25 empfange ich auf einmal auch nur noch Nullen. Das war gerade noch anders :-/
Ahhh und wenn ich statt 1.25 1.253f schreibe, erhalte ich 78 98 und wenn ich 1.0f mache erhalte ich wieder 0 0

Nachtrag
Habs aufgegeben. Hab jetzt alle floats durch int ersetzt. Muss ich nen kleinen workaround machen. Trotzdem Danke


Th69 - Mi 30.04.14 09:39

Hallo nochmals,

wie sieht denn deine SendBlock-Methode aus? Du übergibst da ja nur das Array (als Zeiger) und keine Länge - nicht daß du dort die falsche Länge überträgst (ich hoffe du verwendest dort nicht sizeof(arr)?)...


C# - Mi 30.04.14 12:50

:lol: doch genau so mach ichs


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
void SendBlock(byte data[], byte eventID)
{
  if (!usartInitialized) return;
  
  if (eventID != EVENT_SUPRESS_ID) Send(eventID);
  for (int i = 0; i < sizeof(data); i++) Send(data[i]);
}


Ich habe ja ein byte array dann sollte das doch gehen oder?

Nachtrag
Oh Schande über mich. Jetzt weiß ich was du meinst. Es wird nur ein Pointer übergeben und der ist nur 2 Bytes groß. Mir ist das nur nie aufgefallen, weil das Maximum bei SendBlock immer 2 Bytes waren xD


Th69 - Mi 30.04.14 19:33

Tja, manchmal erinnere ich mich noch an meine C-Wurzeln (und eigenen Fehlern). :lol: