Können sich GPIO-Pins gegenseitig stören?

Ich habe eine einfache Schaltung, in der ich I2C (SCL / SDA ist GP5 / GP4) auf einem Bild 12F629 bitbange. Es funktioniert perfekt, alle Timings sind korrekt, keine Fehler usw. Der genaue Schaltplan ist irrelevant, da ich die gesamte Schaltung in Grundblöcke zerlegt und jedes Teil separat getestet habe, um sicherzustellen, dass der Slave nicht schuld ist.

Beachten Sie, dass ich mit verschiedenen Chips und verschiedenen Modellen getestet habe und das Problem weiterhin besteht.

Jetzt möchte ich einen zufälligen Pin fahren, sagen wir GP2 niedrig. In dem Moment, in dem ich das mache, spielt die I2C-Wellenform verrückt. Hier ist die Wellenform nach dem Tiefziehen von GP2 (SDA blau, SCL gelb):Geben Sie hier die Bildbeschreibung ein

Nach einigen Experimenten hier meine Schlussfolgerungen:

In I2C dürfen die Geräte SDA/SCL entweder herunterziehen oder freigeben (in diesem Fall werden sie von den Pullups hochgezogen). Um also HIGH zu bezeichnen, setzen wir den SDA- oder SCL-Pin auf Eingang und somit wird er freigegeben und auf +5 V hochgezogen, und um LOW zu bezeichnen, setzen wir ihn auf Ausgang und er wird auf LOW getrieben. Damit SDA/SCL beim Setzen auf Ausgang auf Low gesetzt werden, werden diese beiden Pins natürlich während der Initialisierung des Programms zuerst auf Ausgang gesetzt und erhalten den Wert LOW, sodass sie jetzt jedes Mal, wenn sie während der i2c-Kommunikation von Eingängen auf Ausgänge umgeschaltet werden, automatisch LOW fahren.

Und im letzten Teil bricht meiner Meinung nach alles zusammen.

Wenn ich irgendwann nach einer i2c-Kommunikation einen GPIO-Pin treibe, z. GP2 LOW oder HIGH, dies wirkt sich irgendwie auf den GPIO-Wert der ANDEREN gpio-Pins (nämlich SCL/SDA) aus, was alles durcheinander bringt. dh. SDA/SCL-GPIO-Pins sind auf 1 gesetzt, wenn sie also während der i2c-Kommunikation von Eingang zu Ausgang geschaltet werden, erhalten sie den Wert 1 anstelle von 0 und treiben den i2c-Bus daher nicht auf LOW, sondern auf HIGH, was nicht zulässig ist . Und jetzt ist die einzige Möglichkeit, es wieder zum Laufen zu bringen: 1. SDA/SCL-Richtung in TRISIO auf OUTPUT setzen 2. SDA/SCL-Wert in GPIO auf 0 setzen 3. SDA/SCL-Richtung zurück auf Eingang setzen, um den Bus freizugeben und zu lassen es wird von den Klimmzügen hochgezogen.

Und jetzt sind wir bereit, die Kommunikation wieder aufzunehmen. Bis ich natürlich einen weiteren GPIO hoch oder tief ziehe wo wieder alles geschraubt wird.

Nun meine Frage: Wie könnte man das beheben? Könnte dies ein Read-Modify-Write-Problem sein? Ich dachte, dies wäre ein häufiges Problem, ich war mir sicher, dass viele Leute gleichzeitig i2c und einen GPIO-Pin verwenden und sich gegenseitig stören würden, aber meine Suche ergab keine Ergebnisse.

Denken Sie daran, dass nichts mit dem uC verbunden ist, außer dem Oszilloskop. Ich habe alles einzeln entfernt, um das Problem zu finden, und das Problem besteht weiterhin.

