Forum: Mikrocontroller und Digitale Elektronik STM32 I2C EEPROM lässt sich lesen aber nicht beschreiben


von Felix N. (felix_n888)


Angehängte Dateien:

Lesenswert?

Hallo Community,

Ich versuche seit gestern vergeblich ein I2C EEPROM am STM32F103C8T6 
(Blue Pill Board, es ist aber glaubig ein Fake-uC auf dem Board verbaut 
da man ihm mit ST-Link GDB Server nicht programmieren kann es geht nur 
mit OpenOCD, weiß nicht ob es evtl. damit was zutun hat?) ans laufen zu 
bekommen.

Als EEPROM verwende ich ein ST24C08WP, hatte zuerst ein Nagel neuen Chip 
genommen aber als er beim lesen immer nur 0xFF zurückgegeben hat obwohl 
ich ein anderen Wert vorher einprogrammiert habe. Habe ich irgendwann 
mal den gleichen EEPROM-Chip aus einem Gerät von mir genommen wo schon 
Daten drin sind und den ausprobiert. Es kamen dann auch andere Werte als 
0xFF im unteren Adressbereich also habe ich den neuen EEPROM Chip mit 
einem ATMega328P testweise programmiert auf die Adresse 0x08 habe ich 
den Wert 0x18 geschrieben.

Wenn ich mit dem STM32F1 die Adresse 0x08 auslese bekomme ich den Wert 
0x18, gut schon mal das lesen funktioniert. Nur das schreiben will 
nicht.

Da ich keinen Logikanalysator habe, habe ich mir das Signal mit meinem 
Oszilloskop angeschaut, und es versucht zu dekodieren(Beim AVR Bild habe 
ich es mit eingefügt beim STM32 sind mir immer wieder Unstimmigkeiten 
beim ACK aufgefallen). Deswegen auch Adresse 0x08 und 0x18 an Daten da 
diese Bits in der Mitte des Bytes liegen ist es einfacher sie zu 
erkennen.

Das einzige was mir wirklich bei den beiden Schreibzugriffen zwischen 
AVR/STM32 auffällt ist das dass der ACK beim STM32 nur 1us statt fast 
10us wie beim AVR dauert. Und das nachdem der ACK für die Daten kam die 
SCL Leitung noch weitere Zwei Clock Impulse liefert bevor die STOP 
Bedienung kommt.

Jedoch passiert das gleiche beim Lesen mit dem STM32 auch und dort 
scheinen die Daten dem EEPROM ja wohl zu passen sonst würde er ja nicht 
die richtigen Daten zurückschicken. Der Chip scheint ja auch zu 
antworten den schließlich wird das "Address Match Bit" im SR1 Register 
gesetzt ohne EEPROM/Falscher Adresse bleibt der Code in der while 
Schleife hängen.

Wie die Daten/Register "gefüttert" werden müssen habe ich mir aus dem 
"Transfer sequence diagram for master transmitter" Diagramm geholt. Ich 
habe mir dann heute morgen ein Tutorial Video angeschaut über den I2C 
Bus beim STM32 und konnte somit schonmal ein Fehler in meiner 
Schreibsequenz ausschließen da der Schreibcode identisch mit meinem war. 
Und bei ihm in Video konnte der damit Problemlos ein Atmel 2Kibit EEPROM 
beschreiben.

Die I2C Frequenz liegt bei etwa 100KHz was auch der Maximale für den 
EEPROM Chip ist. Aber auch mit niedrigen Frequenzen wie 80KHz oder 50KHz 
macht es kein Unterschied. Lesen geht aber schreiben nicht. Die Frequenz 
des APB1 Bus liegt bei 36MHz. CPU selbst läuft auf 72MHz. CCR Wert ist 
180 und TRISE ist 37. 4,7kOhm PullUp Widerstände sind extern am Bus 
vorhanden nach 3,3V.

