I2C Problem mit Acknowledge Polling

Gast #4224160
Lesenswert?

Hallo zusammen,

ich möchte mit einem STM32F205 ein EEPROM vom Typ "24LC32" über I2C 
ansteuern und bekomme das auch gut hin... Außer einer Kleinigkeit.

Man kann das 24LC32 Pageweise schreiben, wenn man nach Übermittlung von 
32 Byte (= 1 Page) die STOP - Condition sendet, so entkoppelt sich das 
EEPROM vom I2C Bus und startet seinen internen Schreibzyklus. Während 
dieser Zeit reagiert das EEPROM nicht auf I2C - Signale... und das kann 
man sich zunutze machen für sogenanntes "ACK Polling".

Man sendet dabei eine START - Condition, gefolgt von einem AdressByte 
und wartet dananch auf das ACK vom EEPROM. Das tut man solang, bis das 
ACK tatsächlich kommt - dann ist nämlicher der interne Schreibzyklus des 
EEPROMs abgeschlossen.

Soweit zur Erklärung. Ich habe jetzt folgendes Problem: Das ACK sehe ich 
am Oszilloskop, die FW erkennt es aber nicht, zur Illustration hier noch 
das "ACK Polling" Codesegment:
1
uint8_t state = ERROR;
2
do
3
{
4
  I2C_GenerateSTART(I2C1, ENABLE);
5
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
6
  I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
7
  state = I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
8
}  
9
while(state==ERROR);

Zusammengefaßt: das ACK sehe ich am Oszilloskop, allerdings detektiert 
es die FW nicht.

Für das gleiche EEPROM habe ich schon mehrere Funktionen für I2C - 
Zugriff programmiert (auch mit ACK - Abfrage natürlich...), die jeweils 
einwandfrei funktionieren.

Mein aktueller Workaround sieht so aus, dass ich nach jedem Page - Write 
einfach 10ms warte.

Ich bitte Euch um Antworten.

Gruß, Johann
Gast #4224184
Lesenswert?

... hab ich gemacht, sieht so aus:
1
do
2
{
3
  I2C_GenerateSTART(I2C1, ENABLE);
4
  while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
5
  I2C_Send7bitAddress(I2C1, 0xA0, I2C_Direction_Transmitter);
6
  state = I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);    
7
  if (state == ERROR)
8
  {
9
    I2C_GenerateSTOP(I2C1, ENABLE);  
10
  }
11
}  
12
while(state==ERROR);

.. und bringt leider nichts.

Die anhängenden Bilder zeigen das Ganze einmal mit und einmal ohne den 
vorgeschlagenen STOP - Puls, beides funktioniert nicht.
Angehängte Dateien:
#4224188
Lesenswert?

Im Datenblatt des 24LC04 (hatte ich gerade zur Hand) steht auf Seite 8 
auch explizit ein Flußdiagramm, wo ersichtlich ist, daß da ein STOP 
nicht hineingehört.

Beim AVR geht das Ganze auf einwandfrei, nur beim STM32 (hier: 
STM32F103) will das nicht so recht. Das könnte mit dem Errata-Sheet der 
I2C-Hardware erklärt werden.
Gast #4224220
Lesenswert?

Walter T. schrieb:
> Im Datenblatt des 24LC04 (hatte ich gerade zur Hand) steht auf Seite 8
> auch explizit ein Flußdiagramm, wo ersichtlich ist, daß da ein STOP
> nicht hineingehört.

