Forum: Mikrocontroller und Digitale Elektronik Floatwerte in EEPROM abspeichern


von Johann (Gast)


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.

von Rufus T. Firefly (Gast)


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.

von Michael Wilhelm (Gast)


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

von Michael Wilhelm (Gast)


Lesenswert?

Beim lesen muß natürlich heißen wert = wert | k;

MW

von Rufus T. Firefly (Gast)


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++;
  }

von Michael Wilhelm (Gast)


Lesenswert?

Ich meinte auch <<8

MW

von Stefan Kleinwort (Gast)


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

von Rufus T. Firefly (Gast)


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?

von Rufus T. Firefly (Gast)


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

von Matthias (Gast)


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

von Stefan Kleinwort (Gast)


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

von Rufus T. Firefly (Gast)


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?)

von Stefan Kleinwort (Gast)


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

von Stefan Kleinwort (Gast)


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

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.