Forum: Mikrocontroller und Digitale Elektronik Problem mit EEPROM Attiny2313


von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

Hallo,

eigentlich glaubte ich, inzwischen Mikrocontroller-Datenblätter lesen zu 
können. Diesmal brauche ich aber etwas Hilfe:

Ich möchte "einfach" Werte ins EEPROM eines Attiny2313 schreiben und sie 
daraus lesen.
Leider scheint das Schreiben jedoch schon schiefzugehen, da ich stets 
0xFF auslese, egal was ich vorher hineingeschrieben habe.

Die Schreibfunktion habe ich gemäß Datenblatt erstellt:
1
void EEPROM_write(unsigned int addr, unsigned char data){
2
  /* Wait for completion of previous write */
3
  while(EECR & (1<<EEPE));
4
  /* Set up address and data registers */
5
  EEAR = addr;
6
  EEDR = data;
7
  /* Write logical one to EEMPE */
8
  EECR |= (1<<EEMPE);
9
  /* Start eeprom write by setting EEPE */
10
  EECR |= (1<<EEPE);
11
  while(EECR & (1<<EEPE));
12
  return;
13
}

Der Controller läuft mit 8MHz Int. RC-Oszillator.

Das Merkwürdige daran: Selbst im "AVR-Simulator" tritt der gleiche 
Effekt auf. Es scheint, als würde EEPE niemals gesetzt werden (und damit 
nie der Wert ins EEPROM geschrieben).

Kann mir jemand sagen, wo der Fehler ist?

Über Antworten würde ich mich sehr freuen!

Schöne Grüße,
Alex

von Ace (Gast)


Lesenswert?

Hallo Alex,

dein Problem liegt darin dass die Compiler (-o0 -o1 usw. siehe 
Optimization)  die Beschreibung von EECR nicht optimal hingekommt 
spricht innerhalb von 4 Zyklen. Schau dir eventuell die ASM Befehle an.


void EEPROM_write(unsigned int addr, unsigned char data){
  /* Wait for completion of previous write */
  while(EECR & (1<<EEPE));
  /* Set up address and data registers */
  EEAR = addr;
  EEDR = data;
  /* Write logical one to EEMPE */

  cli(); /* disable interrupt */
  /* zeitkritisch muss innerhalb 4 Zyklen ausgeführt sein */
  asm ("sbi 0x1c,2");
  asm ("sbi 0x1c,1");
  sei(); /* enable interrupt */

  /* EECR |= (1<<EEMPE); */
  /* Start eeprom write by setting EEPE */
  /* EECR |= (1<<EEPE); */
  while(EECR & (1<<EEPE));
  return;
}

Grüße Ace

von Faule Socke (Gast)


Lesenswert?

Du kannst auch einfach die fertigen EEPROM-Routinen nehmen, die mit der 
AVR-Libc (und damit mit dem WinAVR, den du vermutlich benutzt) 
mitgekommen sind:

http://www.nongnu.org/avr-libc/user-manual/group__avr__eeprom.html

fix und fertig, getestet, funktionieren.

Allein das "Löschen ohne nachfolgendes Schreiben" fehlt leider.

von Michael R. (dj_motionx)


Angehängte Dateien:

Lesenswert?

Hallo das Problem hatte ich auch schon.
Du kannst auch einfach die routinen der avr lib verwenden.

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

Vielen Dank euch dreien. Ihr beschreibt ja alle den gleichen Fehler, den 
ich auch vermutete. Jedoch dachte ich, wenn ich die beiden Befehle im 
C-Code direkt nacheinander schreibe, würden sie innerhalb von 4 Zyklen 
ausgeführt werden...
Ich werde es morgen mal testen und berichten.

Danke & Gruß,
Alex

von Alex B. (Firma: Ucore Fotografie www.ucore.de) (alex22) Benutzerseite


Lesenswert?

So, vielen Dank für die Antworten!
Es lag wirklich am Timing, EEPE wurd nicht schnell genug gesetzt, 
nachdem EEMPE gesetzt wurde... Habe es jetzt in Assembler geschrieben 
und es klappt perfekt.

Gruß,
Alex

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.