Ich besitze einen neuen XMEGA128A3.
Nun habe ich eine Sinustabelle auf dem µC berechnet. Diese möchte ich
zur Kontrolle einfach mal über RS232 an den PC senden. Der Zahlentype
float ist ja ein 32Bit Wert. Nun habe ich gedacht das ich einfach 4x 8
Bit nacheinander an den PC sende und diese 32 Bit am PC wieder zu einem
float zusammensetze. Jedoch fangen da die Probleme an.
Ich benutze den Codeviosion Compiler für µC. Diese zeigt mir einen Error
an wenn ich den Operrand >> bei float Zahlen benutzen möchte.
Was willst du eigentlich auf der PC-Seite damit anfangen?
So wie oben müsstest du aus den einzelnen Byte dort wieder
eine float in der richtigen Reihenfolge zusammensetzen.
Vielleicht wäre es für Log-Zwecke geschickter, aus den
Zahlen einen String zu machen und den zu senden.
Dann kann man bspw. auf der PC-Seite einfach mit einem
Terminalprogramm verfolgen, was passiert, und muß nicht
extra ein Programm dafür bauen.
Ich würde das auch über den ASCII-String machen. Dann kann die
Übertragung auch problemlos mit jedem terminal mitprotokolliert werden.
Aber trotzdem: Falsches Forum, bitte verschieben...
[erledigt -- Jörg]
Klaus Wachtler schrieb:> Das was du vorhast, geht etwa so: float test = 2.4536;>> putchar( (*(uint32_t*)&test) );> putchar( (*(uint32_t*)&test) >> 8 );> putchar( (*(uint32_t*)&test) >> 16 );> putchar( (*(uint32_t*)&test) >> 24 );>> Geschickter (u.a., weil es wesentlich schnelleren Code erzeugt)> wäre: float test = 2.4536;>> putchar( ((uint8_t*)&test)[0] );> putchar( ((uint8_t*)&test)[1] );> putchar( ((uint8_t*)&test)[2] );> putchar( ((uint8_t*)&test)[3] );>> Portabel ist beides nicht.
Ich gestehen das ich bei diesem Code noch nicht so ganz durchblicke. Ich
habe eine 32Bit float variable mit dem Namen test. Die Funktion putchar
erwartet eine 8Bit Wert als Parameter.
Kann vielleicht jemand versuchen mir diese Quellcodezeile in 2 Sätzden
zu erklären. putchar( ((uint8_t*)&test)[0] );
Martin schrieb:> float test = 2.4536;>> putchar( ((uint8_t*)&test)[0] );
Das bedeutet:
Betrachte den Speicherbereich an der Adresse test (wo ja die 4 Bytes des
floatwertes abgelegt sind) als char-Array und übergebe das erste Byte an
dieser Stelle an die Funktion putchar().
Dazu muß man wissen, dass ein float 4 Bytes lang ist.
Was bei dieser Betrachtung allerdings aussen vor gelassen wird, ist die
Tatsache, dass du dir damit eine Problematik bei der Datenübergabe
zwischen mit Little- und Big-Endian Sytemen einhandelst. Dann ist der
float im Empfänger einfach in der falschen Reihenfolge, und damit stimmt
der Wert nicht mehr.
An putchar() kann man auch eine ganze Zahl übergeben, die
größer als ein Byte ist. Dann wird nur das unterste Byte
genommen, der Rest ignoriert.
Wenn du jetzt aber eine float an putchar() übergibst,
würde der Compiler zuviel denken und die float in eine
ganze Zahl wandeln. Also z.B. aus 3.1415 würde eine 3, und
das Byte mit dem Wert 3 (in ASCII ist das ETX, wenn ich
mich recht entsinne) übergeben.
Mit &test nimmt man von der float die Adresse.
Dadurch ist &test ein Zeiger auf float.
Der Zeiger &test zeigt also auf das unterste der vier Byte
von test.
Mit (uint8_t*) davor macht man daraus einen Zeiger auf
Byte (Zeiger auf uint8_t). Es sind natürlich immer noch die
float-Bytes, auf die gezeigt wird, aber der Compiler
behandelt den Zeiger jetzt auf Zeiger auf die einzelnen Bytes.
Das könnte der Zeiger auf ein uint8_t sein, oder auf den Anfang
eines ganzen Feldes davon. Das ist in C erstmal beides gleich.
Mit den [0], [1], [2] und [3] wird nun auf die einzelnen
Bytes des vermeintlichen Feldes zugegriffen, also auf die
einzelnen Bytes der float.
Ich habe schon verstanden was Du damit erzeugen willst, jedoch war mir
die Schreibweise zu kompakt.
Man erzuegt sich einen Pointer der auf einen vorzeichenlosen 8 Bit Wert
zeigt. Dann weist man die Adresse vom 0 Element (also Bit 0 bis Bit 7)
der Float Zahl dem Pointer zu.
Anschließend gibt man die Inhalt der Adresse auf die der Pointer zeigt
aus und erhöht die Adresse des Zeigers um 1.
Dies habe ich leider nicht aus dem kompakten Code herauslesen können.
Ich hätte es in mehreren Schritten gemacht (da ich noch nicht so geübt
bin).
Trotzdem TAUSEND DANK für die Info,
Martin schrieb:> Dann weist man die Adresse vom 0 Element (also Bit 0 bis Bit 7)> der Float Zahl dem Pointer zu.
Es wird hier keinem Pointer etwas zugewiesen, ...
Martin schrieb:> erhöht die Adresse des Zeigers um 1
... und es wird nicht die ADRESSE des Zeigers erhöht, sondern
zu seinem WERT (der ein Zeiger ist) wird etwas addiert.
(Compiler sind übrigens ebenso pingelig, das ist also
keine Schikane meinerseits.)
Martin schrieb:> Es wird etwas übertargen jetzt muss ich den Wert noch in einen float> zurückwandeln
Du mußt jetzt genau das selbe rückwärts machen:
Nimm die einzelnen Bytes, schrieb sie über einen char-Pointer in den
Speicherplatz des floats. Fertig (abgesehen von der Little- und
Big-Endian-Problematik).
Und dann lass das in einer ruhigen Minute mal auf dich wirken und
überleg, was du da gemacht hat...
Lothar Miller schrieb:> Du mußt jetzt genau das selbe rückwärts machen:>> Nimm die einzelnen Bytes, schrieb sie über einen char-Pointer in den>> Speicherplatz des floats. Fertig (abgesehen von der Little- und>> Big-Endian-Problematik).>>>> Und dann lass das in einer ruhigen Minute mal auf dich wirken und>> überleg, was du da gemacht hat...
Also, das ist doch gemein dem armen Martin gegenüber. Korrigier mich mal
jemand, der Bescheid weiß, aber solange nicht die Compiler auf AVR- und
PC-Seite beide nach IEEE754 arbeiten, ist doch diese Vorgehensweise zum
Scheitern verurteilt, oder?
Haben die Intel Prozessoren nicht ein 80-Bit Fließkommaformat?
Damit hier irgendwas funktioniert, müssen so viele Nebenbedingungen
gegeben sein, dass ich bezweifle, dass wir Martin hier irgendwie
geholfen haben.
Grüße,
Stefan
Stefan Hennig schrieb:> Haben die Intel Prozessoren nicht ein 80-Bit Fließkommaformat?
Wenn er eine float auf dem PC vereinbart, hat die ebenfalls 4 Byte.
Und zufällig die gleiche Auslegung...
Es gibt natürlich Unterschiede, z.B. würde ich nicht unbesehen
behaupten, daß NAN, +/-INF etc. gleich (oder überhaupt) auf
dem AVR behandelt wird.
Aber für "normale" Zahlen wird es klappen.
LE ist auch zufällig gleich.
Stefan Hennig schrieb:> Haben die Intel Prozessoren nicht ein 80-Bit Fließkommaformat?
Wenn ich mich richtig erinnere, dann arbeitet oder arbeitete die FPU
intern mit 80 Bit um Rundungsfehler zu vermindern.
Im Speicher abgelegte double oder floats haben aber 8 Byte/4 Byte