i2C bleibt hängen

Gast #5178220
Lesenswert?

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
#5178281
Lesenswert?

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.
Gast #5178285
Lesenswert?

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 ?
Gast #5178306
Lesenswert?

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.
Gast #5178326
Lesenswert?

@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 ?!
Gast #5178329
Lesenswert?

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.
Gast #5178350
Lesenswert?

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.
Gast #5178383
Lesenswert?

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
Gast #5178413
Lesenswert?

... 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.
#5178546
Lesenswert?

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
Gast #5179008
Lesenswert?

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...
Gast #5179173
Lesenswert?

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"
Gast #5181454
Lesenswert?

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.
Gast #5181520
Lesenswert?

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.
Gast #5182380
Lesenswert?

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

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