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
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.
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
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));
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
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?
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
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.
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:
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
}
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!
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.
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.
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.
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.
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.
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.
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
>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.
>>>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