mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Floatwerte in EEPROM abspeichern


Autor: Johann (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beim lesen muß natürlich heißen wert = wert | k;

MW

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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++;
  }

Autor: Michael Wilhelm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich meinte auch <<8

MW

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?)

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan Kleinwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.