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
Poste doch mal deinen Programmcode; dass das EEPROM wirklich Daten verliert kann ich mir nicht vorstellen.
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
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
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
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
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
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 ???
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.