Forum: Mikrocontroller und Digitale Elektronik EEPROM SPI liefert falsche Werte


von Bbbbb (abcmann)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich bin gerade dabei mit einem Mikrocontroller via SPI einen EEPROM zu 
beschreiben. Genauer gesagt handelt es sich hierbei um  den M95010 
EEPROM.

Die Kommunikation mit dem EEPROM scheint reibungslos zu verlaufen, da 
ich auf meine Fragen stets eine Antwort bekomme. Was mich nun verwirrt 
ist, dass wenn ich an die Adresse 01 einen schreibbefehl sende mit dem 
Inhalt 00 und diese anschließend auslese, erhalte ich 0x80. Besagtes 
Beispiel habe ich im Anhang hinzugefügt.

Erklärung:
1. Byte = Commandbyte (0x02 = Schreiben, 0x03 = Lesen)
2. Byte = Adressbyte
3. Byte = Databyte

Mein Mikrocontroller führt Schreibbefehle aus die Sowohl das Databyte 
als auch die Adresse jeweils um ein erhöhen.
Daraus entstehen die folgenden Werte an Adressen:

Adresse  Schreibwert  Lesewert


0x01.........0x00.........0x80

0x02.........0x01.........0x81

0x03.........0x02.........0x82

................................

0x79.........0x7E.........0xFD

0x80.........0x7F.........0xFE

0x81.........0x80.........0x7F

0x82.........0x81.........0x80

................................

DATA FF wird nie geschrieben + Read DATA wiederholt sich ab 0x80

Ich verstehe nicht so ganz wie dieses Problem zu Stande kommt, da es so 
scheint als wäre das highest value Bit immer gesetzt aber dann kommt der 
Ausnahmefall bei Adresse 0x81 wo auf einmal ein Wert von 7F gelesen 
wird...

Falls benötigt kann ich auch Teile meines Codes zeigen, aber da der 
Schreibwert korrekt funktioniert und der M95010 icht programmierbar ist, 
sollte das keine mögiche Fehlerquelle sein.

: Bearbeitet durch User
von EAF (Gast)


Lesenswert?

Mein Glaskugel sagt:
Du ignorierst die Pagegrenzen und die Wartezeiten.

von Peter D. (peda)


Lesenswert?

Im Datenblatt steht alles nötige.
Zuerst mußt Du WREN senden, damit Du schreiben darfst.
Dann kannst Du das Statusbyte lesen, ob WEL gesetzt ist.

von Bbbbb (abcmann)


Lesenswert?

Hey Peter,
Ja klar WREN und Status hab ich natürlich verwendet das hat nur nicht 
mehr auf den Screenshot gepasst. WEL ist gesetzt wenn ich schreibe.

@EAF könntest du das etwas näher erläutern?

von eeprom writer (Gast)


Lesenswert?

Paul Ö. schrieb:
> @EAF könntest du das etwas näher erläutern?

Bin zwar nicht gefragt worden, antworte aber trotzdem.

Nach dem Schreiben tut man (sinngemäss) das hier:
1
  do  /*  Check EEPROM Busy bit  */
2
  {
3
    SPI_WriteByte (EEPROM_READ_STATUS);
4
    eep_stat = SPI_ReadByte ();
5
  }  while (eep_stat & 0x01);

Und Page Boundaries sind zu beachten, wie EAF schon schrub.

von EAF (Gast)


Lesenswert?

Paul Ö. schrieb:
> @EAF könntest du das etwas näher erläutern?

Ich versuche es.....

Paul Ö. schrieb:
> Falls benötigt
> .....
> sollte das keine mögiche Fehlerquelle sein.
Diese Einschätzung....

Angenommen, deine diagnostischen Fähigkeiten wären soweit ausgebildet, 
dass diese Einschätzung berechtigt ist, dann würdest du diese Frage hier 
im Forum wohl nicht stellen müssen, sondern könntest das Problem alleine 
lösen.

Das treibt mich zu dem logischen Schluss, dass der Fehler genau in dem 
steckt, was ausgeblendet wird.
Ist nicht zu 100% sicher, aber doch recht wahrscheinlich.

