Forum: Mikrocontroller und Digitale Elektronik Float als 4 Byte im EEprom speichern


von Dirk F (Gast)


Lesenswert?

Hallo zusammen,
stehe hier jetzt vor einem Problem.
Ich programmiere in C, verwende zur kalibrierung des ADC eine Float Zahl 
32 Bit breit.
Wie kann ich diese Zahl als 4 Bytes zerlegen, um sie dann im EEprom zu 
speichern.
Vermule mal, mit indirekter Adressierung oder so.....
Bitte Hilfe.
LG Dirk

von Helmut L. (helmi1)


Lesenswert?

Dirk F schrieb:
> Hallo zusammen,
> stehe hier jetzt vor einem Problem.
> Ich programmiere in C, verwende zur kalibrierung des ADC eine Float Zahl
> 32 Bit breit.
> Wie kann ich diese Zahl als 4 Bytes zerlegen, um sie dann im EEprom zu
> speichern.
> Vermule mal, mit indirekter Adressierung oder so.....
> Bitte Hilfe.
> LG Dirk

Mit einer Union kannst du das machen.

von Peter II (Gast)


Lesenswert?

Dirk F schrieb:
> Wie kann ich diese Zahl als 4 Bytes zerlegen, um sie dann im EEprom zu
> speichern.

warum willst du es erst zerlegen, kann kann auch mehre byte auf einmal 
speicher?

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Block_lesen.2Fschreiben

Die andere Frage ist ob ein float überhaupt sinnvoll ist. Auch aus einem 
ADC kommt kein float raus.

von Friedrich J. (franjuja)


Lesenswert?

Hallo Peter II,

>warum willst du es erst zerlegen, kann kann auch mehre byte auf einmal
speicher?

Die I2C Interfaces die ich kenne wollen die übertragenen Daten 
byteweise. Auch die Libfunktionen die ich kenne wollen das so. Die Frage 
ist also nachvollziehbar. Auch die Tatsache dass ein 32 float 
abgespeichert werden soll.

Gut, wie wäre es möglich. Union über float und uint8_t[4]. Danach kannst 
Du die Bytes einzeln adressieren. Über "union" belesen.

Andere Möglichkeit: Die float in einer Schleife mit vier Durchläufen 
jeweils um 8 bit nach rechts shiften und zerlegen, verunden, casten, 
eepromroutine aufrufen.

Grüße

von Peter II (Gast)


Lesenswert?

Friedrich Janus schrieb:
> Die I2C Interfaces die ich kenne wollen die übertragenen Daten
> byteweise. Auch die Libfunktionen die ich kenne wollen das so. Die Frage
> ist also nachvollziehbar
ich gehe davon aus das er es intern speicher will, also nichts mit i2c.

float eeFooFloat EEMEM;

float  f;

eeprom_write_block (eeFooFloat ,&f, sizeof(f));

von Klaus W. (mfgkw)


Lesenswert?


von Dirk F (Gast)


Lesenswert?

Hallo,
danke für die Tips.
Mit Unions kenne ich mich leider nicht aus.

Alsi die Float Zahl wird doch als 4 Bytes im Speicher der MC gehalten.
Wie komme ich denn einfach an diese 4 Bytes einzeln ran, um die dann ins 
EEprom zu schreiben.
Mit der indirekten Adtessierung kann man doch einen Pointer auf das 
erste Byte erzeugen, dann aufs zweite u.s.w.

Kann mir bitte jemand kurz ein Beispiel in C hier schreiben.

Danke

von Peter II (Gast)


Lesenswert?

Dirk F schrieb:
> Wie komme ich denn einfach an diese 4 Bytes einzeln ran, um die dann ins
> EEprom zu schreiben.
du musst da nicht rankommen, es gibt fertige funktionen zum speicher 
eines floats.

ich habe schon ein beispiel hingeschrieben und Klaus Wachtler hat noch 
den link auf die fertige funktion - was brauchst du noch?

von Dirk F (Gast)


Lesenswert?

Hallo, sorry habe vergessen zu sagen, dass ich auf einem PIc18 mit 
HI-TECH C Compiler arbeite.
Also fertige AVR Rotinen nützen mir leider nicht, ich brauche reinen 
C-Code.
LG  DIrk