Das Datenblatt des 24LC04 kann nur sagen, was den 24LC angeht und nicht 
was den I2C Bus allgemein. Der 24LC braucht offensichtlich kein STOP. 
Aber wie willst du in der Pause zwischen deinen Polls irgendein anderes 
I2C Device ansprechen, wenn du den Bus nicht mit STOP freigegeben hast? 
Das Polling mit Auswertung des ACKs hat doch gerade den Zweck, den Bus 
nicht zu blockieren. Es reicht ja auch, beim nächsten Schreiben 
ausnahmsweise das ACK nach dem Adressbyte mal auszuwerten und das 
Schreiben solange zu verzögern, bis es kommt (oder eine Timeout "EEPROM 
kaputt" signalisiert). Dann braucht man nicht sinnlos zu pollen.

Walter T. schrieb:
> Mir fehlt auch irgendwie die Stelle, wo Du auf den Ack-Timeout wartest.

Der Master taktet das ACK selbst, da kann es kein Timeout geben.

MfG Klaus
Gast #4224233
Lesenswert?

Walter T. schrieb:
> Wieso schickst Du eigentlich immer wieder eine 7-Bit Addresse und nicht
> I2C_SendData? Im Datenblatt-Flußdiagramm will das EEPROM ein "Control
> Byte".

Weil im "Control Byte" die Adresse, gefolgt von einem R/W - Bit, 
enthalten ist... Und weil ichs mir gerade mit I2C_SendData am 
Oszilloskop angesehen habe und das am Oszilloskop gleich aussieht und 
auch der Fehler erhalten bleibt.
Gast #4224258
Lesenswert?

Peter D. schrieb:
> Nein!
> Die SDA-Leitung muß bei SCL = 1 stabil sein, sonst verletzt man die
> I2C-Spezifikation.

Was hat den das damit zu tun. Der Master darf nach jedem Byte eine 
Transaktion mit STOP abbrechen. Ein I2C EEPROM, das gerade schreibt, 
beantwortet seine Adresse nicht, stellt sich tot. Das liefert halt ein 
NAK. Mehr steckt in den tollen Begriff "ACK Polling" nicht drin.

Und so wie man jedem anderen Peripheral normalerweise nicht wartet, bis 
es endlich fertig ist, sondern beim nächsten Ansprechen schaut, ob es 
schon fertig, geht das natürlich beim EEPROM auch.

MfG Klaus
Gast #4224328
Lesenswert?

Hallo Herr Dannegger,

also die geforderte Bedingung (SDA Leitung stabil während SCL auf HIGH 
ist) ist erfüllt (siehe auch die Screenshots weiter oben).

Was mich irritiert ist, dass alle andere I2C Aktionen einwandfrei 
funktionieren; mein Verdacht ist, dass es eine "Besonderheit" auf Seite 
des STM32 ist, denn es gibt mehrere Foren, die das "ACK Polling" Problem 
betreffen, und da geht es immer um STM32 Controller, nie um andere (ist 
natürlich ein Indiz, kein Beweis).

Wie gesagt: meine aktueller Workaround ist, einfach 10ms zu warten und 
dann die nächste Page zu schreiben. Funktioniert einwandfrei, 
reproduzierbar und beliebig oft. Sollte aber dennoch mal ein EEPROM 
länger als 10ms schreiben (warum auch immer!), dann haben wir ein Gerät 
im Feld, das blockiert- nur als Hintergrund: wir gehen in einigen 
Monaten in Serie mit einigen 10.000 Geräten. Jedes Gerät hat eine 
Lebensdauer von 6 Jahren. Damit will ich sagen: jeder Fehler, der 
irgendwann auftreten könnte- der TRITT auch auf irgendwann. Daher liegt 
mir dieses Thema am Herzen.

Dennoch mal einen schönen Dank an alle Mit - Teilnehmer zu diesem Thema.
#4224336
Lesenswert?

Die I2C-Peripherie des STM32 ist gelinde gesagt eine Katastrophe.
Benutze am besten die CPAL-Library, darin sind die meisten Fehler schon 
abgefangen. Dann gibts nur noch ab und zu Probleme damit, 1-Byte-Befehle 
zu senden (also Start-Adresse-Byte-Stop), das sollte man tunlichst 
vermeiden.
Ich habe damit leider jeden Tag zu tun und seit ich alles auf CPAL 
umgerüstet habe, ist die Sache deutlich stabiler, wenn auch nicht immer 
alles perfekt läuft.
Gast #4224350
Lesenswert?

Peter D. schrieb:
> Er wollte ja auf das ACK warten und das geht nicht.

Das geht prizipiell nicht. Ich zitier mich selber:

Klaus schrieb:
> Der Master taktet das ACK selbst, da kann es kein Timeout geben.

Joey4711 schrieb:
> as mich irritiert ist, dass alle andere I2C Aktionen einwandfrei
> funktionieren; mein Verdacht ist, dass es eine "Besonderheit" auf Seite
> des STM32 ist, denn es gibt mehrere Foren, die das "ACK Polling" Problem
> betreffen, und da geht es immer um STM32 Controller, nie um andere (ist
> natürlich ein Indiz, kein Beweis).

Wenn eine gelieferte Library im Spiel ist, könnte es daran liegen. Da 
die meisten Programme, die ich hier gesehen habe, das ACK bzw NAK 
grundsätzlich nicht auswerten (andere Fehlerzustände natürlich auch 
nicht), würde ein SW-Fehler da lange unentdeckt bleiben.

MfG Klaus
#4224434
Lesenswert?

Peter D. schrieb:
> mache ich einfach das I2C in
> Software.

Das ist geschummelt! Du drückst Dich um das Tal der Tränen, das jeder, 
der die STM32-Peripherie nutzen will, durchschreiten muß. Und das 
Schlimme ist: Ich habe Deine I2C-Bitbang-Schummel-Routinen auch schon 
genutzt. Nämlich dann, wenn ich nicht sicher war, ob ein merkwürdiges 
Verhalten von der I2C-Peripherie auf der MCU oder vom angesprochenen 
Device kommt.
#4224458
Lesenswert?

Peter D. schrieb:
> Frank B. schrieb:
>> Die I2C-Peripherie des STM32 ist gelinde gesagt eine Katastrophe.
>
> Da ich keinen I2C-Interrupt verwende, mache ich einfach das I2C in
> Software. Das funktioniert immer und auf Anhieb. Und mehr Code ist es
> auch nicht.
>
> Anbei mal meine EEPROM-Lib.

Interessant und traurig zugleich, dass man heute auf einem 
hochgezüchteten Controller mit so viel Peripherie lieber Bitbanging 
benutzt.
Ich bin in meinen Programmen leider auf Interrupts angewiesen, sonst 
dreht der CAN-Bus durch, wenns mal wieder länger dauert.
#4224476
Lesenswert?

Frank B. schrieb:
> Ich bin in meinen Programmen leider auf Interrupts angewiesen, sonst
> dreht der CAN-Bus durch, wenns mal wieder länger dauert.

Ich mache CAN generell immer als Interrupt, da kann sich das Main soviel 
Zeit lassen, wie es lustig ist.
Auch kann man das I2C leicht in Scheibchen schneiden, da es keine 
Maximalzeiten kennt (ein Byte oder nur ein Bit je Maindurchlauf).
#4224485
Lesenswert?

Walter T. schrieb:
> DMA

Sag ich doch, nur im Hintergrund hat das HW-I2C Vorteile.
Allerdings lohnt sich der Aufwand nur, wenn man austesten will, nach 
wieviel Mio Schreibzyklen der EEPROM die Grätsche macht.
Nur um 0..3 mal am Tag ne neue Konfiguration abzuspeichern, aber eher 
nicht.
I2C belegt nur selten ein merkbare CPU-Last, daher wird es auch kaum als 
Interrupt implementiert.
#4224487
Lesenswert?

was der TO am Anfang beschreibt ist mir auch beim Arduino passiert, kann 
also nix mit dem STM oder der Lib zu tun haben.

Ich hatte vorher ja nur im AVR Studio gearbeitet und wusste wann ich 
eine ACK oder NACK Sequenz brauchte und konnte das manuell einpflegen.

Am Arduno Fehlanzeige, solange ich "nur" einen PCF85574(A) befrage oder 
nur ein DS3231 Register abhole kein Problem.

Am Arduino wurde das I2C EEPROM in allen Listings immer mit delay(5) 
gelöst, für mich unhaltbar auf jede Zelle 5ms zu warten was bei Block 
write auch schiefgehen kann wenn das EEPROM 6ms braucht.

Ich überlegte doch glatt für 10µs mit einem anderen Port den Zustand 
abzufragen nach einer write Sequenz und fand dann aber das 
"Prüfkommando", einfach neues Read nach write in einer Schleife zu 
starten und wenn das fehlerfrei klappte ohne ERROR war das I2C EEPROM 
wieder bereit. Beim purren EEPROM hatte ich früher ja das busy Bit 
befragen können, nun eben wenn das EEPROM sich wieder meldet.

Klaus schrieb:
> Wenn eine gelieferte Library im Spiel ist, könnte es daran liegen. Da
> die meisten Programme, die ich hier gesehen habe, das ACK bzw NAK
> grundsätzlich nicht auswerten

das hat doch nix mit auswerten zu tun, oder verstehe ich was falsch?

Ich will 2 Bytes empfangen und das erste wird mit ACK quittiert, das 2te 
und letzte mit NACK

genauso bei einer Kette von 10 Byte, 9x ACK das letzte mit NACK

Wie soll man das machen wenn man einen Block per LIB schickt, dort 
müsste das letzte Byte ja in der LIB per NACK verarbeitet werden, aber 
wenn I2C stretching auftritt weiss ich nie wann, ergo delay oder Port 
beobachten oder prüfen wann das IC wieder mit mir redet.
1
// P. Fleury war so nett eine LIB zu bauen 
2
// Auschnitt:
3
i2c_start_wait(DS3231+I2C_WRITE);  // set device address and write mode
4
i2c_write(DS3231_ControlReg);
5
i2c_rep_start(DS3231+I2C_READ);     // set device address and read mode
6
control=i2c_readAck();
7
status=i2c_readNak();
8
i2c_stop();


also so nach write und nach write block
1
do {
2
Wire.beginTransmission(_address); Wire.requestFrom(_address, 1);
3
_data = readIIC();
4
_error = Wire.endTransmission();
5
}while(_error);

kann ja mit einem timeout erweitert werden
Gast #4224508
Lesenswert?

Joachim B. schrieb:
> Klaus schrieb:
>> Wenn eine gelieferte Library im Spiel ist, könnte es daran liegen. Da
>> die meisten Programme, die ich hier gesehen habe, das ACK bzw NAK
>> grundsätzlich nicht auswerten
>
> das hat doch nix mit auswerten zu tun, oder verstehe ich was falsch?

Wenn die Lib buggy ist und sich nie jemand um ACK bzw NAK kümmert, merkt 
das kein Mensch. Das war gemeint.

Auch die Funktionen der  P. Fleury Lib haben Returnwerte und auch in 
deinem Code sehe ich nichts, was sie auswertet. Obwohl ich es da für 
unwahrscheinlich halte, das die Lib buggy ist.

Joachim B. schrieb:
> Wie soll man das machen wenn man einen Block per LIB schickt, dort
> müsste das letzte Byte ja in der LIB per NACK verarbeitet werden,

Eine Blockfunktion sollte einen brauchbaren Returnwert haben so z.B.

- cannot set START, Bus not idle
- no ACK at address Byte, operation with STOP aborted
- no ACK at data Byte ...
.
.

Joachim B. schrieb:
> fand dann aber das
> "Prüfkommando", einfach neues Read nach write in einer Schleife zu
> starten und wenn das fehlerfrei klappte

Damit hast du gerade das "ACK polling" erfunden. Wobei es geschickter 
ist, mit R/W = 0 zu pollen und danach mit STOP abzubrechen. Ganz ganz 
dumme Slaves erwarten nach einem Read mindestens 9 Clockpulse, bevor sie 
den Bus wieder frei geben.

MfG Klaus
#4224523
Lesenswert?

Klaus schrieb:
> Damit hast du gerade das "ACK polling" erfunden.

ich war es nicht, aber danke für diesen Hinweis:

Klaus schrieb:
> mit R/W = 0 zu pollen

Mich wunderte nur das dies so schwer zu finden war und warum fast alle 
ein delay nach I2C EEPROM write setzen, klar es geht aber elegant ist 
anders.

Klaus schrieb:
> Wobei es geschickter
> ist danach mit STOP abzubrechen.

macht das nicht?

Wire.endTransmission();
#4224630
Lesenswert?

Klaus schrieb:
> Auch die Funktionen der  P. Fleury Lib haben Returnwerte und auch in
> deinem Code sehe ich nichts, was sie auswertet. Obwohl ich es da für
> unwahrscheinlich halte, das die Lib buggy ist.

ich weiss, da kürze ich Schlamper gerne ab, mal aus Bequemlichkeit, mal 
aus Platznot, rate mal warum ich den Arduino mighty atmega1284p so mag?

buggy ist P.Fleurys LIB definitiv nicht, sie sogar sauber und leicht 
verständlich.
#4225401
Lesenswert?

Peter D. schrieb:
> Frank B. schrieb:
>> Ich bin in meinen Programmen leider auf Interrupts angewiesen, sonst
>> dreht der CAN-Bus durch, wenns mal wieder länger dauert.
>
> Ich mache CAN generell immer als Interrupt, da kann sich das Main soviel
> Zeit lassen, wie es lustig ist.

Schon klar, ich habe noch ein CANopen-Protokoll zeitnah auszuwerten, 
denn der HBC ärgert sich, wenn die Antwortzeiten zu lang werden...
#4226128
Lesenswert?

Frank B. schrieb:
> Die I2C-Peripherie des STM32 ist gelinde gesagt eine Katastrophe.

Ich bin auch nicht mit dem I2C der AVRs zufrieden, das hängt sich als 
Multimaster ständig auf, man braucht einen Timeouthandler, der es 
rücksetzt. Das gleiche auch bei den Atmel 8051.

Richtig zuverlässig hat bei mir nur das I2C der original Philips P80C652 
funktioniert, das braucht keine Überwachung mit Timeout. Einmal enablen 
und es läuft und läuft und ...
Gast #4226167
Lesenswert?

Walter T. schrieb:
> Funktioniert das "acknoledge polling" jetzt eigentlich mit den
> bitbanging-Routinen?

Irgendwie scheinst du noch nicht verstanden zu haben, worum es beim "ACK 
polling" wirklich geht.

Ein I2C Slave muß auf seine Adresse nach START mit ACK reagieren. Ein 
EEPROM stellt sich aber tot, wenn es mit Schreiben beschäftigt ist. Es 
antwortet nicht, das heißt der Master liest ein NAK vom Bus. Ein sauber 
programmierter Master beendet dann die Übertragung mit einem STOP. Erst 
wenn es mit Schreiben fertig ist, liefert das EEPROM wieder ein ACK auf 
seine Adresse. Die Funktionen START anlegen, Adresse senden und dabei 
ACK/NAK einlesen, STOP erzeugen etc sind die Grundfuktionen von I2C. Ob 
diese von einer HW oder einer SW erzeugt werden, ist unerheblich.

MfG Klaus
#4226195
Lesenswert?

Zur Information,

Ich Verwende schon seit einigen Jahren mit guten Erfolg die "Optimized 
I2C library". Die funktioniert einwandfrei und hatte noch nie Probleme 
damit. Kann ich nur wärmstens empfehlen. Die lässt sich auch mit 
interrupt, gepollt, und mit DMA konfigurieren.

Diese Library verwendet die I2C hardware ohne irgendwelche Probleme. 
auch ACK polling funktioniert richtig.

Die Beschreibung der I2C Hardware im User Manual ist meiner Meinung nach 
aber eher suboptimal. Da tut man sich schwer die Idiosynkrasien der I2C 
Hardware genügend zu verstehen. Auch sind die Errata darüber recht 
voluminös.

Hatte mit keinem der getesteten EEPROMS irgendwelche Probleme.

Lese mal die AN2824 zum Überblick durch.

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fUsing%20STM32%20Optimized%20I2C%20examples%20when%20two%20I2C%20devices%20connected%20to%20one%20I2C%20port&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=8277

Für mich ist sie jedenfalls jetzt meine Standard I2C Library auf die man 
sich verlassen kann.

Vorher verwendete ich eine eigene soft Lib ähnlich wie die von PD. Hat 
auch gut funktioniert.

Gruß,
Gerhard
Gast #4379964
Lesenswert?

Klaus schrieb:
> Irgendwie scheinst du noch nicht verstanden zu haben, worum es beim "ACK
> polling" wirklich geht.

Ich hol das mal wieder hoch, weil ich JETZT GERADE vor dem genau 
gleichen Problem stehe bei einem 64k E2PROM das ACK zu pollen, während 
das E2PROM gerade  ein Byte wegschreibt. Das muss doch irgendwie gehen, 
meine Routinen funktionieren auch.

Bloss das hier nicht, was ich mir aus den Finger gesogen habe, wie es 
gehen könnte. Tut es aber nicht :-(
1
// Polling, bis E2PROM das Byte weggeschrieben hat
2
        uint cnt = 0;
3
        do {
4
            I2C_GenerateSTART(I2C3, ENABLE);
5
            I2C_Send7bitAddress(I2C3, MEM_DEVICE_WRITE_ADDR, I2C_Direction_Transmitter);
6
            /* Test on I2C3 EV6 and clear it */
7
            timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
8
            while(!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
9
            {
10
                /* If the timeout delay is exeeded, exit with error code */
11
                if ((timeout--) == 0) return 0xFF;
12
            }
13
            cnt++;
14
        } while (I2C_CheckEvent(I2C3, I2C_EVENT_SLAVE_ACK_FAILURE));

Ist das überhaupt das richtige Event? I2C_EVENT_SLAVE_ACK_FAILURE

Mama..... ich will meinen Arduino wiederhaben.....das klappte da alles 
:-(
#4380189
Lesenswert?

Christian J. schrieb:
> Bloss das hier nicht, was ich mir aus den Finger gesogen habe, wie es
> gehen könnte. Tut es aber nicht :-(

Kein Wunder, Du ignorierst ja standhaft die Beispiele, bzw. die 
I2C-Beschreibung im Datenblatt des EEPROM.

ACK-Polling heißt, Du sendest Start+Adresse+Stop in einer Schleife und 
prüfst das ACK auf die Adresse.
Diese Schleife hast Du nicht, also kanns nicht gehen.
#4380206
Lesenswert?

Peter D. schrieb:
> Kein Wunder, Du ignorierst ja standhaft die Beispiele, bzw. die
> I2C-Beschreibung im Datenblatt des EEPROM.
>
> ACK-Polling heißt, Du sendest Start+Adresse+Stop in einer Schleife und
> prüfst das ACK auf die Adresse.
> Diese Schleife hast Du nicht, also kanns nicht gehen.

Christian J. schrieb:
> das ACK zu pollen, während
> das E2PROM gerade  ein Byte wegschreibt. Das muss doch irgendwie gehen,
> meine Routinen funktionieren auch.

ich hatte ja hier beschrieben wie es geht:
Beitrag "Re: I2C Problem mit Acknowledge Polling"

das sollte auch anderswo klappen:

Joachim B. schrieb:
> also so nach write und nach write block
> do {
> Wire.beginTransmission(_address); Wire.requestFrom(_address, 1);
> _data = readIIC();
> _error = Wire.endTransmission();
> }while(_error);
Gast #4380344
Lesenswert?

Ok,

trotzdem wäre es nett, wenn jemand eine fertige Routine hätte, welches 
Bit da wo geprüft wird, welches Eventflag zuständig ist usw.

>> bis er sich wieder meldet,

Dazu müsste ich erstmal wissen, welche Funktion der StdPeriphLib mir 
mitteilt, dass er sich gemeldet hat.... das I2C Modul hat mehr als
hundert Config und Flag Bits. Das Prinzip ist mir klar, es geht nur um
die Codierung für diespen speziellen Prozessor mit einer speziellen
HAL.

Der Code oben ist komplett, er sendet Start und Schreibadresse, wartet 
bis diese raus sind. Ok, vielleicht fehlt noch ein Stop.

I2C_CheckEvent(I2C3, I2C_EVENT_SLAVE_ACK_FAILURE)); ???
#4380374
Lesenswert?

@peda
Wenn ich mir ein IC aussuche, dann achte ich darauf, dass es keines mit 
I2C-Interface ist. Mit anderen Worten: I2C ist nicht so mein Gebiet.

Bei Deinem Kod ist mir aber aufgefallen, dass Du nirgends 
Clock-Stretching in Betracht gezogen hast. Habe ich in Deinem Kod etwas 
übersehen? Oder ist das nicht so wichtig?
Gast #4380435
Lesenswert?

Peter D. schrieb:
> Das alles sollte aber doch im Manual zu Deiner Lib umfassend beschrieben
> sein.

Peter, diese Lib schreibe ich gerade. Alle bisher gefundenen Libs haben 
E2Proms nicht auf dem Radar oder da steht einfach Delay(5ms) hinter 
jedem Byte was ja nicht Sinn der Sache sein kann. Und ACK Polling ist in 
keinem Beispiel zu finden bzw. sehe ich es wohl nicht. Das braucht man 
auch beim Page Write, es sei denn man will 10ms warten, obwohl es 
vielleicht auch nur 5ms sind.
#4380475
Lesenswert?

Christian J. schrieb:
> Alle bisher gefundenen Libs haben
> E2Proms nicht auf dem Radar

Darum geht es nicht, sondern um die Lib für die I2C Basisfunktionen.
Und die I2C-Write Funktion muß zurückliefern, ob sie vom Slave ACK oder 
NACK empfangen hat.
Erst dann kann man sich aus den Basisfunktionen eine EEPROM-Lib bauen.
Schau Dir mal mein Beispiel an:
Beitrag "Re: I2C Problem mit Acknowledge Polling"
Gast #4380483
Lesenswert?

Tja, siehst Du da was, was so ausschaut? Das ist nur Einzelbyte 
Schreiben.....
1
uint8_t Write_24Cxx(uint16_t Addr, uint8_t Data, uint8_t Mem_Type)
2
    {
3
     
4
      uint32_t timeout = I2C_TIMEOUT_MAX;
5
      uint8_t upper_addr,lower_addr;
6
     
7
      lower_addr = (uint8_t)((0x00FF)&Addr);
8
     
9
      if(Mem_Type==M24512)
10
      {
11
      Addr = Addr>>8;
12
      upper_addr = (uint8_t)((0x00FF)&Addr);
13
            }
14
           /* Generate the Start Condition */
15
           I2C_GenerateSTART(I2C1, ENABLE);
16
     
17
           /* Test on I2C1 EV5, Start trnsmitted successfully and clear it */
18
           timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
19
           while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
20
           {
21
                /* If the timeout delay is exeeded, exit with error code */
22
        if ((timeout--) == 0) return 0xFF;
23
           }
24
     
25
           /* Send Memory device slave Address for write */
26
           I2C_Send7bitAddress(I2C1, MEM_DEVICE_WRITE_ADDR, I2C_Direction_Transmitter);
27
     
28
           /* Test on I2C1 EV6 and clear it */
29
           timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
30
           while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
31
           {
32
               /* If the timeout delay is exeeded, exit with error code */
33
        if ((timeout--) == 0) return 0xFF;
34
           }
35
     
36
      if(Mem_Type==M24512)
37
      {
38
        /* Send I2C1 location address LSB */
39
        I2C_SendData(I2C1, upper_addr);
40
     
41
        /* Test on I2C1 EV8 and clear it */
42
        timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
43
        while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
44
        {
45
          /* If the timeout delay is exeeded, exit with error code */
46
          if ((timeout--) == 0) return 0xFF;
47
        }
48
      }
49
      /* Send I2C1 location address LSB */
50
            I2C_SendData(I2C1, lower_addr);
51
     
52
          /* Test on I2C1 EV8 and clear it */
53
          timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
54
          while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
55
          {
56
                /* If the timeout delay is exeeded, exit with error code */
57
        if ((timeout--) == 0) return 0xFF;
58
          }
59
     
60
           /* Send Data */
61
           I2C_SendData(I2C1, Data);
62
     
63
            /* Test on I2C1 EV8 and clear it */
64
            timeout = I2C_TIMEOUT_MAX; /* Initialize timeout value */
65
            while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
66
            {
67
                 /* If the timeout delay is exeeded, exit with error code */
68
        if ((timeout--) == 0) return 0xFF;
69
            }  
70
     
71
            /* Send I2C1 STOP Condition */
72
            I2C_GenerateSTOP(I2C1, ENABLE);
73
     
74
            /* If operation is OK, return 0 */
75
            return 0;
76
    }
#4380502
Lesenswert?

Christian J. schrieb:
> Und ACK Polling ist in
> keinem Beispiel zu finden bzw. sehe ich es wohl nicht. Das braucht man
> auch beim Page Write, es sei denn man will 10ms warten, obwohl es
> vielleicht auch nur 5ms sind.

deswegen habe ich ja die Arduino Routine erweitert, alle I2C EEPROM LIB 
die ich fand wartete immer 5-10ms, das kann nicht sinnvoll sein, mit dem 
polling ist es viel schneller.
#4380645
Lesenswert?

Christian J. schrieb:
> Tja, siehst Du da was, was so ausschaut?

Weil Du das ACK-Polling nicht verstanden hast. Nirgends wird auf ACK 
geprüft und das ist zwingend notwendig!

Wie das ACK/NACK vom I2C_CheckEvent() geliefert werden kann weißt nur Du 
nach dem Lesen der Doku zu Deiner I2C-Lib. Ich kenne Deine Lib ja nicht.

Hier nochmal das ACK-Polling Pseudocode:
1
  while( 1 ){
2
    I2C_start();
3
    I2C_write(adresse);
4
    if( I2C_status == ACK )
5
      break;
6
    I2C_stop();
7
  };
#4380720
Lesenswert?

Joachim B. schrieb:
> muss man nich auch auf NACK abfragen wenn nur ein Byte gelesen werden
> soll?

Beim Lesen dreht sich die Datenrichtung um, d.h. der Master liest das 
Byte und sendet das ACK.
Das ACK zeigt dem Slave an, daß der Master noch weitere Bytes lesen 
will.
Nach dem letzten Byte muß daher der Master ein NACK senden, ansonsten 
kann das STOP fehlschlagen.
In meiner EEPROM-Lib ist das entsprechend implementiert:
1
    *sram++ = si2c_r( !--len );                         // NACK on last byte
Gast #4381242
Lesenswert?

Peter D. schrieb:
> Wie das ACK/NACK vom I2C_CheckEvent() geliefert werden kann weißt nur Du
> nach dem Lesen der Doku zu Deiner I2C-Lib. Ich kenne Deine Lib ja nicht.

Peter..... nochmal: Es gibt keine Lib! Ich schreibe die Funktionen 
gerade. Weil ich mich in vieles eingelesen habe und feststelle, dass die 
allermeisten Libs aus dem Netz, die halbwegs lesbar sind und nicht nur 
aus einem Wust Registerzugriffen bestehen sehr "dürftig" sind. Nämlich 
meist überhaupt keine Fehlerbehandlung haben, auch kein ACK des Slaves 
prüfen bei Schreiben usw. Ok, was soll man auch machen, wenn was 
schiefgeht? Reparieren kann es die CPU ja nicht.

Ich habe jedenfalls aufgegeben sowas simples wie das ACK zu ckecken für 
die StdPeriphLibs des STM32. Ohne deren genaue Funktion zu kennen hat 
das keinen Sinn und die .chm Datei die es nur noch als Hilfe gibt funzt 
bei mir nicht.
#4381750
Lesenswert?

Christian J. schrieb:
> Peter..... nochmal: Es gibt keine Lib!
...
> Ich habe jedenfalls aufgegeben sowas simples wie das ACK zu ckecken

Warum?
Da Du den konkreten Typ nicht nennst, habe ich mal ins STM32F303 
Reference Manual geschaut:
1
28.7.7 Interrupt and status register (I2C_ISR)
2

3
Bit 4 NACKF: Not Acknowledge received flag
4
This flag is set by hardware when a NACK is received after a byte transmission. It is cleared by
5
software by setting the NACKCF bit.
6
Note: This bit is cleared by hardware when PE=0.

Was ist so schwer daran, dieses Bit zu lesen?
Gast #4381906
Lesenswert?

Peter D. schrieb:
> This flag is set by hardware when a NACK is received after a byte
> transmission.

Ja, das gilt aber nur für den Slave Betrieb. Die zugehörige Lib Funktion 
heisst I2C_Event(I2Cx, I2C_EVENT_SLAVE_ACK_FAILS), die aber nicht 
funktioniert da ich damit schon alle Variationen ausprobiert habe.

Der Master sendet ja NAK und danach STOP, wenn er keine weiteren Bytes 
lesen will, damit der Slave weiss, dass Ende ist.

Leider ist das Ganze schwer zu debuggen, da zeitkritisch.

Ich lass das erstmal ruhen, bis ich mich besser in die StdPeriphLib 
eingearbeitet habe.
#4381963
Lesenswert?

Christian J. schrieb:
> Ja, das gilt aber nur für den Slave Betrieb.

Nö:
1
Master transmitter
2
In the case of a write transfer, the TXIS flag is set after each byte transmission, after the 9th
3
SCL pulse when an ACK is received.
4
...
5
If a NACK is received: the TXIS flag is not set, and a STOP condition is automatically
6
sent after the NACK reception. the NACKF flag is set in the I2C_ISR register, and an
7
interrupt is generated if the NACKIE bit is set.
Gast #4381970
Lesenswert?

Evtl ist das beim 407 anders, der hat dieses Bit nicht aber

Acknowledge failure (AF)
This error occurs when the interface detects a nonacknowledge bit. In 
this case:
• the AF bit is set and an interrupt is generated if the ITERREN bit is 
set
• a transmitter which receives a NACK must reset the communication:
– If Slave: lines are released by hardware
– If Master: a Stop or repeated Start condition must be generated by 
software
Gast #4382856
Lesenswert?

Kurz die Auflösung für nachfolgende Generationen:

Ob ein EEPROM seinen Schreibzyklus beendet hat findet man mit folgender 
Sequenz bei einem STM32F4xx heraus (Timeout noch nicht drin). Nach ca 
3-4 Durchläufen kommt das ACK, alles drüber ist Timeout.
1
 // Warte bis Byte weggeschrieben wurde (Slave sendet solange kein ACK)
2
        do{
3
            I2C_GenerateSTART(I2C3, ENABLE);
4
            while(!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_MODE_SELECT));
5
            I2C_Send7bitAddress(I2C3, MEM_DEVICE_WRITE_ADDR, I2C_Direction_Transmitter);
6

7
        } while(I2C_WaitForByteTransmitted(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)!=0);

weil ich endlich im Header diesen Abschnitt fand.
Address Acknowledge
  *
  * After checking on EV5 (start condition correctly released on the 
bus), the
  * master sends the address of the slave(s) with which it will 
communicate
  * (I2C_Send7bitAddress() function, it also determines the direction of 
the communication:
  * Master transmitter or Receiver). Then the master has to wait that a 
slave acknowledges
  * his address. If an acknowledge is sent on the bus, one of the 
following events will
  * be set:
  *
  *  1) In case of Master Receiver (7-bit addressing): the 
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED
  *     event is set.
  *
  *  2) In case of Master Transmitter (7-bit addressing): the 
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
  *     is set
#4383380
Lesenswert?

Christian J. schrieb:
> Nach ca
> 3-4 Durchläufen kommt das ACK, alles drüber ist Timeout.

So wenige? Dann hast Du aber den Timeout sehr hoch gesetzt.
Da der EEPROM kein Clock-Stretching macht, sollte ein Timeout = 0 
reichen.

Christian J. schrieb:
> weil ich endlich im Header diesen Abschnitt fand.

Also benutzt Du doch eine fertige Lib. Und zu dieser gibt es wirklich 
keine Doku?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren