gestartete TWI Übertragung ohne Reset rücksetzen

Gast #1464086
Ich betreibe seit einiger Zeit ein Multimaster TWI System. Dieses 
funktioniert auch recht gut. Allerdings passiert es ab und zu 
(wahrscheinlich durch einen Wackelkontakt) wenn der 1. Master senden 
will dass er bei folgenden Status stehen bleibt:

TWI_REP_START  0x10  // 16 Repeated START has been transmitted
TWI_MTX_ADR_NACK  0x20  // 32 SLA+W has been tramsmitted and NACK 
received

Der 2.Master bekommt davon aber nichts mit, bei ihm ist der letzte 
Status der einer komplett abgeschlossenen Übertragung. Ich kann auch 
wieder eine Übertragung durch den 2. Master anstoßen die den 1. dann 
wieder in normale Funktion versetzt. Dabei sind allerdings 2 
Übertragungen notwendig, die erste versteht der 1.Master noch nicht geht 
da aber in den normalen Zustand. Bei der zweiten Übertragung läuft 
wieder alles normal.

Nun die Frage.

Wie kann ich den 1. Master sagen er soll wieder in den Grundzustand 
gehen. Ohne den µC zu reseten, so dass er für Empfang und Senden wieder 
bereit ist? Mir kommt es so vor als würde er ein Stop vom 2. Master 
benötigen um wieder normal zu laufen. Doch es soll unabhängig vom 2. 
Master laufen.

Die Lösung Wackelkontakt beseitigen ist ausgeschlossen, es soll ein 
System werden, dass Übertragungsschwierigkeiten erkennt.

Danke schon mal im voraus!!
#1464097
Thomas Frosch schrieb:
> TWI_REP_START  0x10  // 16 Repeated START has been transmitted
> TWI_MTX_ADR_NACK  0x20  // 32 SLA+W has been tramsmitted and NACK
> received

Dann bist Du immer noch der aktive Master, der den Bus belegt.
Du mußt ein STOP senden.

Generell sollte man auf alle Interrupts, die unerwartet sind, ein STOP 
senden.
Ist man der aktive Master, gibt man damit den Bus frei.
Ist man ein Slave, wird das Stop nur intern ausgewertet, d.h. der Slave 
wechselt in den nicht adressierten Zustand.


Peter
Gast #1464103
Dass habe ich schon von anfang an so implementiert. Doch der Fehler 
tritt trotzdem auf. Selbst wenn ich im nachhinein per PC über uart dem 
µC sag er soll einfach mal so ein Stop senden (egal ob Stop mit oder 
ohne ACK) bleibt er dabei.

Gibt es noch andere Möglichkeiten?

Wenn ich den Bus belege warum kann dann der 2.Master trotzdem eine 
Übertragung starten? Weil er gar nicht mitbekommen hat dass der Bus 
belegt ist?
Gast #1464155
Ja das habe ich auch schon mal gelesen. Verstehe ich das richtig, sein 
Workaround besteht darin nach dem Senden/Empfangen einfach zu prüfen ob 
SCL und SDA beide längere Zeit High sind und lässt erst dann wieder ein 
Senden zu wenn diese Zeit abgelaufen ist?
#1465178
Ich bin mir nicht sicher, ob das allein hilft.
Ich habe 2 Timeouts eingebaut:

1.
Wenn man als Master STOP sendet und es nicht von selber rückgesetzt 
wird.
2.
Wenn der SDA-Pin konstant auf Low bleibt (Test per Flankeninterrupt).

Dann wird das I2C für ne Weile disabled und neu initialisiert.

Zusätzlich testet der Master, wenn er senden will, ob SDA/SCL für 50µs 
auf high bleiben und erst dann wird das START-Bit gesetzt.

Ist also ganz schön aufwendig (externer Interrupt, Timerinterrupt, 
Warteschleife).


Peter
Gast #1466221
Wie testest du den 1. Fall also er sendet stop aber setzt sich nicht 
zurück. Also wie testest du, dass er sich nicht zurück gesetzt hat?

Und das mit dem Neu initialisieren geht ganz einfach mit den standard 
initialisierungsschritten? Oder muss ich irgend ein Bit vorher 
ausschalten, etwas warten und dann wieder ganz normal initialisieren?

Wäre für mich ein super Workaround.
#1466257
Thomas Frosch schrieb:
> Wie testest du den 1. Fall also er sendet stop aber setzt sich nicht
> zurück. Also wie testest du, dass er sich nicht zurück gesetzt hat?

Ich hab nen Timerinterrupt der alle 1ms aufgerufen wird und verschiedene 
Sachen macht.

Wenn also nach 1ms immer nocht STOP gesetzt ist, disabled er das I2C und 
ruft I2C_init auf.

Und wenn nach 1ms kein Flankeninterruptbit gesetzt ist, aber SDA = 0, 
dann auch.
Ich hab damals noch nen ATmega8 benutzt, d.h. kein Pin-Change-Interrupt 
und hab dann nen Draht von SDA nach INT0 gepatcht.

Es scheint zu gehen, aber man hat eben manchmal 1..2ms den I2C blockiert 
und muß ein Retry machen.

Ich hab mir den Code nochmal angeguckt und warscheinlich nen Fehler 
entdeckt:
Nach den 50µs wird das Startbit gesetzt aber nicht zurückt, wenn der 
andere Master schneller ist.
Ich sollte besser das Starbit nach 10µs zurücksetzen. Dann könnten die 
beiden Timeouts vielleicht überflüssig sein.
Aber es läuft so und never touch a running system.


Peter

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.