Hallo wie kann ich am einfachsten ein float in Raw Bytes splitten (ARM
GCC). Ich möchte float Zahlen übertragen. Auf der PC Seite verwende ich
eine fertige funktion die in Java verfügbar ist, wie mach ich das auf
der ARM Seite.
Besten Dank schon mal.
mgiaco
So mache ich es in JAVA aber mir fehlt hier auf der gcc Seite die
Funktion floatToRawIntBits(). Und nur mit einem Typecast geht es nicht.
Wie kann ich von der float Zahl jedes Byte einzeln lesen?
danke
Jepp bin ich sicher ich portier gerade eine funktionsfähiges Progamm von
Java nach C, von dort stammt das von oben. Danke werde es gleich mal
ausprobieren ich dachte nicht an union, sieht aber sehr einfach aus im
Vergleich zu java.
mgiaco
Hallo
Interessante Variante. Wie wird der Code aber nun übersetzt bzw. was ist
v.a. schneller? Das Kopieren per Type-casting oder per memcpy für ARM
mit gcc?
z.B.
char buf[4];
float f = 10;
memcpy(buf,f,sizeof(f);
Beste Grüsse
Geri
Am schnellsten dürfte sowas sein:
float f = 10;
char* buf = (char*)&f;
Hier muß nämlich nicht kopiert werden. f wird direkt als Array aus char
interpretiert.
Das würde ich so nicht schreiben, denn da ist ein passendes Alignment
nicht garantiert. Es ist eine Sache, einen float als Array aus char zu
interpretieren, denn das geht immer, da char kein spezielles Alignment
braucht. Wenn du aber umgekehrt ein Array aus char als float
interpretieren willst, sieht's anders aus, denn ein float muß beim ARM
an einem vielfachen von 4 Bytes starten.
@ Magnus. Aha okay aber wie realisiere ich jetzt richtig eine
floatToRawBytes() und eine RawBytesToFloat() auf dem ARM7? Ich brauch
also beide Seiten (Senden und Empfangen).
besten dank schon mal.
Da wirst du dann wohl nicht umhin kommen, das char Array
das du als Buffer benutzt richtig zu alignen.
zb so
float tmpBuffer[20];
char* buffer = (char*)buffer;
Jetzt hast du ein char Array bei dem du mittels
(float*)&(buffer[NrFloat*sizeof(float)])
reinindizieren kannst, und wo das Alignment für float
passen müsste.
@karl heinz
>>float tmpBuffer[20];>>char* buffer = (char*)buffer;
wiso float tmpBuffer[30] ?? verstehe ich nicht.
Ich brauche eine Funktion
Float -> 4Byte für Senden.
und eine
4Byte -> Float für Empfangen.
mgiaco wrote:
> @karl heinz>>>>float tmpBuffer[20];>>>char* buffer = (char*)buffer;>> wiso float tmpBuffer[30] ?? verstehe ich nicht.>> Ich brauche eine Funktion>> Float -> 4Byte für Senden.>> und eine>> 4Byte -> Float für Empfangen.
Dann machst du halt nur 1 float.
Ich kann ja nicht wissen, wieviele float du zu übertragen
hast
float tmpBuffer;
char* buffer = (char*)&tmpBuffer;
Hallo es funktioniert leider noch nicht, ich denke ich mache generell
was falsch. Habe verschiedenes probiert komme aber nicht zu einer Lösung
die funktioniert. floatToRawByteArray ist nich das problem jedoch das
zurück wandeln.
return *((float*)&(buffer[offset]));
statt offset müsste da 0 stehen oder einfach return tmpBuffer oder das
umkopieren weglassen und gleich return *((float *)&data[i + offset]);
(falls die Byte-Order passt)
@Arc Net danke, aber wenn ich das umkopieren weglasse dann stimmt ja das
alignment nicht, so habe ich es zumindestens verstanden. Deshalb das mit
dem kopieren.
Zu offset super danke ich hab den Fehler nicht gesehen. Jetzt geht es ob
es auch die schnellste implementierung ist weis ich nicht was meinen die
Experten ?
Warum? Das einzige wäre vielleicht noch das schon angesprochene
rawByteArrayToFloat, das man genauso wie die Int32-Version
implementieren könnte.
Je nach Compiler und/oder Architektur könnte bei der anderen Richtung
auch eine Variante ohne Shifts schneller/kürzer sein.
Da sind jetzt dieselben Elemente wie in der 'Hin-Version' enthalten,
nur alles genau anders rum. Dementsprechend weniger muss ich überlegen,
ob diese Operation das Gegenteil der Hin-Operation ist.
Deine Version ist zwar nicht falsch, kommt mir aber so vor wie
wenn du eine hypotetische Hin-Operation mit einer Division
implementierst, während du die Rückoperation mittels fortgesetzter
Addition in einer Schleife (anstelle einer Multiplikation) machst.
Edit: Ooops. Sehe gerade, dass die relevanten Codeteile vom
August stammen. Da wird der Poster wohl hier nicht mehr rumlungern :-)
naja es gibt auch andere die das selbe Problem haben und da ist es sehr
hilfreich hier reinzuschauen..
>Edit: Ooops. Sehe gerade, dass die relevanten Codeteile vom>August stammen. Da wird der Poster wohl hier nicht mehr rumlungern :-)
es muss ja nicht für den OP sein, ich bin ja auch noch da und kann es
bei mir einsetzten. Dein Vorschlag finde ich super, echt einfach und
geschickt ;-)
Code wrote:
> es muss ja nicht für den OP sein, ich bin ja auch noch da und kann es> bei mir einsetzten. Dein Vorschlag finde ich super, echt einfach und> geschickt ;-)
OK.
Wenn wir schon bei Code-Aufräumarbeiten sind.
vergleiche mal die beiden Funktionen
void floatToRawByteArray(float data, uint8_t buffpos, uint8_t buff[])
float rawByteArrayToFloat(uint8_t data[], uint8_t offset)
fällt dir dabei was auf?
Betrachte die Interfaces.
In der ersten Funktion ist die Reihenfolge
zuerst den Offset und dann der Buffer
in der zweiten Funktion ist es genau umgekehrt.
(Wenn wir jetzt mal davon abehen, dass die eine Funktion ihr
Ergebnis per Returnwert liefert während die andere die
Ausgabe über einen Parameter abliefert)
Sowas ist zwar kein Beinbruch, aber in einem ordentlichen
Interface ordnet man die Argumente in der logischen Reihenfolge
immer gleich an. Das spart Nachdenken, Nachsehen welche
Reihenfolge richtig ist und in weiterer Folge spart das auch
so manchen logischen Fehler.
da ich union nie benutzt habe, weiß ich nicht recht was es genau macht.
Ist es richtig wenn ich sage, dass union die Typumwandlung erzeugt.
float-Wert wird sofort in char umgewandelt (und umgekerht) und bekommt
es auch als Wert zugewissen. Und sobald sich irgendwo etwas ändert,
aktuallisiert union den Rest?!?!
>> da ich union nie benutzt habe, weiß ich nicht recht was es genau macht.> Ist es richtig wenn ich sage, dass union die Typumwandlung erzeugt.
Jein
> float-Wert wird sofort in char umgewandelt (und umgekerht) und bekommt> es auch als Wert zugewissen.
Da wird nicht gewandelt.
In einer union belegen die Member denselben Speicherbereich.
Im Grunde wird derselbe Speicher einfach nur auf 2 verschiedene
Arten genutzt. Stelle es dir so vor, dass beide Variablen
übereinander liegen.
PS: Eine derartige Verwendung einer union ist eigentlich laut
C-Standard verboten. Zumindest ist nicht garantiert, dass das
so klappt. In der Praxis ist aber kein Compiler bekannt, bei dem
das nicht klappen würde.
Hallo.
Da ich zufälligerweise auch gerade nach sowas gesucht habe war ich sehr
froh als ich auf diesen Tread gestoßen bin und wollt den Code gleich in
ein projekt integrieren.
1
#include<avr/io.h>
2
#include<stdint.h>
3
4
typedefunion
5
{
6
floatvalue;
7
charraw[sizeof(float)];
8
}float_to_raw;
9
10
voidftor(floatdata,charraw_buff[])//FLOAT TO RAW
11
{
12
float_to_rawufloat;
13
ufloat.value=data;
14
raw_buff[0]=ufloat.raw[0];
15
raw_buff[1]=ufloat.raw[1];
16
raw_buff[2]=ufloat.raw[2];
17
raw_buff[3]=ufloat.raw[3];
18
}
19
20
floatrtof(charraw_buffer[])//RAW TO FLOAT
21
{
22
float_to_rawufloat;
23
ufloat.raw[0]=raw_buffer[0];
24
ufloat.raw[1]=raw_buffer[1];
25
ufloat.raw[2]=raw_buffer[2];
26
ufloat.raw[3]=raw_buffer[3];
27
28
returnufloat.value;
29
}
30
31
intmain()
32
{
33
charbuffer[4];
34
35
floatf=13.7603;
36
floatg=0;
37
38
ftor(f,buffer);
39
g=rtof(buffer);
40
41
while(1)
42
{
43
asmvolatile("nop");
44
}
45
46
return0;
47
}
Funktioniert auch gut. Aber...
Ich brauche dafür 452 Byte Memory. Kann das sein???
oder habe ich oben irgendwo einen Fehler eingebaut???
mfg Christian Paier
Christian Paier wrote:
> Ich brauche dafür 452 Byte Memory. Kann das sein???
Optimierung eingeschaltet?
Ansonsten: könnte ich mir schon vorstellen, das das real ist.
Mit etwas Pech wurde durch die Verwendung von float die komplette
Floating Point Library ins Programm mit reingezogen.
-0s
Inzwischen wollte ich die Konvertierung auch in einem Anderen programm
nutzen, aber da braucht es sagenhafte 1,8KB was die Kapazitäten meines
Tiny25 zusammen mit den anderen 700Byte Code sprengt.
Gäbe es irgendeine Möglichkeit das kleiner zu implementieren?
Warum wird der Float denn als solcher definiert, wenn keine Berechnungen
stattfinden!
Kann man nicht einfach einen eigenen Typ definieren mit 4 Bytes Grösse
oder einfach einen int64 nehmen.
Sowas wie:
typedef myfloat
{ char f[4]; }
Ja das würde schon funktionieren.
Leider ist man hin und wieder leider doch auf berechnungen angewiesen,
und so auch im oben erwähnten Tiny - Programm:
1
...
2
floatstromwert=(read_adc()-512)/23.1424;
3
ftor(stromwert,Buffer);
4
USI_TWI_Slave_WriteBytes(Buffer,4);
5
...
wenn ich ftor(stromwert,Buffer); auskommentier habe ich dan wie gesagt
1,8KB Code Weniger.
Hallo,
versuche es doch mal mit:
union {
float *f32;
char *c;
} stromwert;
float *stromwert.f32=(read_adc()-512)/23.1424;
//ftor(stromwert,Buffer);
USI_TWI_Slave_WriteBytes(stromwert.c,4);
beiin der Zeile
float *stromwert.f32=(read_adc()-512)/23.1424;
kommt der Compiler nicht richtig zurecht.
wenn ich float weglasse funktioniert es, wenn man davon absieht das der
Code immer noch riesig ist.
Ich hab das Projekt mal in den Anhang gehängt.
obiger Auszug aus der .map-Datei zeigt meiner Meinung nach, dass alles
aus der Floatverarbeitung kommt. Von 02c2 bis 082e sind einige Module
mit _sf im Namen aus libgcc eingebaut.
Das sind ca. 6*256 also ca 1500 Bytes.
Mit einem 32Bit Signed Integer und 10Bit ADC mit 0 bei 512:
Messwert(i32) = (ADC-512)*2831858
bekommt man ein Ergebnis das wie folgt zu interpretieren ist:
Stromwert = Messwert / (1000 * 65536)
Wenn man also die oberen 16 Bit des Messwerts nimmt, hat man den Strom *
1000, also den Strom mit (+/-32.767) 3 Nachkommastellen.
Also einfach den oberen 16Bit Wert nach dezimal wandeln und das Komma
vor die Hunderterstelle.
Christian Paier wrote:
> Ja das würde schon funktionieren.>> Leider ist man hin und wieder leider doch auf berechnungen angewiesen,> und so auch im oben erwähnten Tiny - Programm:>>
1
>...
2
>floatstromwert=(read_adc()-512)/23.1424;
3
>ftor(stromwert,Buffer);
4
>USI_TWI_Slave_WriteBytes(Buffer,4);
5
>...
6
>
>> wenn ich ftor(stromwert,Buffer); auskommentier habe ich dan wie gesagt> 1,8KB Code Weniger.
Da würde ich doch glatt mal darauf wetten, dass dein schlauer
Compiler bemerkt, dass ohne diesen Aufruf der Umwandlungsfunktion
mit der Variablen stromwert nichts gemacht wird. Folgerichtig
schliesst er dann messerscharf, dass eigentlich niemand eine
Berechnung benötigt, wenn mit dem Ergebnis sowieso nichts gemacht
wird und man die Berechnung als Ganzes dann auch rauswerfen könnte.
Ist die Berechnung nicht mehr vorhanden braucht auch niemand mehr
die Floating Point Library und so werden 1.8Kb weniger verbrutzelt.
Dein Problem ist also nicht die Umwandlungsfunktion, sondern
die floating Point Berechnung da im Code.
Aber, du kannst es auch mal ohne die Umwandlungsfunktion versuchen
1
...
2
floatstromwert=(read_adc()-512)/23.1424;
3
USI_TWI_Slave_WriteBytes((char*)stromwert,4);
4
...
Ich glaube aber, das das dein Speicherproblem nicht lösen wird.
So da bin ich wieder, war die die letzten beiden Tage nicht daheim.
Ertmals danke für die vielen Antworten.
Ich hätt nie gedacht des es so schwer ist einem Tiny floats
einzutrichtern.
Ja kbuchegg du hast recht, es würde so auch gehen löst das
Speicherproblem aber nicht. Nichts desto trotz habe ich im Laufe des
Threads jede Menge über floats von euch gelernt, dafür sage ich nochmal
Danke @ all.
Ich habs jetzt so implementiert wie es mir der Gast (3 Beiträge weiter
oben) empfohlen hat. Danke @ Gast
Aber eine letze Frage hät ich da noch da ich diesen Trick auch in
Zukunft noch brachen werde: Wie ist Gast auf den Wert 2831858 gekommen??