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
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
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
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
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.
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