von Helmut L. (helmi1)


Lesenswert?

typedef union {
float f;
unsigned char b[4];
} FB;


FB fb;

fb.f = 1234.0;   float rein

b1 = b[0];    byte raus

usw.

von Rainer S. (rsonline)


Lesenswert?

Muss es nicht

b[3];

heißen?

von Peter II (Gast)


Lesenswert?

Rainer S. schrieb:
> Muss es nicht
> b[3];
> heißen?
wenn dein float aus 3 byte besteht ja, sonst nicht.

von Helmut L. (helmi1)


Lesenswert?

Die 4 Byte:

fb.b[0]
fb.b[1]
fb.b[2]
fb.b[3]

von Dirk (Gast)


Lesenswert?

Super,
danke für die Hilfe. Werde es gleich nach dem Kaffee mal ausprobieren.

von Karl H. (kbuchegg)


Lesenswert?

Dirk schrieb:
> Super,
> danke für die Hilfe. Werde es gleich nach dem Kaffee mal ausprobieren.

Und gleich danach kaufst du dir ein C-Buch oder fängst zumindest an, das 
hier
http://openbook.galileocomputing.de/c_von_a_bis_z/
durchzuarbeiten.

Das
> Mit Unions kenne ich mich leider nicht aus.
> Muss es nicht b[3]; heißen?
sind deutliche Indizien dass du keines hast aber dringend eines brauchen 
würdest. Es gibt noch zig-tausend andere Kleinigkeiten ohne die du nicht 
verünftig programmieren kannst, die alle in den Büchern stehen und an 
denen du ohne Literatur verzweifeln wirst.

von Rolf M. (rmagnus)


Lesenswert?

Helmut Lenzen schrieb:
> typedef union {
> float f;
> unsigned char b[4];
> } FB;
>
>
> FB fb;
>
> fb.f = 1234.0;   float rein
>
> b1 = b[0];    byte raus

Man kann sich allerdings auch den ganzen Umstand mit Definition eines 
eigenen Datentypen und umkopieren des Float sparen:
1
float f; // meine Variable
2
3
unsigned char* b = (unsigned char*)&b;
4
5
b1 = b[0];
6
.
7
.
8
.

von Dirk (Gast)


Lesenswert?

Hi zusammen, ja, ein C-Buch habe ich schon, habe mich auch eben mal in 
die Union eingelesen.
Das Programm läuft jetzt.
Gruß Dirk


//********************EEwriteD Float 32 *********
void EEwriteD(unsigned int adr, double dat) /* write a Double Float of 
data to EEPROM */
{
union {
float f;
unsigned char b[4];
} test ;

test.f = dat;  //  float rein

 EEwrite (adr+0,test.b[0]);    // 1. Byte
 EEwrite (adr+1,test.b[1]);    // 2. Byte
 EEwrite (adr+2,test.b[2]);    // 3. Byte
 EEwrite (adr+3,test.b[3]);    // 4. Byte
}

von Karl H. (kbuchegg)


Lesenswert?

Dirk schrieb:
> Hi zusammen, ja, ein C-Buch habe ich schon,

Arbeite es durch!
Das ist wichtig, dass du dein Werkzeug (die Programmiersprache) auch 
kennst!

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Das bezweifle ich, dass das jetzt richtig geht.

lese mal über Unterschiede zwischen double und float und werde Dir 
darüber klar dass es bei einem Typecast einen Genauikeitsverlust gibt.

Dennoch empfehle ich ausschließlich "long double" zu verwenden, damit 
Dein Programm erst recht langsam wird.

von Peter II (Gast)


Lesenswert?

Markus Müller schrieb:
> lese mal über Unterschiede zwischen double und float und werde Dir
> darüber klar dass es bei einem Typecast einen Genauikeitsverlust gibt.

bei einem atmel sind beide gleich, und es gibt doch auch keinen 
Datenverlust. Und bei dem pics scheint es auch so zu sein.

von (prx) A. K. (prx)


Lesenswert?

Markus Müller schrieb:
> lese mal über Unterschiede zwischen double und float und werde Dir
> darüber klar dass es bei einem Typecast einen Genauikeitsverlust gibt.