EAF schrieb:
> Mein Glaskugel sagt:
> Du ignorierst die Pagegrenzen und die Wartezeiten.
Tipp:
Wenn es solche Dinge gibt, sollten sie im Datenblatt erwähnt werden.
Da (so ich vermute) dir das unbekannt ist, solltest du das nachholen.
Ins besondere dein "fehlerfreies" Schreiben daraufhin kontrollieren.

von Bbbbb (abcmann)


Lesenswert?

Ich führe diesen Code nach jedem geschriebenen Byte aus, also sollte der 
EEPROM idR immer aufnahmefähig sein.
1
  temp = eepromReadStatus(csPin);
2
  while(temp == 0xFB)
3
  {
4
    temp = eepromReadStatus(csPin);
5
  };
mit den Pagesizes hab ich mich noch nicht groß beschäftigt da werde ich 
dann gleich mal rein schauen.

: Bearbeitet durch User
von Bbbbb (abcmann)


Angehängte Dateien:

Lesenswert?

Ich habe den Code mal auf die relevanten Stellen und Funktionen 
zusammengekürzt.

von eeprom writer (Gast)


Lesenswert?

Paul Ö. schrieb:
> mit den Pagesizes hab ich mich noch nicht groß beschäftigt

Man macht einmal Write enable, dann schreibt man soviel
man braucht bis eine Page-Grenze erreicht ist, dann
prüft man das Write-in-progress-Bit bis es gelöscht ist
und fängt von vorne an. Innerhalb einer Page musst du
nicht dauernd Write enable ausführen, du kannst maximal
eine Page mit voller Geschwindigkeit und ohne Handshake
schreiben.

Deine delay-Routine kommt mir sehr verdächtig vor ....
Da gibt es vom Arduino-Framework Besseres.

von A. B. (Gast)


Lesenswert?

Was für einen Sinn soll "while(temp == 0xFB)" machen? Es geht doch NUR 
um das WIP Bit, also fragt man ab, ob (temp & 0x1) wahr oder falsch ist.
Am Ende der Schreiboperation werden WIP und WEL automatisch 
zurückgesetzt, aber ob das gleichzeitig passiert bzw. in welcher 
Reihenfolge ist nicht spezifiziert. Außerdem sind BP1 und BP0 da 
irrelvant.

Auch die erste Schleife mit "while(temp == 0xF8)" macht keinen Sinn. 
Entweder ist WEL sofort nach dem Write Enable gesetzt, oder 
irgendetwas ist schief gelaufen, dann aber weiteres Warten und erneute 
Statusabfrage sinnlos.

von Bbbbb (abcmann)


Lesenswert?

eeprom writer schrieb:
> Man macht einmal Write enable, dann schreibt man soviel
> man braucht bis eine Page-Grenze erreicht ist, dann
> prüft man das Write-in-progress-Bit bis es gelöscht ist
> und fängt von vorne an.

Ja gut, aber da ich bei jedem Schreibzyklus als erstes Write enable 
schreibe, sollte ich dieses Problem was ich durch page sizes bekommen 
könnte umgehen oder verstehe ich da etwas falsch? Klar diese Prozedur 
kostet Geschwindgkeit aber diese muss ich momentan eh Künstlich drosseln 
um meinen logic analyser zu nutzen.

die delay-Routine wird ausschließlich zur Takt-Synchronisierung 
verwendet dafür ist es eben wichtig, dass es recht genau ist.

von mitlesa (Gast)


Lesenswert?

Paul Ö. schrieb:
> aber dann kommt der
> Ausnahmefall bei Adresse 0x81 wo auf einmal ein Wert von 7F gelesen
> wird...

Zeige mal deine Schaltung und Aufbau. Da wird wohl noch ein
Problemchen versteckt sein. Ein Fehlender Abblock-Kondensator
könnte zu solchen "statistischen" zufälligen Fehlern führen.

von A. B. (Gast)


Lesenswert?

Seufz, vielleicht war ich oben nicht deutlich genug oder ich habe 
chinesisch geredet?!

