I2C: Ist ein wiederholter Start zwischen verschiedenen Slave-Adressen legal?

Ich schreibe I²C-Code für eine Anwendung, bei der ich nur einen Master, aber mehrere Slaves habe. In allen Datenblättern, die ich gelesen habe (nicht nur für dieses Projekt), wird die wiederholte Startbedingung nur verwendet, um zwischen Schreiben und Lesen und Schreiben auf / von demselben Slave oder umgekehrt umzuschalten. Natürlich würden diese Datenblätter keine anderen Sklaven zeigen (warum sollten sie das auch tun).

Ist es legal, die Stoppbedingung zwischen Übertragungen zu/von verschiedenen Slaves wegzulassen?

Verhalten sich einige Slaves falsch, wenn sie nach einer wiederholten Startbedingung angesprochen werden, nachdem zuvor andere Slaves angesprochen wurden?

Ich weiß, dass die zweite Frage nicht sicher mit „nein“ beantwortet werden kann, aber wenn jemand von euch schon einmal Probleme in einer solchen Situation hatte, reicht mir das.

Antworten (3)

Die Bedingung für wiederholten Start wurde der Spezifikation hinzugefügt, um es einem Master in einer Konfiguration mit mehreren Mastern zu ermöglichen, die Kontrolle über den Bus zu behalten, während er eine neue Operation einleitet. Es funktioniert auch in einem Ein-Master-Setup, wie auf Seite 9 der Spezifikation zu sehen ist: Die wiederholte Startbedingung wird in einer allgemeinen Beschreibung beschrieben, funktioniert also für beide Modi. Auch nach einer erneuten Startbedingung wird die Adresse erneut gesendet, also sollte es auch beim Ändern der Adresse funktionieren.

Es ist jedoch nicht sehr häufig, daher erwarten einige Sklaven (ich habe jedoch noch nie einen gesehen, aber Michael Karas hat wie in seiner Antwort angegeben ) eine Stoppbedingung, die Probleme verursachen kann, wenn die Stoppbedingung weggelassen wird. Ich würde Ihnen daher empfehlen, die Stoppbedingung nur zur Sicherheit einzufügen, obwohl Ihre Implementierung nach der Spezifikation nicht "falsch" wäre. Eine Stoppbedingung kostet nicht so viel Zeit.

Ich weiß, dass die Stoppbedingung nicht viel Zeit kostet; der Hintergrund ist eher umsetzungsorientiert. Ich schreibe Interrupt-gesteuerten I2C-Code für einen AVR, und das Einfügen von Stopps hat Auswirkungen auf die Implementierung.
Ich verstehe, guter Punkt. Die Antwort bleibt die gleiche: Es sollte funktionieren, wenn man die Spezifikation befolgt.
@Christoph: Dann scheint das Grundproblem eine schlecht durchdachte Architektur zu sein, was den Interrupt-Code betrifft, was der Vordergrund tut und wie die Anwendung damit interagiert. Es gibt keinen legitimen Grund, warum Sie nicht am Ende jeder Nachricht einen Stopp senden könnten.
@Olin: Es ist noch nicht durchdacht, also kann es noch nicht schlecht durchdacht sein. Wie kann das Einfügen von Stoppbedingungen am Ende jeder Operation keinen Einfluss auf die Implementierung haben, im Vergleich zum Nichteinfügen eines Stopps und Senden eines wiederholten Starts? Die Umsetzung wird anders sein.
Die Frage ist, wie viel Einfluss es haben wird. @OlinLathrop sagt, dass Ihre Implementierung schlecht durchdacht ist, wenn die Auswirkungen groß sind. Daher sollte die Implementierung so sein, dass das Hinzufügen einer Stoppbedingung zur Implementierung nicht so schwierig wäre.
Michael und Sie haben die gleiche Grundaussage gemacht. Ich würde beide Antworten akzeptieren, aber leider kann ich nicht.

Meine Empfehlung ist, jede Transaktion mit jedem Gerät immer mit einer Stop-Sequenz zu beenden. Sie haben eine viel größere Erfolgschance, wenn Sie mit verschiedenen Arten von alternativen Geräten sprechen, die Sie in Zukunft anschließen möchten.

Ich habe speziell Geräte gesehen, die sich schlecht verhalten, wenn am Ende der Transaktion ein Stopp fehlt.

Tatsächlich habe ich vor einigen Jahren daran gearbeitet, einige Slave-Geräte in FPGA-artige Teile zu entwerfen. Ich fand es wichtig, die Stoppbedingung zu decodieren und damit die Transaktionszustandsmaschine des Slaves zurückzusetzen. Der Hauptgrund dafür ist, dass im Bus seltsame Dinge passieren können, Dinge, mit denen die Master-Seite des Busses nicht einmal gerechnet hat. Wenn eine laufende Operation durch diese "unerwarteten Dinge" beschädigt wird, kann Chaos entstehen, das einige Arbeit erfordert, um sich davon zu erholen. Die beste Entwurfsstrategie für Geräte besteht darin, dass sie die Stoppsequenz entwerfen und verwenden, um das Zurücksetzen der Schnittstelle zu erzeugen. Wenn diese Strategie befolgt wird, erhält der Gerätehersteller viel weniger Supportanrufe und eine zufriedenere Gruppe von Kunden.2 C-Netzwerk, das aus einem Sequenzpaar START -> STOP besteht. Dies kann in der übergeordneten Treibersoftware der Masterseite als Teil einer Wiederholungsschleife verwendet werden, wenn die Gerätekommunikation aus dem einen oder anderen Grund fehlgeschlagen ist.