Wenn man davon absieht, dass Hi-Tech für PIC18 in der 
Standardeinstellung keinen Unterschied zwischen float und double macht, 
und beide sowieso nur 24 Bits gross sind. Man kann wahlweise auch 32 
Bits kriegen, aber das wars dann auch.

von (prx) A. K. (prx)


Lesenswert?

Dirk F schrieb:
> Vermule mal, mit indirekter Adressierung oder so.....

Kann man:
  uin8t_t *p = (uint8_t *)&zahl;
und dann p[0], p[1], ... p[sizeof(zahl)-1] verwenden.

Unions sind ein Weg, das ist ein anderer.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Ach ja, ein Kastrierter float, auch noch deklariert als double.

Dennoch programmiert man so nicht, wenn man den Code auf einen größeren 
Prozi portiert gibt es auf einmal Probleme.

von (prx) A. K. (prx)


Lesenswert?

Keine Frage. Wenn man nicht grad mit 24-bit float und 32-bit double 
arbeitet, dann ist schon die blosse Verwendung des double Typs 
eigentlich Selbstverarschung. Bei AVRs ja auch, es suggeriert mehr als 
tatsächlich drin ist. Bei float sieht man das wenigstens.

von Dirk F (Gast)


Lesenswert?

Hallo,
also ich habe die Kalibrierung des 24 Bit Wertes vom ADC mit Float (24 
Bit) und mit Double (32 Bit)  verglichen.
Bei Double kan man feiner kalibrieren.
Meinen Hi-Tech C18 habe ich auf 32 Bit beim Typ Double eingestellt.

Der 23 Bit Wert + Vorzeichen (18 Bit rauschfrei) vom ADC entspricht 
einer Spannung von 0...5 V.
Hatte vorhrt mit LONG (INT 32 Bit) gearbeitet, war aber zu ungenau.

Danke für die gute Hilfe, ist schon ne feine Sache so ein Forum....
LG Dirk

von Nocheiner (Gast)


Lesenswert?

>Der 23 Bit Wert + Vorzeichen (18 Bit rauschfrei) vom ADC entspricht
einer Spannung von 0...5 V. Hatte vorhrt mit LONG (INT 32 Bit) 
gearbeitet, war aber zu ungenau.

Na dann viel Glueck. Denn Longint mit 32bit hat 9 signifikante Stellen. 
Float mit 32bit hat nur 6 signifikante Stellen. Etwas anderes waere 
double mit 64bit. Das hat 15 signifikante Stellen.

von (prx) A. K. (prx)


Lesenswert?

Nocheiner schrieb:
> double mit 64bit. Das hat 15 signifikante Stellen.

Hätte es, wenn es das gäbe.

von Dirk F (Gast)


Lesenswert?

>>>Na dann viel Glueck. Denn Longint mit 32bit hat 9 signifikante Stellen.
>>>Float mit 32bit hat nur 6 signifikante Stellen. Etwas anderes waere
>>>double mit 64bit. Das hat 15 signifikante Stellen.

Das Problem bei Longint 32 Bit ist, dass ich bei der Multiplikation des 
18 Bit Messwertes mit dem Skalierungsfaktor als LONGINT mit dem Ergebnis 
schnell an die 32 Bit Grenze stoße. 64 Bit INT kann mein Compiler nicht.

Deshalb  der Weg:
Messwet 18 Bit mit Faktor x als double skalieren und dann wieder in 
longint32 zurückwandeln.

ALs Ergebnis kann ich bei einem Messbereich von 5 V  6 Nachkommastellen 
darstellen, das reicht.

Gruß Dirk

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

ne 32b*32b MUL kann man sich auch selber schreiben, hier im Forum gabs 
dazu  was bei denen die DDS ICs ansteuern.

von Friedrich J. (franjuja)


Lesenswert?

Hallo PeterII,

>ich gehe davon aus das er es intern speicher will, also nichts mit i2c.

OOOps, der Fehler lag zwischen den Ohren.

Grüße

von Dirk F (Gast)


Lesenswert?

Ja stimmt, ich nutze das interne EEPROM des PIC18F4620.
Läuft jetzt alles bestens !
Gruß Dirk

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.