Forum: Analoge Elektronik und Schaltungstechnik Datenverlust im Eeprom ohne Versorgungsspannung


von Matthias (Gast)


Lesenswert?

Hallo!

Ich programmiere einen ATmega8L mit avr-gcc.
Periodisch werden Daten in das Eeprom geschrieben und über die Uart
ausgegeben.
Solange der Microcontroller an der Versorgungsspannung angeschlossen
ist, bleiben die Werte im Eeprom erhalten und werden auch korrekt
ausgegeben.
Wird er von der Spannung getrennt und wieder angeschlossen, sind alle
Werte weg (Wert 256 wird aus jeder Speicherzelle ausgelesen).
Die Fuse-Bits für Brown-out-detection sind gesetzte:
BODEN = 0 und BODLEVEL 0 oder 1, macht keinen Unterschied.
Alle 4 Möglichkeiten verhindern keinen Datenverlust.


Gruss,
Matthias

von Andreas Schwarz (Gast)


Lesenswert?

Poste doch mal deinen Programmcode; dass das EEPROM wirklich Daten
verliert kann ich mir nicht vorstellen.

von Peter D. (peda)


Lesenswert?

Manchmal kann es sein, daß ein Quarz nur sehr langsam anschwingt
(falsche Fusebits für den Frequenzbereich).

Auch muß man bei Quarz grundsätzlich die längste Resetzeit auswählen.

Der beste Brown-Out nützt nämlich nichts, wenn der Quarz erst aus den
Hufen kommt, wenn der Reset schon wieder vorbei ist.

Wenn das immer noch nichts hilft, dann mal testweise einen
Quarzoszillator anschließen oder den internen RC-Oszillator nehmen.


Peter

von Michael (Gast)


Lesenswert?

Das Problem gab es bei den Classik-Bausteinen sehr oft (bei mir war es
der 8515). Bei langsam ansteigenden oder abfallenden Betriebsspannungen
war der Mikrocontroller oft "längere" zeit in einem Spannungsbereich,
der ihm schon Funktionen abverlangte, aber recht eigenwillig. Wie mir
ein App-Ing von Atmel sagte, ist es schon drin, daß der Controller von
sich aus einen Schreibzyklus initiiert, am meisten betroffen war das
EEPRO-Bit 0x00. Sichere Abhilfe schafft ein externer Reset-Baustein, z.
B. Dallas DS1813-10 (für 5V Betriebsspannung). Eine RC-Kombination an
Reset und definieren auf Vcc hatten fehlerhafte Ergebnisse. Versuch es
mal so. Reset-bausteine gibt es wie Dand am meer. Viel Glück.
Michael

von Matthias (Gast)


Lesenswert?

Hi

das eine EEPROM-Zelle überschrieben ist durchaus wahrscheinlich. Das
aber immer_ _alle Zellen auf 0xFF gesetzt werden sollten halte ich
für äußerst unwahrscheinlich. Ich vermute einen Softwarefehler.

Matthias

von Marcus Maul (Gast)


Lesenswert?

Hallo Andreas,

poste mal bitte Deinen Code, da ich selber das Phänomen schonmal kennen
gelernt habe. Bei mir war es ein Array, das im Stack lag und nicht ins
Eprom geschrieben worden ist.
Alternativ schau mal mit einem ISP nach, was zur Laufzeit in dem Eprom
gestanden hat.


Gruß Marcus

von Matthias (Gast)


Lesenswert?

Hallo!

Vielen Dank schon mal für eure Tips.
Ich benutze den internen RC-Oszillator mit 4 Mhz.



Das Lesen und Schreiben mit dem Eeprom sieht folgendermassen aus:


// Variablendefinition
uint8_t    Temperatur = 0;
uint8_t    Temperatur_Ausgabe = 0;

.
.
.
// Wird beim Betätigen von Taster 1 gesartet.
INTERRUPT(SIG_INTERRUPT0)
  {
  // Externen Interrupt abschalten, damit später
        // geprüft  werden kann, ob der Taster nach zwei
        // Sekunden noch gedrückt ist.
  cbi(GICR,INT0);

  // maximale Temperatur aus Eeprom an Adresse 1 auslesen
  Temperatur_Ausgabe = eeprom_rb(0x01);

  // Anzeige über 7-Segment-Anzeige
  Hunderter = Temperatur_Ausgabe / 100;
  Zehner = (Temperatur_Ausgabe % 100) / 10;
  Einer = (Temperatur_Ausgabe % 100) % 10;
  ausgabe_einer(Einer);
  ausgabe_zehner(Zehner);
  ausgabe_hunderter(Hunderter);

  delay_sek(2);

  // Wenn er noch gedrückt ist, Wert im Eeprom löschen
  // und erfolgte Löschung durch "00" anzeigen.
  if bit_is_clear(PIND,PIND2)
    {
    eeprom_wb(0x01,0);
    Ziffer_3_0; Ziffer_2_0; Ziffer_1_aus;
    delay_ms(250);
    delay_ms(250);
    }

  // Die Variable Temperatur_max muss jetzt den                     //
gespeicherten Wert bekommen.
  Temperatur_max = eeprom_rb(0x01);

  // externen Interrupt wieder einschalten
  sbi(GICR,INT0);
  }




void main(void)
  {
  .
  .
  // Temperatur aus AD-Wandler einlesen und berechnen
  Temperatur = .........
  .
  .
  // Speichern des Wertes von Temperatur im Eeprom,
        // Adresse 1
  eeprom_wb(0x01,Temperatur);
  .
  .
  .
  }



Solange die Versorgungsspannung dran ist, wird beim Drücken vom Taster
immer die höchste bisher gemessene Temperatur ausgegeben.
Diese steht in Adresse 1 drin und wird der Variablen Temperatur_Ausgabe
zugewiesen. Diese Variable wird sonst nirgends verwendet. Demzufolge
müsste das Lesen und Schreiben in das Eeprom funktionieren.
Nach dem Abklemmen von der Spannungsversorgung ist der alte Wert aber
nicht mehr vorhanden.


Gruss,
Matthias

von C3PO (Gast)


Lesenswert?

lese doch einfach mal nach dem schreiben der EEPROM-Zelle den
reingeschriebenen Wert aus und vergleiche ihn mit dem
reinzuschreibenden Wert !!!

am besten direkt in der EEPROM_wb Funktion

vielleicht übergibst du ja 0xFF ???

von Marcus Maul (Gast)


Lesenswert?

Hallo Mathias,

wenn ich das jetzt nicht ganz falsch im Kopf habe, dann benutzt wird
nach dem das Eprom beschrieben worde ein Interrupt ausgelöst. Hast Du
den deaktiviert? Falls nicht, dann wird nur gelöscht, aber nichts
geschrieben. Löschen heißt in Eprom Sprache aber 0xff.
Zudem würde ich Dir dringend von einer sooooo langen Interrupt Routine
abraten, da ich aus eigenen Erfahrungen sagen kann, dass Du damit sehr
schnell unbeabsichtigete Zustände heraufbeschwörst.
Tritt während eines Interrupts ein höherer Interrupt ein, so wird der
abgearbeitet und u.U. nicht wieder korrekt in den letzten Interrupt
gesprungen sondern leider ab und zu zurück nach main.

Gruß Marcus

von Matthias (Gast)


Lesenswert?

Vielen Dank für eure Tips!

@Marcus:
Ist es dann besser, den Code des Interrupt in ein Unterprogramm zu
packen, das nach dem Aufruf des Interrupts abgearbeitet wird? Eher
nicht, der auszuführende Code während des Interrupts wird ja nicht
weniger?

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.