Hallo Habe einen AVR Mega8 und habe Probleme mit den i2c Bus Verwende die Lib von Peter Fleury Verwendete zuerst die Software Version und jetzt bin ich auf die TWI Version umgestiegen.. Bei der Software Version funktionierte alles aber bei der TWI Version hängt sich der AVR manchmal auf. Manchmal läuft es Stunden lange (Zugriff auf i2c, alle Minuten) und manchmal hängt sich das Programm nach einer Stunde auf. Da es vorher mit Software i2c funktionierte und erst nach dem Umstieg auf TWI, Probleme gibt, vermute ich jetzt, dass es in der TWI-Lib hängt. Leider tritt der Fehler unregelmäßig auf. Habe versucht die TWI-Lib zu verstehen, aber als relativer Anfänger, versteh ich nicht alles.. Versuche jetzt in der Lib, nacheinander , bei jeder Anweisung zuerst eine Led einzuschalten und am Ende wieder ausschalten zu lassen, um so drauf zukommen, in welchen Bereich die Lib hängen bleibt.. Vermute, das die Lib in irgendeiner "While" oder "IF" Abfrage hängen bleibt, weil es vielleicht Daten Aussätzer gibt.?! Habe auch schon das Forum danach durchsucht aber nicht viel gefunden.. Mir schwebt da vor, in der Lib irgendwie einen Time Out einzubauen, falls er zu lange in einer Abfrage hängt... Hat jemand schon mal so ein Problem gehabt ? Tips ? Muss mir noch das i2C Signal genauer ansehen. Eventuell pull up R anpassen, aber die Lib dürfte trotzdem nicht hängenbleiben, auch wenn das Signal nicht passt... Hat jemand bitte einen Tip ? Danke l.G. Robert
Robert schrieb: > Hat jemand bitte einen Tip ? Ja! Robert schrieb: > Muss mir noch das i2C Signal genauer ansehen. Eventuell pull up R > anpassen, Mache da Fakten draus! Das wäre ein wichtiger Schritt.
Wenn man keine riesen I2C-Datenmengen hat und das I2C nicht im Hintergrund als Interrupt laufen muß, hat das HW-I2C als single-Master nur Nachteile. Es ist weder schneller noch weniger Code, sondern nur störanfälliger. Störungen auf den I2C-Leitungen können dazu führen, daß das HW-I2C den Bus als belegt erkennt oder die Arbitration verliert. Ohne Timeout mit I2C-Disable kommt es da nicht wieder raus. Und falls das passiert, während ein Slave adressiert wurde, kann dieser SDA auf low ziehen, was das HW-I2C dauerhaft blockiert. Nur ein SW-I2C kann unabhägig von SDA Takte auf SCL erzeugen, bis der Slave wieder frei ist.
mmh.. derzeit 10k pull up, eventuel auf 5k runter gehen.. Aber bei 50kHz i2C, sollte das auch kein Problem sein.. Aber das Programm dürfte nicht hängenbleiben, egal ob Signal schlecht oder gut... Welche Fakten brauchst du noch ?
Robert schrieb: > Aber das Programm dürfte nicht hängenbleiben, egal ob Signal schlecht > oder gut... Wenn sich die TWI-Hardware verheddert, hat die Software wenig Chancen. Das lässt sich zwar alles irgendwie mit Timeouts abfangen und absichern, aber da kannst du dann auch gleich Software-I2C einsetzen. Oliver
:
Bearbeitet durch User
Robert schrieb: > Welche Fakten brauchst du noch ? Ich brauche keine Fakten.... Du brauchst welche. Denn so kommst du zu machtvollen Urteilen. Vermutungen und "was wäre wenn", helfen da nicht. Mein Vorgehen, bei I2C Problemen: 1. Signalform ok? (oszi) 2. Signalanalyse (LA) Dann weiß man ob einer der Partner den Bus niederhält. Mit einem Serienwiderstand, kann man auch raus finden, welcher der beiden das ist. Robert schrieb: > Verwende die Lib von Peter Fleury Die kenne ich nicht (nur aus der Ferne) Ausschließen, dass das ein Software Fehler ist, kann ich nicht. Aber das sieht man bei der Analyse des Busses.
@Arduino Fanboy Ja, mit Osci muss ich noch schauen.. (Flanken) Mit dem LA habe ich die Woche lang, Messungen gemacht.. Leider tritt der Fehler nur selten auf.. :-( Braucht oft Stunden... Habe mit dem LA nur gemerkt, dass nach dem Aufhängen des Busses die Pegel verschieden sind... Manchmal beide auf High, manchmal unterschiedlich... (hoffte auf einen Fehler in der Clock-Leitung) -- Danke für die anderen Kommentare Peter, usw... Scheint also doch nicht so selten zu sein, dass der Bus hängen bleiben kann.. Wenn ich einen Timeout in der Lib einbauen würde, muss ich da etwas beachten ?! Bestimmte Register zurücksetzen? oder nur normal mit Return (Break) aufsteigen ?!
Robert schrieb: > Hat jemand schon mal so ein Problem gehabt? Massig. i2c-Probleme gibt es hier im Forum relativ oft. Wie ober bereits vorgeschlagen, stell auf sw-i2c um. Wenn es dir um das Verständnis von i2c geht, klappt das mit sebst erstellter i2c software am besten.
Ich wundere mich etwas über die SoftI2C Predigten.... OK, ich kenne nur meine kleine Arduino AVR I2C Welt. Da funktioniert das allerdings prächtig. Nix Ausfälle alle Stunde, oder so. Und das ist nicht SoftI2C, sondern nutzt die TWI Hardware. Solange nicht mehr, als 2 AVR Master, sich die Spielwiese teilen müssen, tuts das.
Hi >> Hat jemand schon mal so ein Problem gehabt? >Massig. i2c-Probleme gibt es hier im Forum relativ oft. Hä? Wir setzen schon seit fast 20 Jahren HW- bzw. SW-I2C ein. Das läuft beides sehr zuverlässig. Allerdings beides mit eigenen Routinen. MfG spess
Robert schrieb: > mmh.. derzeit 10k pull up 10k sind schon heftig. Typischerweise sollten da eher 1k5 drin sitzen.
Gu. F. schrieb: > Typischerweise sollten da eher 1k5 drin sitzen. ? Peter Fleury empfiehlt 4k7 Ich halte das bei Vcc=5V schon für einen guten Ausgangspunkt. Aber vielleicht haben wir es ja hier mit 2m Kabel (und dann auch noch im Auto) zu tun.
... und keiner spricht hier wieder vom Aufbau der ja immer soooooo gut ist dass darüber auf keinen Fall gesprochen werden muss und darf. Ja, der Aufbau ist mehr als nur zwei Pullup-Widerstände.
Hi >Peter Fleury empfiehlt 4k7 Interessiert eigentlich den Gasmann. Dafür gibt es offizielle Dokumente: UM10204: https://www.nxp.com/docs/en/user-guide/UM10204.pdf MfG Spess
Hi Wer ist denn der Gegenspieler Deines µC? Liest sich so, daß Dieser ein Timing-Problem bekommt und dann eben Nichts mehr geht. Der Slave wartet auf eine Aktion des Master, der Master wartet auf das letzte Bit vom Slave oder irgend so ein Müll. Wenn DU am µC noch ein Pin und etwas Speicher frei hast, kannst Du ja ein LCD anschließen, Welches Dir einen Status anzeigt, in Dem sich der µC gerade befindet (LEDs gingen auch, das LCD kann aber 'Mehr' anzeigen und ist verständlicher). Die Pegel des Bus kannst Du beim Hänger ja extern erfassen - wenn SDA auf LOW gezogen wird, hat wohl der Slave ein Problem, bei SCK der Master (da Er der Einzige ist, Der an SCK spielen darf) - oder ist der Gegenspieler ebenfalls Master?? MfG
Um den Fehler öfters zu provozieren kannst du auch öfters lesen. Vorschlag: 1000 mal lesen/schreiben, 500ms Pause und wieder von vorn.
Also wenn Lego 82k Ohm Pull-Ups verwendet (was ich nicht tun würde), dann können 10k nicht völlig falsch sein, oder?
Hi Scheinbar liegt es an der lese Routine der Lib /*********************************************************************** ** Read one byte from the I2C device, request more data from device Return: byte read from I2C device ************************************************************************ */ unsigned char i2c_readAck(void) { TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); while(!(TWCR & (1<<TWINT))); return TWDR; }/* i2c_readAck */ /*********************************************************************** ** Read one byte from the I2C device, read is followed by a stop condition Return: byte read from I2C device ************************************************************************ */ unsigned char i2c_readNak(void) { TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))); return TWDR; }/* i2c_readNak */ ------------------------ Wenn hier kein Slave dran ist, oder es Störungen gibt, hängt er sich wohl in dieser Routine auf bzw. wartet endlos :-( Schreiben geht immer... (Ist nur Master und 1 (2) Slave) Mit SW-i2c ging das immer. Könnte jetzt immer Abfragen, ob ein Slave da ist, aber bei einer Störung oder wenn der Slave spinnt, ist dann wieder das gleiche...
Stefan U. schrieb: > Also wenn Lego 82k Ohm Pull-Ups verwendet (was ich nicht tun würde), > dann können 10k nicht völlig falsch sein, oder? Spess hat doch schon auf die Spec verlinkt. Warum also nicht gleich richtig machen?
Gu. F. schrieb: > Spess hat doch schon auf die Spec verlinkt. Bei LEDs wird hier im Forum scheinbar immer der Maximalstrom angesetzt, bei den I2C Pullups immer der Minimalwiderstand. An der Achse steht Rp(min), kleiner ist zwar nicht unbedingt kaputt aber außerhalb der Spec. > Warum also nicht gleich richtig machen? Richtig heißt also immer größer als in diesem Bild gezeigt, ein Wert für den Maximalwert ist da nicht gezeigt. MfG Klaus PS. Die typische Antwort hier im Forum auf den Ratschlag: "mach die Pullups kleiner" ist "hat nichts gebracht"
Robert schrieb: > Mit SW-i2c ging das immer. Dann bleib doch dabei. Die gezeigte Hardware-Lösung pollt ja auch nur stumpf das Statusbit, und bringt damit keinerlei Vorteile. Oliver
Robert schrieb: > Scheinbar liegt es an der lese Routine der Lib while(!(TWCR & (1<<TWINT))); setz halt einen Timeout ein. Hatten wir die Tage schon mal.
1 | u32 downtimer=200000; |
2 | while((TWCR & (1<<TWINT)) && downtimer)downtimer--; |
3 | if (!downtimer)return; |
Hi >Dann bleib doch dabei. Die gezeigte Hardware-Lösung pollt ja auch nur >stumpf das Statusbit, und bringt damit keinerlei Vorteile. Wenn man sich das Beispiel aus dem Datenblatt ansieht, dann fehlt bei den hier Beitrag "Re: i2C bleibt hängen" die Behandlung der Fehler. MfG Spess
Robert schrieb: > enn hier kein Slave dran ist, oder es Störungen gibt, hängt er sich > wohl in dieser Routine auf Nachtrag: Was soll er bei dieser Routine denn sonst machen als sich aufhängen wenn kein slave dran ist???
Hallo @grundschüler danke für den Tip :-) gibt den Beitrag hier: Beitrag "Timeout bei serieller abfrage" Habe das aber ein bisschen anders gelöst: --------- */ unsigned char i2c_readNak(void) { uint32_t downtimer = 25000; TWCR = (1<<TWINT) | (1<<TWEN); while(!(TWCR & (1<<TWINT))) { if downtimer <1) return 0; downtimer--; } return TWDR; }/* i2c_readNak */ ----------- Wie das Beispiel in dem Link funktionieren soll, ist mir zwar nicht ganz klar, aber damit habe ich dann meine Lösung gebastelt.. Mit dem 8MHz Takt und mit einem downtimer Wert von 25000, bekomme ich eine Timeout von ca. 0,1 Sekunden.
Robert schrieb: > while(!(TWCR & (1<<TWINT))) > { > if downtimer <1) return 0; > downtimer--; > } das ist im Prinzip identisch mit while(!(TWCR & (1<<TWINT)) && !downtimer ) { downtimer--; } Die Bedingung "downtimer ergibt 0" wird nur in der while-Bedingung statt bei dir als separate Bedingung abgearbeitet. if downtimer <1) return 0; => hier sollte nicht 0 sondern ein Fehlerwert zurückgegeben werden.
Hallo Ich versuche gerade das Nack vorher abzufangen, befor es überhaupt zum i2c_read.. kommt. Habe mir dazu folgendes gebastelt (für die Lib von Peter Fleury) --------------------------------------------------- unsigned char test[1]; uint8_t Daten1, daten2; ------------- i2c_Start (0x50); test[1] = i2c_write (0x10); if (test[1] ==1) { i2c_stop(); springe raus--> } i2c_rep_start (0x51); Daten1 = i2c_readAck(); Daten2 = i2c_readNak(); i2c_stop(); ------------------------------------------------------ Link zur Lib ist hier: http://homepage.hispeed.ch/peterfleury/i2cmaster.zip Mein Code funktioniert ganz gut, schaut aber ein bisschen aufwendig aus. Kann man das irgendwie besser(einfacher) machen ? Danke für Tips :-) l.G. Robert
> Mein Code funktioniert ganz gut...
Solange, bis an test[1] eine andere Variable liegt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.