Forum: Mikrocontroller und Digitale Elektronik i2C bleibt hängen


von Robert (Gast)


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

von Einer K. (Gast)


Lesenswert?

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.

von Peter D. (peda)


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.

von Robert (Gast)


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 ?

von Oliver S. (oliverso)


Lesenswert?

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
von Einer K. (Gast)


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.

von Robert (Gast)


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 ?!

von grundschüler (Gast)


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.

von Einer K. (Gast)


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.

von spess53 (Gast)


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

von Gu. F. (mitleser)


Lesenswert?

Robert schrieb:
> mmh.. derzeit 10k pull up

10k sind schon heftig.
Typischerweise sollten da eher 1k5 drin sitzen.

von Einer K. (Gast)


Lesenswert?

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.

von Hard Werker (Gast)


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.

von spess53 (Gast)


Lesenswert?

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

von Patrick J. (ho-bit-hun-ter)


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

von Peter (Gast)


Lesenswert?

Um den Fehler öfters zu provozieren kannst du auch öfters lesen.
Vorschlag: 1000 mal lesen/schreiben, 500ms Pause und wieder von vorn.

von Stefan F. (Gast)


Lesenswert?

Also wenn Lego 82k Ohm Pull-Ups verwendet (was ich nicht tun würde), 
dann können 10k nicht völlig falsch sein, oder?

von Robert (Gast)


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

von Gu. F. (mitleser)


Angehängte Dateien:

Lesenswert?

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?

von Klaus (Gast)


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"

von Oliver S. (oliverso)


Lesenswert?

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

von grundschüler (Gast)


Lesenswert?

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;

von spess53 (Gast)


Lesenswert?

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

von grundschüler (Gast)


Lesenswert?

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

von Robert (Gast)


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.

von grundschüler (Gast)


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.

von Robert (Gast)


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

von Stefan F. (Gast)


Lesenswert?

> Kann man das irgendwie  besser(einfacher) machen ?

Nicht wirklich.

von neuer PIC Freund (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.