Welchen Wert des externen Pullup-Widerstands verwenden Sie für SCL und SDA?
4,7 KiloOhm Widerstände (min. Zeichengrenze: P)
Poste deinen Code! (Und ein Schema, wie SamGibsons Antwort zeigt, spielt im Minimalfall immer noch eine Rolle).
-1 für "Der genaue Schaltplan ist irrelevant".
@DmitryGrigoryev Was passiert also, wenn das einzige Schema das uC (nicht einmal das externe xtal) und das Oszilloskop ist?
@John Offensichtlich passiert nichts, da keine Stromversorgung vorhanden ist;) Im Ernst, viele solcher Störungen werden durch fehlende Entkopplungskappen oder falsch platzierte Oszilloskopsonden erklärt. Stack Overflow erfordert das Posten eines Beispiels für fehlerhaften Code, selbst wenn es nur ein „Hallo Welt!“ ist. App. Warum nicht die gleiche Regel hier durchsetzen?
Vielleicht haben Sie das Problem bereits mit SamGibsons Antwort gelöst, aber ... Wie stellen Sie den GP2-Pin ein? Wenn Sie es mit dem Befehl TRISIO = 0x04;oder auf einen Ein- oder Ausgang setzen TRISIO = 0x00;, dann setzen Sie auch die beiden I2C als Ausgänge und machen somit Fehler. Sie sollten so etwas wie TRISIO |= 0x04;und verwenden TRISIO &= ~0x04;(und dasselbe für das GPIO-Register). Wie auch immer, ich denke, Sie tun das bereits, aber ... ich habe gelernt, dass es immer besser ist, nicht zu viel anzunehmen ;)

Antworten (3)

Ich glaube, ich habe Ihr Problem gefunden, und (ich weiß, dass Ihnen das nicht gefallen wird) ein genauer Schaltplan hätte das Problem (zumindest einigen) Lesern sofort aufgezeigt. :-)

Wenn Sie sich die Startspannung an den beiden Pins in Ihren beiden obigen Spuren ansehen, liegt diese Spannung bei etwa +3,3 V. Das sagt mir, dass der PIC von dieser Spannung gespeist wird. Dann sehen wir, wie die Spannung auf +5 V ansteigt, wenn Ihr Code die Pins in Eingänge ändert und die I²C-Pull-up-Widerstände übernehmen.

Sie ziehen also die I²C-Signale auf +5 V hoch, aber der PIC wird von +3,3 V gespeist. Das ist das Problem. Dies führt zu einem kontinuierlichen Stromfluss durch die internen "ESD-Klemmdioden" (sie sind heutzutage normalerweise keine Dioden, aber das ist eine andere Geschichte). Dies hat Konsequenzen (insbesondere bei mehr als minimalen Strömen), einschließlich der Beeinflussung anderer Teile des PIC oder sogar der Verursachung von Ausfällen aufgrund von EOS, da Strom dort eingespeist wird, wo er nicht sein sollte.

Einige der Symptome in Ihrer gestrigen Frage - " Alles funktioniert nicht mehr, nachdem ich PWM aktiviert habe " - deuteten auf diese Möglichkeit hin, insbesondere als Sie berichteten, dass alles in Ordnung war, als Sie die Schaltung auseinander genommen und wieder aufgebaut haben (da, wenn kein dauerhafter Schaden entstanden ist , die Auswirkungen dieses Problems verschwinden manchmal, wenn die Stromversorgung vollständig unterbrochen wird). Ohne Schaltplan konnte ich jedoch keine Hypothese aufstellen, mit der ich zufrieden war, da Sie sagten, dass nichts mit dem PIC verbunden war - aber etwas mit dem PIC verbunden war: die I²C-Pull-up-Widerstände an +5 V!

Dann schien Ihre frühere Frage heute - " Ist mein GPIO-Pin gebraten? " - einen Hardwareschaden zu bestätigen. Das könnte immer noch wahr sein, und ein solcher Schaden (oder das alternative vorübergehende Ergebnis, das in Ihrer ersten Frage aufgetreten ist) passt zu dieser Hypothese.

Diese Hypothese erklärt auch Ihren neuen Kommentar in dieser Frage vollständig:

Beachten Sie, dass ich mit verschiedenen Chips und verschiedenen Modellen getestet habe und das Problem weiterhin besteht.

Ja, alle ähnlichen Geräte würden sich in dieser Situation von Pull-ups auf eine Spannung weit über +Vdd ähnlich verhalten.

Im relevanten PIC-Datenblatt (das ich in einer Minute herunterladen werde) wird gezeigt, dass "empfohlene Betriebsbedingungen" (mit anderen Worten Bedingungen, unter denen der Chip funktionieren sollte ) mit einem Chip, der mit +3,3 V und Eingängen betrieben wird, nicht erfüllt werden Empfang von +5V (über die I²C-Pullup-Widerstände). Mit den strombegrenzenden Effekten dieser I²C-Pullups können Sie jedoch Glück haben, dass die Effekte nur vorübergehend sind, wenn Sie den im Abschnitt „Absolute Maxima“ aufgeführten maximalen Klemmstrom nicht überschritten haben.