Die beiden Abfragen (temp == 0xFB) bzw. (temp == 0xF8) sind einfach grob 
falsch. BP1 und BP0 im Status Register sind mitnichten '1' und '0'.
Das sind die Block Protect Bits, und im Auslieferungszustand i. d. R. 
beide 0.

Das (temp == 0xFB) ist daher NIE richtig, es wird also NIE auf das 
Ende des Schreibvorgangs gewartet, womit natürlich nur Müll herauskommt.

von mitlesa (Gast)


Lesenswert?

A. B. schrieb:
> Das (temp == 0xFB) ist daher NIE richtig, es wird also NIE auf das
> Ende des Schreibvorgangs gewartet

.... was durch die sagenhafte delay-Routine noch verschleiert wird.

Eigentlich steht's ja schon länger da, aber beratungsresistente
Leute sind ja immun gegen solche Hinweise:

eeprom writer schrieb:
> dann prüft man das Write-in-progress-Bit bis es gelöscht ist

von A. B. (Gast)


Lesenswert?

mitlesa schrieb:
> Eigentlich steht's ja schon länger da, aber beratungsresistente

Ja, sogar mehrfach, aber Lesen ist mittlerweile zur Kunst geworden, die
nicht jeder beherrscht. Einfach traurig ...

> Leute sind ja immun gegen solche Hinweise:

von Bbbbb (abcmann)


Lesenswert?

A. B. schrieb:
> Seufz, vielleicht war ich oben nicht deutlich genug oder ich habe
> chinesisch geredet?!
>
> Die beiden Abfragen (temp == 0xFB) bzw. (temp == 0xF8) sind einfach grob
> falsch. BP1 und BP0 im Status Register sind mitnichten '1' und '0'.
> Das sind die Block Protect Bits, und im Auslieferungszustand i. d. R.
> beide 0.
>
> Das (temp == 0xFB) ist daher NIE richtig, es wird also NIE auf das
> Ende des Schreibvorgangs gewartet, womit natürlich nur Müll herauskommt.

Wenn du dir den Code mal anschaust wirst du merken dass das im Prinzip 
Error-Handler sind die das Programm im Fall dass block protect bits 
gesetzt sind festhalten. Auf diese Art wollte ich sicher gehen, dass das 
keine Fehlerquelle ist.
Außerdem sollte man auf das Ende des Schreibzyklus nicht vor sonder nach 
dem Schreiben warten was mit delay(writecycle) geschieht :)

: Bearbeitet durch User
von mitlesa (Gast)


Lesenswert?

Paul Ö. schrieb:
> Wenn du dir den Code mal anschaust wirst du merken .....

Also wir stellen fest: du machst alles richtig, daher kann
der Thread ja geschlossen werden.

von Bbbbb (abcmann)


Lesenswert?

Hab ich nie gesagt aber ich möchte mich nicht beleidigen lassen für 
Dinge die das tun was sie sollen.

von Bauform B. (bauformb)


Lesenswert?

Paul Ö. schrieb:
> Außerdem sollte man auf das Ende des Schreibzyklus nicht vor sonder nach
> dem Schreiben warten was mit delay(writecycle) geschieht :)

Warum?

von Bbbbb (abcmann)


Lesenswert?

Vorrausgesetzt es würde immer ein Writebefehl folgen wäre es egal ob man 
vor oder nach dem Befehl wartet aber wenn zwischen den Write-Befehlen 
ein Read-Befehl kommt müsste dieser auch eine Routine aufweisen welche 
auf die Beendigung eines potentiellen Write-Befehls reagiert. Ist meiner 
Minung nach etwas umständlich im Vergleich zu einem Warte-Befehl am Ende 
eines Write-Zyklus

von Bauform B. (bauformb)


Lesenswert?

Danke! Ich hatte schon befürchtet, dass die EEPROM-Hardware das braucht.

von Bbbbb (abcmann)


Lesenswert?

Fehler gefunden Thread kann geschlossen werden.

von EAF (Gast)


Lesenswert?

Und?
Was wars?

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.