Floatwerte in EEPROM abspeichern

Gast #151914
Lesenswert?

Ich versuche schon länger einen Weg zu finden, einen Floatwert z.B.
-12.4 in einen normalem EEPROM abzuspeichern. Das Auslesen aus dem
EEPROM sollte auch gehen, um wieder eine Floatzahl daraus zu machen.
Wie macht man das am schlausten? Vielen Dank für die Unterstützung im
Voraus.
Gast #151915
Lesenswert?

Eine floatzahl ist nichts weiter als mehrere Bytes. Du musst also nur
herausfinden, wie mehrere Bytes ins EEPROM zu schreiben sind bzw.
daraus gelesen werden sollen.
Du könntest Dich beispielsweise daran orientieren, wie Strings im
EEPROM abgespeichert werden können, das sind ja auch nichts anderes als
mehrere Bytes. Und bei floatzahlen ist's sogar noch einfacher, da die
Anzahl der Bytes bekannt ist, während sie bei Strings von deren Länge
abhängt.

Der Operator sizeof() liefert die Anzahl der Bytes, die eine Variable
groß ist; bei float ist das in der Regel 4.

Vielleicht ist ja der eine oder andere Anhaltspunkt dabei.
Gast #151916
Lesenswert?

Kleines Beispiel in C:
unsigned char i,j;
float wert;
unsigned int adresse;

//lesen
for(i=0;i<sizeof(wert);i++)
{
  eeprom_lesen(adresse,k);
  adresse ++;
  if (i<sizeof(wert)-1)
  {
     wert = k;
     wert = wert << 1;
  }
  wert = k;
}

//schreiben

for(i=0;i<sizeof(wert);i++)
{
  eeprom_schreiben(adresse,(unsigned char)wert);
  adresse++;
  wert = wert >> 1;
}

ungetestet, schnell hingetippt

MW
Gast #151918
Lesenswert?

O nein. Das kann so nicht gehen.

Was soll wohl das Ergebnis von

  wert = wert << 1;

oder

  wert = wert >> 1;

sein? Außerdem überschreibt Deine Leseroutine bei jedem
Schleifendurchlauf wert mit dem letzten gelesenen Byte.


Ich würd's so machen:

  unsigned char i;
  float wert;
  unsigned char* pwert;
  unsigned int adresse;


  //lesen
  pwert = (unsigned char *) &wert;

  for (i = 0; i < sizeof(wert); i++)
  {
    eeprom_lesen(adresse, k);
    adresse++;
    *pwert = k;
    pwert++;
  }

  //schreiben
  pwert = (unsigned char *) &wert;

  for (i = 0; i < sizeof(wert); i++)
  {
    eeprom_schreiben(adresse, *pwert);
    adresse++;
    pwert++;
  }
Gast #151920
Lesenswert?

Warum so kompliziert? avr-libc hat doch schon alles an Board:

  float my_float, my_erg;

  my_float = -12.4;
  eeprom_write_block(&my_float, (void*) 20, sizeof(my_float));
  my_float = 0;
  eeprom_read_block (&my_float, (void*) 20, sizeof(my_float));

  my_erg = my_float;

Den EEPROM-Ptr habe ich kurz quick&dirty gecastet, sorry dafür.

Stefan
Gast #151921
Lesenswert?

@Stefan:
Ich kenne und verwende avr-libc nicht, mir ging es um die Darstellung
des Prinzips.

@Michael:
Das verbessert nichts. Was meinst Du denn, was dabei 'rauskommt, wenn
Du einen float - Wert shiftest?
Gast #151922
Lesenswert?

(Nachtrag:)

Mal kurz den folgenden Code einem anderen* C-Compiler zum Fraß
vorgeworfen:

  float bla;
  float fusel;

  bla = 12.34;
  fusel = bla >> 8;

Die Antwort des Compilers ist unmissverständlich:

  test.c(25) : error C2296: '>>' : illegal, left operand has type
'float'
  test.c(25) : error C2297: '>>' : illegal, right operand has type
'float'

Tja, das ist wohl undefiniert.


*) mangels momentaner Verfügbarkeit eines anderen war's MSVC++ 6.0
Gast #151923
Lesenswert?

Hi

Stimmt. Die << >> Operatoren sind für floating point Zahlen
genausowenig erlaubt wie der % Operator.

Aber den M$ VC++ Compiler (für C++) in Version 6 sollte man nicht
unbedingt als Referenz verwenden. Der ist an einigen Stellen etwas,
naja, kaputt. Der 7er soll da deutlich besser sein. Das weiß ich
allerdings nur aus zweiter Hand.

Matthias
Gast #151924
Lesenswert?

@Rufus:
stimmt, Dein Code ist vom Lerneffekt sicher besser.

Die EEPROM-Blockbefehle haben allerdings den Vorteil, dass i.d.R. das
EEPROM nur einmal beschrieben werden muss (solange die Daten innerhalb
einer EEPROM-Page liegen).

Stefan
Gast #151925
Lesenswert?

@Matthias:

VC++ 6 ist kein sonderlich standardkonformer C++-Compiler, das mag
stimmen. Aber als C-Compiler hält er sich an C90 (ANSI-C).

Meinen Test habe ich unter anderem deshalb mit C und nicht C++
angestellt (letzteres kann ja >> und << auch überladen, was wiederum
ganz spannende Resultate liefern kann).

@Stefan:

D'accord. Nachdem man ein Prinzip verstanden hat, ist es sinnvoll und
angebracht, Vereinfachungen zu verwenden.

(Bist Du Dir mit den EEPROM-Schreibvorgängen absolut sicher? Das kann
doch byteweise ohne Berücksichtigung irgendwelcher Pages beschrieben
werden; so etwas wie Pages ist doch IMHO nur beim Beschreiben von
Flash-ROMs zu berücksichtigen. Irre ich mich?)
Gast #151926
Lesenswert?

@Rufus:
>(Bist Du Dir mit den EEPROM-Schreibvorgängen absolut sicher? Das kann
>doch byteweise ohne Berücksichtigung irgendwelcher Pages beschrieben
>werden; so etwas wie Pages ist doch IMHO nur beim Beschreiben von
>Flash-ROMs zu berücksichtigen. Irre ich mich?)

Ganz sicher bin ich mir nie - ich bin Programmierer und kein
Leichenbestatter ;-)

Das EEPROM kann man entweder byteweise beschreiben oder gleich eine
ganze Page (= 4 Bytes) füllen und dann "am Stück" programmieren. Da
ein Schreibzyklus ca. 8,5ms dauert (unabhängig, ob nur ein oder alle 4
Bytes der Page beschrieben werden), kann dies schon ein erheblicher
Zeitvorteil sein.

Allerdings: ich habe das gerade mal verifiziert und bin bei beiden
Möglichkeiten auf dieselbe Zeit gekommen - ca. 8s für 200
Schreibzyklen. Dann habe ich mir mal den Source von eeprom_write_block
angeschaut: dort werden alle Bytes einzeln programmiert, die
Page-Option wird nicht verwendet.

Viele Grüße, Stefan
Gast #151927
Lesenswert?

Ich muss die Sache mit den Pages zurücknehmen:

Die page-weise EEPROM-Programmierung scheint nur einem externen
Programmer vorbehalten zu sein. Über im Microcontroller zugängliche
Register hat man dagegen keinen (dokumentierten) Zugriff auf die
Page-Programmierung.

Ich habe übersehen, dass sich das Kapitel "Memory Programming"
ausschliesslich auf den externen Zugriff bezieht.

Viele Grüße, Stefan

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren