gestartete TWI Übertragung ohne Reset rücksetzen

Gast #1464086
Lesenswert?

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

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

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

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

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

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

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

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