Archiv verlassen und diese Seite im Standarddesign anzeigen : Brauche einen Tipp bzgl. EEPROM_write() und EEPROM_read()
Moin!
Ich habe folgendes Problem: Wenn ich mit EEPROM_write() Charakters speichere und sie dann wieder einlesen möchte, dann kommt immer nur 0xff zurück. Dabei habe ich mich (meiner Meinung nach) an das Datenblatt des Tiny2313 gehalten. Diesem habe ich nämlich die beiden benutzten Funktionen entnommen.
unsigned char cTest[2];
//
EEPROM_write(0,'A');
EEPROM_write(1,'B');
EEPROM_write(2,'C');
myWait(2000);
cTest[0] = EEPROM_read(0);
cTest[1] = EEPROM_read(1);
cTest[2] = EEPROM_read(2);
myWait(2000);
USART_transmit(cTest[0]);
USART_transmit(cTest[1]);
USART_transmit(cTest[2]);
Irgendjemand eine Idee, wo der Fehler liegen könnte?
Hier noch die beiden Funktionen:
/***************/
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
/***************/
{
/* Wait for completion of previous write */
while(EECR & (1<<EEPE)) {
;
}
/* Set up address and data registers */
EEAR = uiAddress;
EEDR = ucData;
/* Write logical one to EEMPE */
EECR |= (1<<EEMPE);
/* Start eeprom write by setting EEPE */
EECR |= (1<<EEPE);
return;
}
/***************/
unsigned char EEPROM_read(unsigned int uiAddress)
/***************/
{
/* Wait for completion of previous write */
while(EECR & (1<<EEPE))
;
/* Set up address register */
EEAR = uiAddress;
/* Start eeprom read by writing EERE */
EECR |= (1<<EERE);
/* Return data from data register */
return EEDR;
}
Ist das nicht so, das man da ein EEMWE bit setzen muss bevor man auf das EEProm schreiben kann und man dann auch nur ein paar Takte hat um den Schreibvorgang zu beginnen ?
Was sagt das Datenblatt dazu, da sind doch so Musterroutinen drin ?
Ich dreh noch durch!
Erstmal herzlichen Dank an wkrug für den Tipp. Du hast Recht, auch wenn das Register und die Bits beim Tiny2313 anders benannt sind. Jedoch habe ich nun einen mir absolut unerklärlichen Effekt vorliegen.
Meine Schleife sah anfangs so aus (alles überflüssige wie USART_init(), LED-Spielchen etc. habe ich weggekürzt):
for(;;) {
//
if( UCSRA & (1<<RXC) ) { //bei einer Eingabe wird diese direkt zurück ans Terminal geschickt
USART_transmit(UDR);
}
}
Dabei wurde einfach jedes empfangene Zeichen zurück ans Terminal (bei mir HTerm) geschickt. Das hat perfekt funktioniert! Dann wollte ich mal die EEPROM-Funktionen testen und hab das ganze folgendermaßen erweitert:
unsigned char cTest[2];
//
//EECR &= ~( (1<<EEPM1)|(1<<EEPM0) ); //(1)
//
EEPROM_write(0,'A');
EEPROM_write(1,'B');
EEPROM_write(2,'C');
myWait(2000);
cTest[0] = EEPROM_read(0);
cTest[1] = EEPROM_read(1);
cTest[2] = EEPROM_read(2);
myWait(2000);
USART_transmit(cTest[0]);
USART_transmit(cTest[1]);
USART_transmit(cTest[2]);
for(;;) {
//
if( UCSRA & (1<<RXC) ) { //bei einer Eingabe wird diese direkt zurück ans Terminal geschickt
USART_transmit(UDR);
USART_transmit(cTest[0]);
USART_transmit(cTest[1]);
USART_transmit(cTest[2]);
}
}
Dann empfing ich, wie gesagt, nur Schrott über die EEPROM-Funktionen. Zumindest dachte ich, dass es daran liegt. Als ich dann aber gesehen habe, dass USART_transmit(UDR) auch nur noch Blödsinn schickt, habe ich die Funktion durch Auskommentieren wieder in den Ursprungszustand versetzt.
Das Ergebnis ist erschütternd: Jetzt liefert mir USART_transmit(UDR) dauerhaft seltsame Werte (jedenfalls nicht die zuvor eingegebenen!). Z.B. kommt 5 mal hintereinander 0xff (255), dann z.B. 0xc0 (192). Dabei kommt es scheinbar nicht darauf an, welche Zeichen ich sende.
Den 2313 habe ich auch mal ausgetauscht, daran kann es nicht liegen. Hat jemand dafür eine Erklärung?
Zu (1): Ich kenne mich noch nicht so gut mit bitweisen Operationen aus. Ist dieser Ausdruck richtig, wenn ich die Bits EEPM1 und EEPM0 löschen will? Dann hätte ich zumindest schonmal die Lösung für mein ursprüngliches Problem, dank des Tipps von wkrug.
Schonmal vielen Dank für jede nützliche oder unnütze Antwort!
Gruß Matze
Hier im Anhang ein ScreenShot von HTerm. Unten sieht man die eingegebenen Werte, oben die von HTerm empfangenen. Man sieht, es scheint egal zu sein, welche Zeichen man nun sendet...
So, bevor ihr euch alle die Köpfe zerbrecht: Ich hab den (wirklich blöden) Fehler gefunden. Die Fuses waren anders gesetzt als ich das mal eingerichtet hatte. Es war eine falsche Taktung angegeben, und das war der Grund für die unsinnigen Outputs.
Hat eigentlich jemand eine Ahnung, warum das AVR Studio teilweise tagelang meine Fuses-Einstellungen behält, dann aber plötzlich und gänzlich unerwartet alles ändert (wahrscheinlich auf Standard-Werte)? Ich kann mir das nicht erklären...
Ich habe immer wieder das Problem, dass die Fuses zurückgesetzt werden (Frequenz anders, Clock divide by 8 plötzlich wieder an...), obwohl es sich immer um mein Testprogramm mit unveränderter Hardware handelt.
@wkrug:
Wenn du jetzt eine Ewigkeit umsonst über das beschriebene Phänomen gegrübelt hast, entschuldige ich mich hiermit. War ein blöder Fehler. Bin halt noch ganzt am Anfang der AVR-Programmierung...
Gruß Matze
Es wäre nett, wenn mir noch einer sagen kann, ob der von mir formulierte Ausdruck (Code-Ansicht, siehe //(1) ) richtig ist. Damit wäre mir sehr geholfen.
So, das Ursprungsproblem ist leider noch vorhanden. Ich habe mal testweise versucht, das komplette EEPROM (beim Tiny2313 128 Bytes) zu beschreiben und auszulesen, jedoch bekomme ich immer nur 0xff zurück.
Die Register sollten doch eigentlich richtig gesetzt sein, oder (siehe oben, 2. Code-Block)? Schließlich ist der Code direkt dem Datenblatt entnommen.
So, wie ich es verstehe, sollten die beiden Funktionen zum Lesen und Schreiben ausreichen, ohne dass ich mir noch eine init()-Funktion basteln muss. Nur, dass es einfach nicht klappt.
Ich habe die Lösung des Problems gefunden!
Der Fehler war tatsächlich, die im Datenblatt enthaltenen Funktionen EEPROM_write() und EEPROM_read() zu nutzen. Die scheinen fehlerhaft zu sein. Stattdessen habe ich nun die Funktionen eeprom_write_byte() und eeprom_read_byte() aus der eeprom.h probiert, und siehe da! Es läuft!
Wirklich schade, dass im Datenblatt, auf das man sich verlassen können sollte, und auf das hier im Forum ständig verwiesen wird, solche Fehler manifestiert sind. Das hat mich unnötigerweise einen guten halben Arbeitstag gekostet...
Gruß Matze
Das Datenblatt muss hier nicht zwingend falsch sein.
Das ist vermutlich auch vom Compiler abhängig.
Wenn der Compiler zu viele Schritte zum Setzen der Bits braucht funktioniert es nicht mehr.
Vieleicht wäre auch Inline Assembler für die Routine eine Lösung gewesen?
Mag sein, ich hatte bislang jedoch den Eindruck, dass der AVR-GCC ziemlich gebräuchlich ist, schließlich wird er auch mit AVR Studio / WinAVR mitgeliefert. Meiner Meinung nach sollte es möglich sein, ein solches Code-Beispiel zum Laufen zu kriegen, wenn man es ohne Änderungen übernimmt.
Mit Assembler habe ich mich noch nicht beschäftigt. Ich bin ja schließlich nicht nur AVR, sondern auch C/C++-Neuling (ich komme aus der Clipper- und VB-Welt). Dies habe ich aber vor. Ich bin sicher, dass das gerade für meinen kleinen 2313 eine gute Idee ist.
Gruß Matze
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.