2017-06-04 1 views
-1

Ich versuche derzeit, Floats über USB zu senden. Der PC weist eine Qt-Anwendung den folgenden Code ausgeführtSTM32 Float über USB vom PC, Endianess kämpfen

float x = 2.0; 
memcpy(buffer.data() + 14, &x, sizeof x); 

mit der DebugLog Funktion i eindeutig die Serie von Bytes sieht

.. 00 00 00 40 .. 

mit der folgenden Reihenfolge, die durch die an dieser Stelle nach

http://www.scadacore.com/field-tools/programming-calculators/online-hex-converter/

wird bei geringer Endianität in 1073741824 umgewandelt.

auf meinem STM32 kann ich den folgenden Code verwenden, um dann einschalten LED4

uint32_t a = buffer[14] | (buffer[15] << 8) | (buffer[16] << 16) | (buffer[17] << 24);      
if (a == 1073741824){ 
    HAL_GPIO_WritePin(LED4_PORT, LED4_PIN, GPIO_PIN_RESET); 
} 

Das Problem entsteht, wenn ich auf die Real float-Wert konvertiert werden soll 2.0

in der Tat, wenn ich tun

float b = buffer[14] | (buffer[15] << 8) | (buffer[16] << 16) | (buffer[17] << 24); 
if (b == 2.0f){ 
    HAL_GPIO_WritePin(LED5_PORT, LED5_PIN, GPIO_PIN_RESET); 
} 

Die LED5 schaltet sich nicht ein.

Ist es ein Endianess-Problem? Wie kann ich den Gleitkommawert 2.0 erhalten?

Grüße,

+1

Senden Sie die Floats als ASCII-Text und konvertieren Sie sie am anderen Ende zurück. Es ist einfach sicherer und einfacher. – ThingyWotsit

+0

"2.0" mit einem abschließenden Zeichen, (CR oder NUL sagen), ist die gleiche Größe wie eine einzige, und kann nicht leicht fehlinterpretiert werden, solange beide Seiten das Protokoll kennen, und dann können Sie fast alles mit allem kommunizieren. Außerdem vermeidet das Protokoll mit dem abschließenden Zeichen die Probleme mit Streaming-Verbindungen, bei denen ein rx-Aufruf "früh" mit weniger Bytes zurückgibt, als für eine vollständige Nachricht/Float benötigt wird. – ThingyWotsit

+0

können Sie ein Beispiel geben? – Luigi

Antwort

1

Für 754 Schwimmer IEEE ist die Endianess in der Regel kein Problem, aber überprüfen, um sicher gerade zu sein.

Ihr Hauptproblem ist das Lesen des Wertes. Sie ORing Wert in ganzzahligen Arithmetik und erhalten einen ganzzahligen Wert, der korrekt ist, aber dann konvertieren es zu float. Dies ergibt immer Müll, außer für 0.

Sie müssen es als Float neu interpretieren. Sie können:

  • Ein Zeiger Besetzung: float a = *(float*)&myInt;
  • A memcpy: memcpy(&myFloat, &myInt, 4);
  • Eine Vereinigung: union { uint32_t i; float f; };, u.i = myInt; float f = u.f;

Sie müssen auch vorsichtig sein, wenn Gleitkomma-Vergleich. Es ist im Allgemeinen eine schlechte Idee, if(f == 2.0f) zu schreiben, weil 2.0f eine Annäherung ist. Es ist besser, == zu vermeiden und stattdessen > >= < <= zu verwenden. Wenn Sie einen bestimmten Wert und nicht einen Bereich überprüfen möchten, sollten Sie einen ausreichend kleinen Bereich um Ihren Wert herum prüfen, wobei Ihr Bereich Ihren Präzisionsanforderungen entspricht.

+0

Ich werde es versuchen und es wieder melden. Jedenfalls dachte ich, dass ein gegebenes uint32 nur zu einem festen float übersetzen kann. Es ist nicht? – Luigi

+0

@ Luigi Ja, jedes Uint32 kann einen gültigen, anderen Float darstellen. Durch die Konvertierung erhalten Sie jedoch nur einen Bruchteil des Float-Bereichs und nicht die, die Sie in Ihrem Fall haben möchten. Zum Beispiel wird '1.0f' als' 0x3F800000' dargestellt, eine Ganzzahl, die nicht '1.0' ergibt, wenn ** sie ** konvertiert wird. – ElderBug

+0

Gibt es eine Verknüpfung, um nur/direkt mit den Elementen des Arrays zu arbeiten? – Luigi

Verwandte Themen