Forum: Mikrocontroller und Digitale Elektronik LPC1751 und 24LC01 per I2C


von Lars R. (larsr)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich betreibe ein 24LC01 an einem LPC1751 per I2C und habe 
Schwierigkeiten damit. Wenn ich per Debugger durch den Code steppe 
funktioniert jeder Schreibzugriff auf das EEPROM.

Lasse ich jedoch das Programm ganz normal durchlaufen, welches mehrere 
Dutzend Bytes versucht zu schreiben, gibt es Probleme. Der alte Wert 
bleibt einfach im EEPROM erhalten.

Lesen scheint ganz gut zu funktionieren. Jedenfalls wird immer der 
korrekte Wert gelesen, wenn ich vorher mittels Debugger das Schreiben 
ausgelöst habe.

Wo ist das Problem? Ich habe mir Haltepunkte an den Endlosschleifen 
gesetzt, damit ich sehe, wo es eventuell hängen könnte, doch alle 
Statuscodes scheinen korrekt.


Viele Grüße,

Lars

von Jörg S. (joerg-s)


Lesenswert?

>Lasse ich jedoch das Programm ganz normal durchlaufen, welches mehrere
>Dutzend Bytes versucht zu schreiben, gibt es Probleme.
Und wenn du eine Pause zwischen den Bytes machst?

von Klaus (Gast)


Lesenswert?

Hallo,

2 Dinge darfst du nicht machen (sind mir vor ein paar wochen passiert):

1) schreibe bei Page-Write nie über eine Blockgrenze hinaus
   (bei 24LC01 liegen die bei modulo 128 Byte)

2) warte zwischen zwei Schreibzuriffen mindesten diese ominöse "typical
   write cycle time" unabhängig davon wieviele Bytes du geschrieben 
hast.
   (bei 24lC01 sind das 2 msec)

falls jetzt bei I2C kein Fehler ist dann sollte alles gut gehen !!!

Eine Anmerkung noch:

diese zeilen mit " for (;;); " sind nicht schön !!

wenn du auf eine Bedingung triffst nach der sowas steht solltest du die 
Funktion mit einem Error-Code (z.B. -1) verlassen. (vorher noch ein 
i2c_stop)

Gruss Klaus

von Lars R. (larsr)


Lesenswert?

Klaus schrieb:
> 2 Dinge darfst du nicht machen (sind mir vor ein paar wochen passiert):
>
> 1) schreibe bei Page-Write nie über eine Blockgrenze hinaus
>    (bei 24LC01 liegen die bei modulo 128 Byte)

Ich schreibe immer nur einzelne Bytes, da die Zugriffsreihenfolge mehr 
oder weniger zufällig ist.

> 2) warte zwischen zwei Schreibzuriffen mindesten diese ominöse "typical
>    write cycle time" unabhängig davon wieviele Bytes du geschrieben
> hast.
>    (bei 24lC01 sind das 2 msec)

Gut, danke für den Hinweis, das werde ich versuchen. Ich melde mich dann 
wieder.

> falls jetzt bei I2C kein Fehler ist dann sollte alles gut gehen !!!

Im Datenblatt steht, dass man den Controller durch Polling abfragen 
kann. Aber auch innerhalb von wenigen us nach dem Schreibzugriff gibt 
das EEPROM offenbar ein ACK zurück. Sehr seltsam.

> Eine Anmerkung noch:
>
> diese zeilen mit " for (;;); " sind nicht schön !!
>
> wenn du auf eine Bedingung triffst nach der sowas steht solltest du die
> Funktion mit einem Error-Code (z.B. -1) verlassen. (vorher noch ein
> i2c_stop)

Natürlich. Ich habe diese Zeilen ja aber auch nur deshalb eingefügt, 
dass ich dort einen Breakpoint im Debugger setzen kann. Ich hatte mir 
erhofft, so dem Fehler auf die Spur zu kommen.

von Lars R. (larsr)


Angehängte Dateien:

Lesenswert?

Ich habe es nun zum Laufen bekommen dank des Tipps Wartezeiten 
einzufügen.

Zusätzlich habe ich den Takt des I2C-Bus auf 10 kHz reduziert.

Aber irgendwie bin ich von dem Ganzen noch nicht so wirklich überzeugt, 
denn das Lesen geht ja schließlich auch ohne diese Wartezeiten. Zumal 
das Schreiben nun in jedem Falle funktioniert.

Ich habe zwar bis zu fünf Wiederholungen für den Fall vorgesehen, dass 
nachher immer noch der falsche Wert im EEPROM steht, aber bei meinen 
Tests klappte es immer direkt beim ersten Mal. Auch die I2C-Statuscodes 
stimmten bei jedem meiner Versuche...

Mir erscheint dies aber ziemlich unprofessionell, wer weiß Rat?

von Klaus (Gast)


Lesenswert?

Hallo,

lese mal ein paar Datenblätter und auch sonstige Informationen zu 
EEPROM.

