Wie man I2C dazu bringt, den Mund zu halten, während man auf Daten im Master-Sendemodus auf LPC1114 wartet

Ich habe einen LPC1114 (FN28), für den ich Code schreibe. Derzeit versuche ich, meinem Code eine asynchrone Ansicht der I2C-Schnittstelle bereitzustellen (der Chip verfügt über einen integrierten I2C-Controller). Der Controller selbst ist im Grunde eine Zustandsmaschine, aber da die I2C-Spezifikation kein Timeout oder andere Einschränkungen für die SCL-Taktrate vorgibt, sollte ich in der Lage sein, das Senden zu verzögern (es muss nicht perfekt synchron sein), solange der Controller steuert SCL korrekt, wenn Daten gesendet werden, und hält es niedrig, wenn keine Daten gesendet werden.

Die Idee ist, Daten puffern zu können, die auf dem I2C-Bus gesendet werden sollen. Ein paar Bibliotheken, die ich sehe, gehen damit um, indem sie das Ganze einfach puffern und alles auf einmal bitbangen, was meistens in Ordnung ist, da Sie im Allgemeinen nicht viele Daten über I2C senden, aber ich möchte es richtig machen.

Ich habe den Basiscode eingerichtet und das Problem, das ich beim Übertragen von Daten habe, besteht darin, dass der Controller immer dann, wenn er in den Modus "Daten an Slave senden" wechselt, einen Interrupt auslöst, der mich auffordert, ein Datenbyte zum Senden (oder Senden) auszufüllen ein STOP-Signal). Das Problem ist, wenn ich nichts tue, wird sofort derselbe Interrupt ausgegeben, sodass mein Hauptcode nicht einmal die Möglichkeit hat, ausgeführt zu werden! Was ich möchte, ist die Möglichkeit, dem Controller zu sagen: "Ich habe gerade keine Bytes zu senden, also geben Sie keinen weiteren Interrupt aus, bis ich es Ihnen von meinem Hauptcode aus sage"!

Ich habe etwas aufgerüstet, das funktioniert, indem ich (ab?) das NVIC verwende, um den I2C-Interrupt zu deaktivieren, wenn ich auf Daten warte, und ihn wieder zu aktivieren, wenn ich bereit bin, über die I2C-Schnittstelle zu senden, aber das scheint sehr unorthodox und Ich weiß nicht, ob es wirklich zuverlässig oder sogar korrekt ist, besonders wenn zwischenzeitlich schlimme Dinge mit dem Bus passieren sollten (Busfehler usw.)

Hier ist das Handbuch für den Chip , die Dokumentation für den I2C-Controller befindet sich auf Seite 239. Ich dachte, ich könnte das SI-Steuerbit verwenden, um ihm zu sagen, dass es keinen Interrupt ausgeben soll, bis ich es wieder lösche, aber anscheinend ist das nicht das, wofür es ist.

Hat jemand Erfahrung mit diesem oder ähnlichen I2C-Controllern und weiß, wie ich das erreichen kann, was ich suche? Natürlich muss es möglich sein, da ein Protokoll, bei dem Sie jedes Mal alle Daten im Voraus bereithalten müssen, mir nicht praktikabel erscheint.

"Ein Protokoll, bei dem Sie jedes Mal alle Daten im Voraus bereithalten müssen, scheint mir nicht praktikabel." Es gibt wahrscheinlich Möglichkeiten, dies zu umgehen, z. B. das Abfragen des Registerstatus, anstatt im Interrupt-Modus zu laufen. Aber in Wirklichkeit würde die Vorbereitung aller Daten im Voraus die überwiegende Mehrheit der typischen Anwendungen beschreiben – wenn Sie sich den Treiber von NXP ansehen, übergeben Sie normalerweise eine gesamte Transaktion auf einmal und treffen Entscheidungen nur zwischen ihnen.
"Ich will es richtig machen." IMO Bit-Banging ist die richtige Vorgehensweise, es sei denn, Sie benötigen einige der Vorteile der Hardwareunterstützung (Geschwindigkeit, Hands-off-Betrieb). Aber Sie verlieren die Portabilität, was meiner Meinung nach ein großer Verlust ist.
@WoutervanOoijen Ich halte Portabilität im Moment nicht für ein großes Problem für mich. Ich werde wahrscheinlich auf absehbare Zeit mit Cortexes und NXP-Chips arbeiten. Wenn also auf dem Chip gute Hardware integriert ist, möchte ich sie verdammt noch mal verwenden :) aber in Angesichts der Kommentare von Ihnen und Chris werde ich über bessere Möglichkeiten nachdenken, meinen Code so zu strukturieren, dass ich nicht durch Reifen springen muss

Antworten (1)

Das Deaktivieren des Interrupts, wenn Sie keine Daten zum Senden haben, ist genau der richtige Ansatz für einen Hardware-I2C-Master-Controller.

Wenn die Daten verfügbar sind, aktivieren Sie den Interrupt erneut und Sie nehmen ihn sofort, wodurch das Byte an den Controller übertragen wird.

Danke, das beruhigt mich ein wenig. Ist es in der Embedded-Entwicklung üblich, Interrupts ständig ein- und auszuschalten? Bisher musste ich sie nur einmal aktivieren und das war's, aber ich bin noch nicht sehr weit gekommen.
Absolut! Dafür sind sie da! Sie würden beispielsweise dasselbe mit einem UART-Übertragungsinterrupt tun, wenn Sie nichts zu senden haben.
Oh, Sie machen einen guten Punkt ... Ich habe keinen Übertragungsinterrupt für UART verwendet, sende aber im Moment synchron. Wenn ich ihn verwendet hätte, hätte ich wahrscheinlich das gleiche Problem gehabt wie für I2C ... das klärt sich es auf. Danke!