Wenn Sie sich im Internet umsehen, finden Sie bestimmte App-Notizen, die verschiedene Arten von beteiligten I 2 C-"Bus-Reset" -Schemata beschreiben, die versuchen, Geräte wiederherzustellen, die aufgrund unerwarteter Ereignisse im Bus hängen geblieben sind. Einige davon beinhalten Start-Stopp-Sequenzen mit 9 oder 27 Taktzyklen dazwischen. Andere haben gezeigt, wie man den Strom zum Zielgerät leitet, indem man einen FET in der Vcc-Leitung verwendet, um einen "internen Reset" im Slave-Gerät zu bewirken.

Wenn jeder so konstruiert ist, dass die Stoppsequenz einfach zurückgesetzt wird, können alle bizarren I 2 C-Probleme, die auftreten können, auf einfache Weise gelöst werden, ohne auf Schemata zurückgreifen zu müssen, wie sie in diesen App-Notizen beschrieben werden. Ich habe eine enorme Verbesserung der Robustheit neuerer I 2 C-Geräte erlebt, die ich in meinen eigenen Embedded-Design-Projekten verwende. Dies ist eine solche Erleichterung im Vergleich zu LM75-Temperatursensoren von vor 10 bis 15 Jahren, die ein Power-Gating ihrer Vcc-Pins benötigten, um einen zuverlässigen Betrieb zu gewährleisten, ODER einige unbenannte I 2 C -8-Bit-DAC/ADC, die zusätzliche Wiederherstellungs-Resets vom Takttyp erforderten.

Aufgrund jahrelanger Erfahrung möchte ich Ihnen daher nochmals empfehlen, diese wiederholte Startsequenz / dieses geänderte Adressschema nicht zu versuchen. Befolgen Sie immer die einfachste Reihenfolge, die die Arbeit für ein bestimmtes I 2 C-Gerät erledigt . Stellen Sie außerdem sicher, dass jede Transaktion mit einer Stoppsequenz endet, und stellen Sie eine Busrücksetzfunktion bereit, die ein Start-Stopp-Sequenzpaar ist.

Ich weiß, dass es hier wahrscheinlich viele Leser gibt, die I 2 C-Kommunikationssoftware implementieren, die auf der Annahme basiert, dass Geräte immer einfach funktionieren werden. Ich möchte darauf hinweisen, dass es eine ganze Reihe unternehmenskritischer eingebetteter Anwendungen gibt, bei denen diese Technik nicht akzeptabel ist. Es wird notwendig, jeden möglichen Fehler in einer Transaktion zu erkennen und dann darüber eine weitere Ebene hinzuzufügen, die Wiederholungsversuche und eine versuchte Busrücksetzungswiederherstellung umfasst. Und schließlich, wenn ein kritisches Verhalten des Produkts von dem ausgefallenen I 2 C-Kanal abhängt, ergreifen Sie sorgfältige Schritte, um das Gerät ordnungsgemäß und sicher herunterzufahren.

Ich mag das Design des I2C-Protokolls, aber ein Großteil der vorhandenen Hardware ... nicht so sehr. Es scheint, als gäbe es eine Reihe von Dingen, die das Protokoll bieten sollte, aber Hardwareimplementierungen können dies nicht. Zum Beispiel sehe ich keinen Grund, warum es nicht möglich sein sollte, mehrere I2C-Slave-Geräte auf dem Bus zu haben, die vernünftig auf einen Befehl "48-Bit-Seriennummern in numerischer Reihenfolge beginnend mit XXXXXX abrufen" reagieren würden, wenn I2C-Arbitrierungshardware aktiviert werden könnte im Slave-Modus und alle sechs Bytes wieder aktiviert. Mir fallen aber keine Umsetzungen ein...
... außer vielleicht für den 8749 (dessen I2C-Hardware jeweils nur ein bisschen verarbeitet), der so etwas möglicherweise kann.
Ich habe vergessen zu erwähnen: Ein Start/Stopp-Paar funktioniert nicht, um den Bus zurückzusetzen, wenn Daten von einem Slave gelesen werden. Wenn z. B. ein serielles EEPROM eine Folge von Nullen liest, dann wird es für acht Bitzeiten aus jeder Gruppe von neun Bits SDA niedrig halten; Wenn der Master SCL nicht oft genug pulsiert, dass der Slave ihn freigibt, kann er keinen Stopp/Start ausgeben. Außerdem ignorieren viele EEPROM- und ähnliche Geräte jede Transaktion, die nicht mit einer ordnungsgemäßen Stoppsequenz endet. Daher ist es oft wünschenswert, sicherzustellen, dass die zum Zurücksetzen des Busses verwendete Sequenz möglicherweise nicht mit einem legitimen Stopp verwechselt werden kann.

Ich habe eine Software für einen Mikrocontroller als Master mit mehreren Slave-Geräten geschrieben und wollte sicher sein, dass der Master den Fall erkennt, wenn der Slave keine Antwort gab.

Ich hatte einige Software laufen und sprach mit einem Slave, also dachte ich, ich würde ändern, um eine andere Adresse zu verwenden, auf die kein Slave antworten würde. Ich habe versehentlich diese ungültige Adresse direkt nach einem wiederholten Start verwendet, wo das Gerät im Lesemodus neu adressiert wird, um es dazu zu bringen, seine Registerinhalte auszulesen.

Es stellt sich heraus, dass zumindest für dieses spezielle Gerät die ungültige Adresse ignoriert und normal weitergemacht wurde und ich alle üblichen Daten erhalten habe.

Mein vorläufiges Fazit hier ist, dass I2C-Geräte, sobald die erste Adresse an den Bus gegangen ist, weiterhin Transaktionen ignorieren oder bis zur nächsten Stoppbedingung auf Transaktionen reagieren werden.