Forum: Mikrocontroller und Digitale Elektronik EEPROM wird nicht korrekt ausgelesen


von Thorsten (Gast)


Lesenswert?

Hallo,

ich habe eine Frage bezüglich Arbeiten mit EEPROM.

Ich schicke über UART einen String zum Atmega8, dieser String wird dann 
im EEPROM gespeichert, sowie die Länge des Stringes.

Ds funktioniert auch wunderbar. Jetzt möchte ich allerdings den String 
wieder auslesen, das klappt auch, jedoch wird immer alles, was in dieser 
EEPROM Stelle geschriebn ist ausgelesen und nicht nur der teil, den ich 
gerne hätte.

Folgenden Teilausschnitt betrifft das EEPROM
1
// String ins EEPROM abspeichern
2
eeprom_write_block (&uart_string, &eeFooNummer,sizeof(uart_string));  // Nummer ins EEPROM abspeichern
3
4
//Länge des Strings extra abspeichern
5
NummerLaenge = strlen(uart_string);          eeprom_write_byte(&eeFooLaengeNummer,NummerLaenge);  // Länge der Nnummer ins EEPROM abspeichern
6
7
//EEPROM auslesen
8
NummerLaenge = eeprom_read_byte (&eeFooLaengeNummer);    // Auslesen der Länge der Nnummer
9
eeprom_read_block( &EepromNummerAusgelesen, eeFooNummer, NummerLaenge  );    // Nummer aus dem EEPROM lesen

wenn ich jetzt einen string abspeicher kann ich ihn ohne Probleme 
auslesen. Wenn ich jetzt allerdings einen kleineren String als den 
gespeicherten abspeicher, wird die Länge korrekt angezeigt, beim 
auslesen werden aber die nicht überschriebenen Zeichen vom alten String 
mit ausgegeben.

Warum ist das so ?

von (Gast) (Gast) (Gast) (Gast) (Gast) (Gast) (Gast) (Gast)


Lesenswert?

Wo schreibst du die stringlänge ins eeprom?

von Thorsten (Gast)


Lesenswert?

siehe
1
//Länge des Strings extra abspeichern
2
NummerLaenge = strlen(uart_string);          eeprom_write_byte(&eeFooLaengeNummer,NummerLaenge);  // Länge der Nnummer ins EEPROM abspeichern

Das ist auch nicht das problem, wenn ich einen neuen kleineren String 
abspeicher und ich mir dann beim auslesen die Länge auch ausgeben lasse, 
passt die auch, nur wird immer alles von andere ausgegeben.
Bsp.:
ich sende über UART: 12345
aus EEPROM ausgelesen: 12345
Länge ausgelesen: 5
ich sende über UART: 124
Länge ausgelesen: 3
aus EEPROM ausgelesen: 12445

Obwohl ich vermutet habe, dass nur 124 ausgelesen wird.......

Ich find den Fehler einfach nicht.

von (Gast) (Gast) (Gast) (Gast) (Gast) (Gast) (Gast) (Gast)


Lesenswert?

Oh sorry, das wird am Telefon schlecht dargestellt. Hmm, strlen() gibt 
die Länge ohne das abschließende \0 zurück. Ob da der Haken liegt?

von holger (Gast)


Lesenswert?

>eeprom_read_block( &EepromNummerAusgelesen, eeFooNummer, NummerLaenge  );

Müsste das nicht

eeprom_read_block( &EepromNummerAusgelesen, &eeFooNummer, NummerLaenge 
);

lauten?

Ich denke das das mit dem &EepromNummerAusgelesen falsch ist und

eeprom_read_block( EepromNummerAusgelesen, &eeFooNummer, NummerLaenge 
);

sein sollte.

Wo ist der komplette Code?

von holger (Gast)


Lesenswert?

Nachtrag:

Wenn du EepromNummerAusgelesen am Ende nicht mit 0 abschliesst
wird natürlich auch der bereits enthaltene alte Schrott mit angezeigt.

Versuch mal EepromNummerAusgelesen[NummerLaenge] = 0;
nach dem auslesen.

von Thorsten (Gast)


Lesenswert?

Hallo,

danke für die Antworten.

Ist es dnen möglich, die EEPROM Stelle vor dem Beschreiben mit einem 
neuen Wert zu löschen oder zurückzusetzen?

Weil die Anzahl der Zeichen stimmt ja überein, nur wird halt der alte 
Teil irgendwie nicht gelöscht....

Gruß

von Karl H. (kbuchegg)


Lesenswert?

So wie du das EEPROM beschreibst, brauchst du die Länge überhaupt nicht 
speichern. In C ist jeder gültige String \0 terminiert und enthält somit 
implizit seine Längenangabe.

Willst du die Länge speichern, dann musst du allerdings diese 
0-Terminierung beim Lesen aus dem EEPROM auch wieder korrekt herstellen.
Das hier
1
eeprom_read_block( &EepromNummerAusgelesen, eeFooNummer, NummerLaenge  );    // Nummer aus dem EEPROM lesen
gewährleistet das nicht. Denn NummerLaenge ist die Anzahl der Zeichen 
ohne die abschliessende \0 Terminierung.

Da du den String so in den Speicher schreibst:
1
eeprom_write_block (&uart_string, &eeFooNummer,sizeof(uart_string));  // Nummer ins EEPROM abspeichern
steht die \0-Terminierung sowieso im EEPROM (sofern das Ausgangsmaterial 
im Array korrekt war). Du könntest daher den String entweder so 
zurücklesen
1
eeprom_read_block( &uart_string, eeFooNummer, sizeof(uart_string));    // Nummer aus dem EEPROM lesen

oder so
1
eeprom_read_block( &EepromNummerAusgelesen, eeFooNummer, NummerLaenge+1  );    // Nummer aus dem EEPROM lesen

oder so
1
eeprom_read_block( &EepromNummerAusgelesen, eeFooNummer, NummerLaenge  );    // Nummer aus dem EEPROM lesen
2
EepromNummerAusgelesen[NummerLaenge] = '\0';

in all diesen Fällen wird die \0-Terminierung wieder korrekt 
hergestellt. Persönlich würde ich die erste Variante nehmen und die 
Länge überhaupt nicht im EEPROM speichern.

Und PS:
Bei Arrays brauchst du kein & um es an eine Funktion zu übergeben. 
Arrays werden immer so an Funktionen übergeben, dass der Arrayname als 
Startadresse des Speicherbereihs fungiert. Genau genommen ist es falsch 
hier ein & zu schreiben, nur haben hier die Compilerbauer anscheinend 
resigniert und akzeptieren diesen Operator an dieser Stelle. Eigentlich 
müsste hier eine Fehlermeldung kommen, denn eine Adresse hat selbst 
keine Adresse.

von Thorsten (Gast)


Lesenswert?

Vielen Dank für die sehr ausführliche Antwort.

Ich werde es heute Abend direkt ausprobieren und eine kurze Rückmeldung 
geben.

Wegen der Fehlermeldung kommt bei meinem Compiler nicht mal eine 
Warnung, wahrscheinlich ist die Stufe zu niedrig eingestellt oder was 
auch immer.

Mit freundlichen Grüßen

Thorsten

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.