Die Lösung besteht darin, den I²C-Bus mit der gleichen Spannung wie der PIC selbst zu betreiben, nicht höher . Wenn dies aufgrund von Einschränkungen erforderlich ist, die von den I²C-Slaves (was auch immer sie sind) auferlegt werden, verwenden Sie I²C-Pegelumsetzer, um eine lokale I²C-Spannung für den PIC zu erreichen, die diese Regel erfüllt.

[Erwarten Sie später eine weitere Bearbeitung, wenn ich einige Zahlen aus dem Datenblatt zitieren kann, nur der Vollständigkeit halber.]

Ok ich bin doof. Das war ein Fehler meinerseits, ich habe vergessen zu erwähnen, mein PIC wird mit 5 V betrieben und mein Slave mit 3,3 V. Sorry für die Verwirrung...
@John - Zu Ihrer Information, wenn Ihr Slave-Gerät mit 3,3 V betrieben wird, ist es möglicherweise nicht glücklich (und kann fehlerhaft funktionieren oder beschädigt werden), wenn es mit 5 V an einen I2C-Bus angeschlossen wird! Die Tatsache, dass der Beginn Ihrer Scope-Spur +3.etwas Volt anzeigt, sagt uns etwas , obwohl Sie sagen, dass der PIC mit +5 V betrieben wird. Wenn es keinen anderen Teil der Geschichte gäbe, würden wir am Anfang der Scope-Spur +5 V sehen - aber das tun wir nicht . Die Hypothese in dieser Antwort passt zu den Symptomen in allen drei Ihrer Fragen, daher würde ich versuchen, besser zu verstehen, welche Netzspannungen wo angeschlossen sind.
Vdd + 0,3 V ist die absolute Höchstleistung an jedem Pin. Selbst wenn der Chip nicht beschädigt zu sein scheint / der Klemmstrom nicht überschritten wurde, ist er wahrscheinlich immer noch verdächtig.
Sie waren wirklich hilfreich bei der Lösung dieses Problems, das mich in den letzten 2 Tagen genervt hat! Danke!

Klingt so, als würden Sie in die Register des Ports (z. B. PORTA == Portwertregister für Port A) anstelle der Latch-Register schreiben (z. B. LATA == Output-Latch-Register für Port A). Das Port-Register verfolgt den aktuellen Wert des Eingangs, das Latch-Register behält seinen Zustand bei. Wenn Sie versuchen, ein Bit in einem Portregister zu setzen/zu löschen, werden die anderen Bits gesetzt/gelöscht, um ihrem aktuellen Eingangszustand zu entsprechen. Wenn Sie ein Bit in einem Latch-Register setzen/löschen, wird nur der Ausgang dieses Bits beeinflusst.

Bearbeiten: Aus dem Datenblatt.

Das Lesen des GPIO-Registers liest den Status der Pins, während das Schreiben darauf in das Port-Latch schreibt. Alle Schreiboperationen sind Lese-Modifizier-Schreib-Operationen. Daher impliziert ein Schreiben an einen Port, dass die Port-Pins gelesen werden, dieser Wert modifiziert wird und dann in das Port-Daten-Latch geschrieben wird. GP3 liest '0', wenn MCLREN = 1.

Es scheint, dass diese PIC-Serie tatsächlich die LATCH-Register überspringt, wie Sie kommentiert haben. Eine einfache Problemumgehung (nicht die sauberste Lösung, aber es würde funktionieren) besteht darin, eine globale Variable zu verwenden, um die Zustandsverfolgung manuell für Sie durchzuführen. Modifizieren Sie dieses Global einfach etwas und kopieren Sie das Ganze dann in das Portregister (GPIO in dieser Serie).

Aber LAT-Register sind nur PIC18-Serien :(
Mir ist gerade aufgefallen, dass diese Serie sie tatsächlich nicht hat, siehe meine Bearbeitung.

Dies wirkt sich irgendwie auf den GPIO-Wert der ANDEREN GPIO-Pins (nämlich SCL / SDA) aus, was alles durcheinander bringt.

das kann nur in einem System passieren, in dem die Software schlecht entworfen ist.

Nun meine Frage: Wie könnte man das beheben?

Schreiben Sie den richtigen Code, damit es nicht passiert.

Kurz gesagt, setzen Sie das Pin-Ausgangsdatenregister auf seinen richtigen Zustand zurück, bevor Sie sein Ausgangsrichtungsregister ändern.

Dies erklärt nicht, warum/wie die Software schlecht gestaltet ist oder wie "richtiger Code" ist/aussieht.