Dort siehst du dass das Auslesen von EEPROMs keine zeitlichen Probleme 
macht.
Aber das Schreiben:
- zuerst kommt alles in einen Puffer (alles IC intern)
- dann muss die Speicherstelle gelöscht werden
- und dann wird sie neu programmiert

und weil das alles für ein einzelnes Byte viel zu aufwändig ist wird das 
(chip intern) immer für einen ganzen Block gemacht unabhängig wieviel du 
von dem Block verändert hast.

Das Alles daaaaaauuuuuuuuert !!!!

Gruss Klaus

von Klaus (Gast)


Lesenswert?

Noch was vergessen:

Der Takt spielt keine Rolle, den kannst du auf das Maximum 400kHz 
stellen sofern es deine Harware zulässt (kurze Leitungen, wenig 
Kapazität etc.)

von Lars R. (larsr)


Lesenswert?

Klaus schrieb:
> lese mal ein paar Datenblätter und auch sonstige Informationen zu
> EEPROM.

Ich bitte dich, das ist das Erste, was ich tue.

Im Datenblatt steht, dass der "Self-timed write cycle" beginnt, sobald 
das I2C-STOP nach dem Schreibbefehl erkannt wurde.

Während das EEPROM dann mit dem Schreiben beschäftigt sei, würde es 
nicht auf seine Geräteadresse reagieren, deshalb könne man den 
Datendurchsatz durch Polling maximieren.

Und dies ist eben nicht der Fall! Das EEPROM reagiert unmittelbar nach 
Absetzen des Schreibbefehls auf seine Geräteadresse mit einem ACK und 
deshalb lässt es sich nicht pollen.

Ich kannte den I2C eigentlich immer so, dass ein IC die Taktleitung auf 
Masse gezogen hält, so lange es noch beschäftigt ist. Dies wäre auch 
okay, dann bekäme ich einen Fehler beim Versuch ein I2C-START 
auszugeben. Dies würde sich auch gut abfragen lassen.

Aber so? Ich könnte hier vielleicht einen Timer auf 5 ms aufziehen und 
den nächsten Schreibbefehl erst ausgeben, wenn diese Zeit abgelaufen 
ist, aber dies gefällt mir eigentlich nicht.

Im Datenblatt steht auch nichts davon, dass man sogar Pausen zwischen 
den einzelnen Bytes machen muss.

Andere serielle EEPROM wie das 93LC46 machen solche Probleme nicht: Die 
halten ihre Ausgabeleitung auf "low" so lange sie schreiben und das Chip 
Select-Signal anliegt. Sobald das Schreiben fertig ist, geht dann die 
Ausgabeleitung wieder auf "high". Dies ist auch okay und lässt sich 
wunderbar abfragen.

Verstehe mich bitte nicht falsch, ich sehe ja, dass es auch so 
funktioniert. Aber ich würde eigentlich erwarten, dass es irgendwie 
möglich ist, dieses Teil zu pollen. Bloß wie?

von Lars R. (larsr)


Lesenswert?

Klaus schrieb:
> Noch was vergessen:
>
> Der Takt spielt keine Rolle, den kannst du auf das Maximum 400kHz
> stellen sofern es deine Harware zulässt (kurze Leitungen, wenig
> Kapazität etc.)

Im Datenblatt steht, dass 400 kHz nur bei 5 Volt Versorgungsspannung 
erlaubt seien. In meinem Falle wird das EEPROM mit 3,3 Volt versorgt. 
Laut Datenblatt ist hierbei bereits bei 100 kHz Schluss.

So viel zum Thema Datenblatt.

von Klaus (Gast)


Lesenswert?

Hallo,

ich bin leider ein vergesslicher Mensch und weiss nicht mehr wie es mit 
24LC01 war. Der letzte IC mit dem ich gearbeitet hab war der 24LC256 vor 
etwa einem halben Jahr und der zeigte ziemlich das gleiche Verhalten das 
du bemängelst.
Wie das aber ganz genau war weiss ich auch nicht mehr !

Dass er den Bus nicht blockiert (weder SDA noch CLK auf LOW) wenn er 
beschftig ist gut.

Nur er sollte (auch laut Datenblatt) bei jeden "Request" (ob lesen oder 
schreiben) die "Slave Adresse" mit NACK beantworten wenn er beschäftigt 
ist.

Jetzt hab ich mal in meinem letzten Programm nachgeschaut.
Dieses Programm läuft auf einem LPC2148, der offensichtlich eine 
identische I2C Einheit besitz wie der LPC1751.

Du solltest in deinem Status Register nach einem Request entweder
>case 0x20:  /* MT, SLA+W has been transmitted; NOT ACK has been received. */
oder
>case 0x48:  /* MR, SLA+R has been transmitted; NOT ACK has been received. */
vorfinden und das ist OK.

So steht das in meinem Interrupt-Handler!
MT steht für "Master Transmitt" bzw MR für "Master Receive"

In beiden Fällen sollte/muss die Übertragung mit I2C_stop abgebrochen 
werden und der Bus freigegeben werden.
Dem nächsten Versuch etwas später steht dann nichts im Weg.


Gruss Klaus

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.