Mein Code habe ich mal als Datei angehängt(Habe ihn nur auf den I2C 
Schreibkram begrenzt da das auch mein letzter Test war um auszuschließen 
das andere Peripherie wie PWM, USART, SPI etc... die noch aktiv waren 
darein zu stören. Wenn dann die gelesen Daten 0x20 entsprachen ging die 
Onboard LED an(Sie ging aber nie an)

Ich weiß nicht mehr weiter woran es liegen könnte. Habt ihr ne Idee?

Mfg

von Ingo Less (Gast)


Lesenswert?

Lesen und Schreiben wird in durch die Hardware des Controllers bestimmt, 
d.h. er generiert das R/W -Bit selber. Du kannst nicht einfach R/W zu 
der Adresse hinzufügen, dass macht der Controller selber wenn du ihn im 
entsprechendem Register sagst Lesen oder Schreiben. Das ist ne miese 
Falle...

von Felix N. (felix_n888)


Lesenswert?

Ingo Less schrieb:
> Lesen und Schreiben wird in durch die Hardware des Controllers bestimmt,
> d.h. er generiert das R/W -Bit selber

Hallo, also im Datenblatt darüber konnte ich jetzt nix finden das er es 
selbst generiert.

Ingo Less schrieb:
> du kannst nicht einfach R/W zu
> der Adresse hinzufügen, dass macht der Controller selber wenn du ihn im
> entsprechendem Register sagst Lesen oder Schreiben

Welche Bit soll das den in dem CR1/CR2 Registern sein? Habe gerade 
nochmal geschaut habe da nicht gefunden um den Bus es mitzuteilen das es 
nun eine Lese oder Schreibzugriff ist.

Unter Start Condition steht:

"Once the Start condition is sent:
* The SB bit is set by hardware and an interrupt is generated if the 
ITEVFEN bit is set. Then the master waits for a read of the SR1 register 
followed by a write in the DR register with the Slave address"

Mfg

von Harry L. (mysth)


Lesenswert?

Den WP-Pin (Pin 7) richtig beschaltet?

von Walter T. (nicolas)


Lesenswert?

Ingo Less schrieb:
> Lesen und Schreiben wird in durch die Hardware des Controllers bestimmt,
> d.h. er generiert das R/W -Bit selber. Du kannst nicht einfach R/W zu
> der Adresse hinzufügen, dass macht der Controller selber wenn du ihn im
> entsprechendem Register sagst Lesen oder Schreiben.

Das stimmt in Bezug auf Bus lesen/schreiben, aber nicht in Bezug auf 
EEPROM lesen/schreiben. Beim EEPROM lesen wird auf dem Bus gelesen und 
geschrieben.

von Ingo Less (Gast)


Lesenswert?

Felix N. schrieb:
> Welche Bit soll das den in dem CR1/CR2 Registern sein?
Sorry, grade gesehen das du einen F1 benutzt. Bei einem F0 ist es das 
Bit im RD_WRN im CR2 Register.

von Peter D. (peda)


Lesenswert?

Felix N. schrieb:
> Das einzige was mir wirklich bei den beiden Schreibzugriffen zwischen
> AVR/STM32 auffällt ist das dass der ACK beim STM32 nur 1us statt fast
> 10us wie beim AVR dauert.

1µs = 1MHz I2C-Takt. Manche EEPROMs können das, aber nicht jeder.
Setze mal den Takt auf 100kHz runter.

Felix N. schrieb:
> Und das nachdem der ACK für die Daten kam die
> SCL Leitung noch weitere Zwei Clock Impulse liefert bevor die STOP
> Bedienung kommt.

Das STOP muß immer direkt auf das ACK/NACK folgen. Da ist also eindeutig 
was faul in Deiner I2C-Lib.

von Holger (Gast)


Lesenswert?

Felix N. schrieb:
> Das einzige was mir wirklich bei den beiden Schreibzugriffen zwischen
> AVR/STM32 auffällt ist das dass der ACK beim STM32 nur 1us statt fast
> 10us wie beim AVR dauert.

Nein, ich glaube du verwechselst ACK und NACK. I²C ist open-drain, d.h. 
wenn der Gegenpart nicht antwortet (z.B. falsche Adresse) bleibt die 
Datenleitung high, was deswegen einem NACK entspricht. Nur wenn die 
Gegenstelle ihre eigene Adresse erkennt und aktiv die Datenleitung auf 
low zieht wird weitergemacht. Deswegen: ACK=low und NACK=high.

Das ACK wird vom Empfänger in der steigenden Flanke des Neunten Bit 
übertragen. In der darauf folgenden fallenden Flanke lässt der Empfänger 
die Datenleitung nochmal los und der Sender übernimmt nochmal, deswegen 
siehst du da auf der Datenleitung immer diesen kurzen Puls.

Beim AVR bleibt die Datenleitung während des neunten Bit high -> Der 
Empfänger antwortet nicht.

Beim ST ist die Datenleitung während des neunten Bit low -> Der 
Empfänger ACK'ed die Anfrage, anschliessend übernimmt nochmal der ST 
(deswegen der kurze Peak auf der Datenleitung)

Gruß,

Holger

von Felix N. (felix_n888)


Angehängte Dateien:

Lesenswert?

Harry L. schrieb:
> Den WP-Pin (Pin 7) richtig beschaltet?

Jo der WP Pin liegt auf Masse. Also nicht schreibgeschützt.

Walter T. schrieb:
> Das stimmt in Bezug auf Bus lesen/schreiben, aber nicht in Bezug auf
> EEPROM lesen/schreiben

Ingo Less schrieb:
> Sorry, grade gesehen das du einen F1 benutzt. Bei einem F0 ist es das
> Bit im RD_WRN im CR2 Register

Ah ok alles klar.

Peter D. schrieb:
> 1µs = 1MHz I2C-Takt. Manche EEPROMs können das, aber nicht jeder.
> Setze mal den Takt auf 100kHz runter.

Eben nicht. Die Taktfrequenz des SCL Signals liegt ziemlich genau bei 
100KHz. Habe ich gerade nochmal mit meinem Scope geprüft. Allerdings 
verhält sich das ACK Signal sehr komisch(Siehe Bild).

Es erfolgt für etwa 9,7us eine Anhebung auf 660mV danach erfolgt dann 
für ca. 1us eine Anhebung auf 3,3V des Signals. Also das 10us Signal ist 
wohl da allerdings auf gerade mal 0,6V was definitiv als LOW erkannt 
wird.

Deswegen hatte ich ja oben auch geschrieben das dieses der einzige 
Unterschied zum AVR Bild ist. Beim AVR-I2C ist der ACK 10us lang und 
geht direkt auf 5V hoch. Bei dem STM32 nur für 1us auf 3,3V der Rest ist 
0,6V. Allerdings wenn ich von einer EEPROM Adresse lesen möchte sieht 
das Signal und auch das ACK Bit genauso aus. Und da scheint es ihm ja 
wohl nicht zu stören denn die Daten kommen ja richtig raus aus dem Chip.

Peter D. schrieb:
> Das STOP muß immer direkt auf das ACK/NACK folgen.

Tut es ja auch siehe meine main.c das ist der letzte Code welcher dieses 
Signal erzeugt. Der Ablauf ist wie folgt:

(1) START Bedienung

(2) Adresse schreiben   -> Generiert ACK

(3) Antwort auf Adresse?

(4) Interne EEPROM Adresse schreiben -> Generiert ACK

(5) Wert ins EEPROM schreiben    -> Generiert ACK

(6) STOP Bedienung


Die ACK Generation ist die ganze Zeit über aktiviert. So das nach jedem 
übertragenden Byte ein ACK generiert wird.

Das ganze wundert mich halt auch weil beim lesen muss ich ja dem Chip 
erst durch ein Schreibefehl die Adresse zuweisen dann ein neuen Start 
auslösen und die Daten dann lesen. Was ja funktioniert, also scheint er 
die gesendeten Daten zu verstehen. Nur warum er das beim schreiben nicht 
tut ist mir ein Rätsel.

Mfg

von Felix N. (felix_n888)


Lesenswert?

Holger schrieb:
> Nein, ich glaube du verwechselst ACK und NACK. I²C ist open-drain, d.h.
> wenn der Gegenpart nicht antwortet (z.B. falsche Adresse) bleibt die
> Datenleitung high, was deswegen einem NACK entspricht.

Hallo, also deuten diese ersten 0,6V für 9,8us auf ein ACK des EEPROM 
Chips hin. Sprich nachdem senden der Salveaddress das er diese erkannt 
hat? Und dann entsprechend auch das ADDR Bit im Mirkocontroller gesetzt 
wird?

Holger schrieb:
> Beim AVR bleibt die Datenleitung während des neunten Bit high -> Der
> Empfänger antwortet nicht.

Hmm, komisch die Daten wurden trotzdem rein geschrieben ins EEPROM.

Also ich habe mir gerade nochmal das Datenblatt des ST24C08WP angeschaut 
dort steht der Byte Write so drin.

Als erstes muss eine START Bedienung erfolgen worauf dann die 
Geräteadresse mit R/W Bit 0 erfolgen muss. Wenn diese richtig ist 
antwortet der Speicherchip mit einem ACK. Danach muss die Adresse für 
den internen EEPROM Speicher erfolgen. Das wird dann vom Chip wird mit 
einem ACK bestätigt. Dann wird das zu Speicherende Byte gesendet was 
wieder vom Chip mit einem ACK bestätigt wird dann kommt die STOP 
Bedienung.

Ich verstehe das nun so das der EEPROM Chip die ACKs erzeugt und nicht 
der I2C Master also muss ich das ACK Generierungs Bit im CR1 Register 
deaktivieren?

Mfg

von Holger (Gast)


Lesenswert?

Felix N. schrieb:
> Holger schrieb:
>> Nein, ich glaube du verwechselst ACK und NACK. I²C ist open-drain, d.h.
>> wenn der Gegenpart nicht antwortet (z.B. falsche Adresse) bleibt die
>> Datenleitung high, was deswegen einem NACK entspricht.
>
> Hallo, also deuten diese ersten 0,6V für 9,8us auf ein ACK des EEPROM
> Chips hin. Sprich nachdem senden der Salveaddress das er diese erkannt
> hat? Und dann entsprechend auch das ADDR Bit im Mirkocontroller gesetzt
> wird?

Ja, das würde ich so interpretieren.


Felix N. schrieb:
> [...]
> Also ich habe mir gerade nochmal das Datenblatt des ST24C08WP angeschaut
> dort steht der Byte Write so drin.

https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwiOu-3-mKTyAhUImBQKHQlbCsoQFnoECAYQAw&url=https%3A%2F%2Fwww.st.com%2Fresource%2Fen%2Fdatasheet%2Fm24c08-r.pdf&usg=AOvVaw0P4YggHW9alYwr6HgoNzX-

Auf dem Bild auf Seite 11 erkennst du das ACK einem low entspricht.

Felix N. schrieb:
> [...]
> Als erstes muss eine START Bedienung erfolgen worauf dann die
> Geräteadresse mit R/W Bit 0 erfolgen muss. Wenn diese richtig ist
> antwortet der Speicherchip mit einem ACK. Danach muss die Adresse für
> den internen EEPROM Speicher erfolgen. Das wird dann vom Chip wird mit
> einem ACK bestätigt. Dann wird das zu Speicherende Byte gesendet was
> wieder vom Chip mit einem ACK bestätigt wird dann kommt die STOP
> Bedienung.
>
> Ich verstehe das nun so das der EEPROM Chip die ACKs erzeugt und nicht
> der I2C Master also muss ich das ACK Generierungs Bit im CR1 Register
> deaktivieren?

Genau, das ACK wird immer vom Empfänger generiert. Für den Fall das du 
Daten an das EEProm schickst, ACK'ed das EEPRom jedes empfangene Byte. 
Die Daten werden in der Regel in einen temporären Buffer geschrieben und 
erst beim Empfang der STOP-Condition in den internen Speicher 
übernommen. Möglicherweise ist es für das EEPRom ein Problem das 
zwischen ACK und STOP-Condition noch ein Datenbit kommt, so das es auf 
das nächste Datenbyte wartet anstatt die Daten in den internen Speicher 
zu übernehmen.

Ich glaube du musst beim ST die STOP-Condition setzen bevor das letzte 
Datenbyte gesendet wird, dann sendet er die STOP-Condition sofort 
nachdem  er das ACK empfange hat.

Gruß,

Holger

von Holger (Gast)


Lesenswert?

Holger schrieb:
> [...] Möglicherweise ist es für das EEPRom ein Problem das
> zwischen ACK und STOP-Condition noch ein Datenbit kommt, so das es auf
> das nächste Datenbyte wartet anstatt die Daten in den internen Speicher
> zu übernehmen.

Vergiss den Satz. In der Grafik im Datenblatt gibt es ebenfalls noch ein 
Clock Signal bevor die STOP-Condition kommt.

von Peter D. (peda)


Lesenswert?

Die Nadel stört nicht, der Pegel darf sich wärend SCL = 0 ändern und 
wird mit der steigenden Flanke eingelesen.
Die 0,6V low Pegel sind allerdings recht hoch, deutet auf zu kleinen 
Pullup hin. Es sollten nicht mehr als max 3mA fließen.

von Felix N. (felix_n888)


Lesenswert?

Holger schrieb:
> Ich glaube du musst beim ST die STOP-Condition setzen bevor das letzte
> Datenbyte gesendet wird, dann sendet er die STOP-Condition sofort
> nachdem  er das ACK empfange hat.

Selbst wenn man es macht. Dann bleibt der I2C Bus im "Busy" Mode 
stecken.

Peter D. schrieb:
> Die Nadel stört nicht, der Pegel darf sich wärend SCL = 0 ändern und
> wird mit der steigenden Flanke eingelesen.

OK.

Peter D. schrieb:
> Die 0,6V low Pegel sind allerdings recht hoch, deutet auf zu kleinen
> Pullup hin. Es sollten nicht mehr als max 3mA fließen.

Du meinst die 0,6V als Low Pegel? Die Pullup Widerstände sind 4,7kOhm 
groß. Es fließt nicht mal ein mA.

I = U/R -> 3,3V/4,7kOhm = 0,00070 A = 700uA. Aus den AVR Datenblätter 
kenne ich diese Formel zum Berechnen der Pullup Widerstände noch:

Wenn fscl <= 100KHz. Rmin = Vcc - 0,4V / 3mA und Rmax = 1000ns/Cbus

und bei fscl >= 100KHz Rmin gleich wie bei <=100KHz nur rmax = 
300ns/Cbus

Wenn ich das jetzt mal für 100KHz beim STM32 durchrechne:

fscl=100KHz, Vcc=0,3V, I=3mA, Cbus=~8pF(Aus Datenblatt ST24C08WP)

Rmin = 3,3 - 0,4V / 3mA = 966,667 Ohm -> 1kOhm

Rmax = 1000ns/8pF = 125kOhm

Allerdings muss ich sagen das es nun funktioniert ....

Ich weiß nicht woran es lag. Ich hatte testweise die PullUp Widerstände 
gegen 1K getauscht da ich aber versehentlich in der Software die 
Geräteadresse um 2 nach linkes statt 1 geschiftet habe bekam ich erst 
keine Antwort vom Chip. Habe dann die Widerstände wieder zurück nach 
4,7k getauscht und dann den Software Fehler behoben und auf einmal wurde 
der zuvor geschriebene Wert wieder ausgelesen.

Habe dann noch ein paar andere Werte getestet, funktioniert jetzt wie es 
soll. Keine Ahnung ob es Kontakt Schwierigkeiten gab oder das tolle 
Steckbrett wieder Schuld ist. Die Signal fürs Scope habe ich direkt an 
den Widerständen abgenommen und nicht am IC Pin selbst.

Werde noch ein paar Sachen damit testen, und dann meine Lib 
weiterschreiben um mehrere Bytes zuschreiben bwz. zu lesen das scheint 
ja auch wohl eine Besonderheit bei den STM32 I2Cs zu sein.

Sagte trotzdem mal danke an alle die mir geholfen haben! DANKE

mfg

von Holger (Gast)


Lesenswert?

Felix N. schrieb:
> Allerdings muss ich sagen das es nun funktioniert ....
>
> Ich weiß nicht woran es lag. Ich hatte testweise die PullUp Widerstände
> gegen 1K getauscht da ich aber versehentlich in der Software die
> Geräteadresse um 2 nach linkes statt 1 geschiftet habe bekam ich erst
> keine Antwort vom Chip. Habe dann die Widerstände wieder zurück nach
> 4,7k getauscht und dann den Software Fehler behoben und auf einmal wurde
> der zuvor geschriebene Wert wieder ausgelesen.

Hast du vielleicht versucht direkt nach dem Schreiben die Daten zu 
lesen? Das eeprom puffert die Daten und schreibt sie erst in den 
internen Speicher wenn es die STOP-Condition empfängt. Der 
Schreibvorgang dauert einige Millisekunden und in der Zeit reagiert das 
eeprom auch nicht auf seine Adresse (NACK). Deswegen musst du nach einem 
Schreibvorgang einige Millisekunden warten bis du die Daten auslesen 
kannst.
Wenn du wissen willst wann das eeprom mit dem Schreiben fertig ist, 
kannst du es so lange Adressieren bis es nochmal reagiert (ACK).

Gruß,

Holger

von Felix N. (felix_n888)


Lesenswert?

Holger schrieb:
> Hast du vielleicht versucht direkt nach dem Schreiben die Daten zu
> lesen?

Nein ich hatte immer nur eins gemacht also Schreiben oder lesen. Weil 
ich mir das Signal ja mit meinem Oszilloskop anschauen wollte wenn ich 
schreibe und lese triggert das Scope nur auf das schreiben und das lesen 
konnte ich nicht mehr mit einsehen.

Holger schrieb:
> Deswegen musst du nach einem
> Schreibvorgang einige Millisekunden warten bis du die Daten auslesen
> kannst.

Ich weiß im Byte Mode 10ms und im Multibyte Mode 20ms mindestens. Habe 
später 50ms gewartet. Ich vermute das es schlechter Kontakt von den 
Widerstände ans Steckbrett oder zwischen Steckbrett und EEPROM IC wahr.

Holger schrieb:
> Wenn du wissen willst wann das eeprom mit dem Schreiben fertig ist,
> kannst du es so lange Adressieren bis es nochmal reagiert (ACK).

Meinst du mit dem warten bis das ADDR Bit gesetzt ist?

Mfg

von Holger (Gast)


Lesenswert?

Felix N. schrieb:
> Holger schrieb:
>> Wenn du wissen willst wann das eeprom mit dem Schreiben fertig ist,
>> kannst du es so lange Adressieren bis es nochmal reagiert (ACK).
>
> Meinst du mit dem warten bis das ADDR Bit gesetzt ist?

Während das eeprom Daten schreibt reagiert es nicht auf die eigene 
Adresse, die Datenleitung bleibt also im Neunten Bit also high (=NACK)). 
Das kannst du im Register SR1[ ADDR ] abfragen. Nachdem alle Neun Bits 
übertragen wurden (8 Adressbits + 1 ACK/NACK) steht dort nämlich das 
Ergebnis drin (0=NACK, 1=ACK). Falls dort eine 0 drin steht (NACK) 
kannst du es erneut versuchen, so lange bis du entweder ein Timeout 
erreicht hast oder das eeprom nochmal antwortet.

von Peter D. (peda)


Lesenswert?

Wichtig ist für das Schreiben das abschließende STOP. Ohne STOP wird das 
Schreiben verworfen (z.B. Power off, repeated START).

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.