www.mikrocontroller.net

Forum: Analoge Elektronik und Schaltungstechnik Datenverlust im Eeprom ohne Versorgungsspannung


Autor: Matthias (Gast)
Datum:

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

Autor: Andreas Schwarz (Gast)
Datum:

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

Autor: Peter Dannegger (peda)
Datum:

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

Autor: Michael (Gast)
Datum:

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

Autor: Matthias (Gast)
Datum:

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

Autor: Marcus Maul (Gast)
Datum:

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

Autor: Matthias (Gast)
Datum:

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

Autor: C3PO (Gast)
Datum:

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

Autor: Marcus Maul (Gast)
Datum:

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

Autor: Matthias (Gast)
Datum:

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

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.