Forum: Compiler & IDEs float im EEPROM


von Florian (Gast)


Lesenswert?

Ich will ein float im EEPROM ablegen und auslesen. Klappt eigentlich 
auch. Aber ich will feststellen, ob da schon ein Wert abgelegt wurde, 
oder nicht (neuer Chip) und dann einen Standardwert nehmen. Das klappt 
nicht. µC: ATmega32

Ich habe:

float epromwert EEPROM;
float wert=0;
...
eeprom_read_block(&wert, &epromwert, sizeof(float));

Wenn ich wert mit

dtostrf (wert, 6, 3, text);

konvertiere, bekomme ich bei einem leeren EEPROM (FF) "NAN". Ok, so weit 
ja auch brauchbar. Jetzt dachte ich, ich prüfe mit

isnan (wert)

ob das Ergebnis aus dem EEPROM auslesen eine Zahl ist. Aber die Fkt. 
liefert immer 0
:-(

Wie mache ich's denn richtig?

von Hermann-Josef (Gast)


Lesenswert?

Hallo Florian,

eine interessante Fragestellung. Die beiden Funktionen in der avr-libc 
(Version 1.4.4) haben eine unterschiedliche "Meinung" darüber was ein 
NaN ist, ich denke, die richtige Definition müßte sich in IEEE-754 
finden, bei Interesse danach 'googeln' oder auch mal bei 
http://en.wikipedia.org/wiki/NaN vorbeischauen).

bei isnan() findet sich:
  CPI  r25, 0xFF  ; NaN is 0xffc0XXXX
  BRNE  .Lfalse
  CPI  r24, 0xC0
  BRNE  .Lfalse

bei dstrtof():
  cpi  r17, 0xff  ; NAN ?
  brne  1f

Es ist nicht auszuschliessen, dass avr-libc das noch nicht 100 %-ig 
implementiert (siehe auch 
https://savannah.nongnu.org/bugs/?group=avr-libc&func=browse&set=open , 
hier Item # 13330), ich würde das daher in der gegenwärtigen Situation 
'schmutzig' lösen und auf 0xffff (bzw. 2 Worte mit 0xffff) abprüfen. 
Wenn (float)0xfffffffff eine gültige Float-Zahl ist, dann hat man 
natürlich ein Problem... ich hab' gerade kein AVR-System hier, was käme 
denn da raus ?

Ciao
 Hermann-Josef

von Florian (Gast)


Lesenswert?

Ah. Dann kann man sich ja totsuchen. Nachzuschauen, wie die Funktionen 
implementiert sind, käme mir nie in den Sinn. Ich gehe (blauäigig, wie 
ich wohl zugeben muß) davon aus, daß die Dinge so funktionieren, wie sie 
sollen.
Ich hatte es noch etwas dreckiger gemacht und in einen String gewandelt 
und dann mit strcmp auf "NAN" geprüft.

Aber der Test auf FF geht auch (in meinem Fall).

for (i=0; i<=6; i+=2)
{
  if (eeprom_read_word((uint16_t *)(&wert+i)) != 0xFFFF)
    is_number = 1;
}

Was mich jetzt nur noch stutzig macht, ist das ein double lediglich 4 
Bytes belegt, wie auch ein float.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, davon abgesehen, dass das gesamte Handling der IEEE754-
Sonderfeatures (Inf, NaN, Denormals) in der bestehenden
Implementierung unterbelichtet ist, ist es aber auch recht
blauäugig anzunehmen, dass ein 0xffffffff automatisch eine
gültige NaN wäre.  Den Test auf nicht programmierten EEPROM
solltest du also sinnvollerweise schon explizit gegen 0xffffffff
vornehmen.

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

beim AVRGCC ist sizeof(double) == sizeof(float) Double ist (im Prinzip) 
nur eine typedef auf ein float.

Matthias

von Florian (Gast)


Lesenswert?

@ Jörg Wunsch
Ich ging ja nicht davon aus, daß das NaN ist, aber die Funktion isnan 
lieferte halt immer 0, das störte mich. Das die Implementierung nicht OK 
ist, kann man ja nicht unbdeingt wissen finde ich.

@Matthias Weißer
Aha. Wieder was gelernt (und vermutlich dann wieder vergessen, wenn ich 
es das nächste mal brauche :-( ) Ist halt doof, wenn man mehrere 
Sprachen kennt und immer wieder wechselt und dann Wissen transferieren 
will...

Danke.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Laut Quellcode betrachtet die Funktion isnan() das Bitmuster
0xFFC0xxxx als NaN.

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.