I²C

Aus besserwiki.de
I2C-Bus
I²C bus logo.svg

Typ Serieller Kommunikationsbus
Produktionsgeschichte
Designer Philips Semiconductor, heute bekannt als NXP Semiconductors
Entworfen 1982; vor 41 Jahren
Daten
Daten-Signal Open-Collector oder Open-Drain
Breite 1 Bit (SDA) mit separatem Takt (SCL)
Bitrate 0,1, 0,4, 1,0, 3,4 oder 5,0 Mbit/s je nach Modus
Protokoll Seriell, halb-duplex

I2C (Inter-Integrated Circuit, eye-squared-C), auch bekannt als I2C oder IIC, ist ein synchroner, paketvermittelter, unsymmetrischer, serieller Kommunikationsbus mit mehreren Controllern und Zielen (Controller/Target), der 1982 von Philips Semiconductors erfunden wurde. Er wird häufig für den Anschluss von Peripherie-ICs mit geringerer Geschwindigkeit an Prozessoren und Mikrocontroller für die Kommunikation über kurze Entfernungen auf der Leiterplatte verwendet.

Mehrere Wettbewerber wie Siemens, NEC, Texas Instruments, STMicroelectronics, Motorola, Nordic Semiconductor und Intersil haben seit Mitte der 1990er Jahre kompatible I2C-Produkte auf den Markt gebracht.

Der System Management Bus (SMBus), der 1995 von Intel definiert wurde, ist eine Untermenge von I2C und definiert eine strengere Verwendung. Ein Ziel des SMBus ist es, die Robustheit und Interoperabilität zu fördern. Dementsprechend enthalten moderne I2C-Systeme einige Richtlinien und Regeln des SMBus und unterstützen manchmal sowohl I2C als auch SMBus, wobei nur eine minimale Rekonfiguration entweder durch Befehle oder die Verwendung von Ausgangspins erforderlich ist.

I²C, für englisch Inter-Integrated Circuit, im Deutschen gesprochen als I-Quadrat-C oder englisch I-Squared-C (ˈaɪ skwɛərd ˈsiː) oder I-2-C (ˈaɪ tuː ˈsiː), ist ein 1982 von Philips Semiconductors (heute NXP Semiconductors) entwickelter serieller Datenbus.

Atmel führte aus lizenzrechtlichen Gründen die heute auch von einigen anderen Herstellern verwendete Bezeichnung TWI (Two-Wire-Interface, englisch für Zweidraht-Schnittstelle) ein; technisch sind TWI und I²C praktisch identisch. Allerdings ist das ursprüngliche Patent am 1. Oktober 2006 ausgelaufen, so dass keine Lizenzgebühren für die Benutzung von I²C mehr anfallen. I²C ist auch kein eingetragenes Markenzeichen von NXP Semiconductors, Markenschutz besteht lediglich für das Logo.

Anwendungen

Microchip MCP23008 8-Bit I2C I/O-Erweiterung im DIP-18-Gehäuse

I2C ist für Peripheriegeräte geeignet, bei denen Einfachheit und niedrige Herstellungskosten wichtiger sind als Geschwindigkeit. Gängige Anwendungen für den I2C-Bus sind:

  • Beschreibung von anzuschließenden Geräten über kleine ROM-Konfigurationstabellen, um den Plug-and-Play-Betrieb zu ermöglichen, z. B. in Serial Presence Detect (SPD) EEPROMs auf Dual In-Line-Speichermodulen (DIMMs), und Extended Display Identification Data (EDID) für Monitore über VGA-, DVI- und HDMI-Anschlüsse.
  • Systemmanagement für PC-Systeme über SMBus; SMBus-Pins sind sowohl in herkömmlichen PCI- als auch in PCI-Express-Anschlüssen zugewiesen.
  • Zugriff auf Echtzeit-Taktgeber und NVRAM-Chips, die Benutzereinstellungen speichern.
  • Zugriff auf Low-Speed-DACs und ADCs.
  • Ändern der Einstellungen für Hintergrundbeleuchtung, Kontrast, Farbton, Farbbalance usw. in Monitoren (über den Display Data Channel).
  • Ändern der Lautstärke in intelligenten Lautsprechern.
  • Steuerung kleiner LCD- oder OLED-Anzeigen (z. B. bei Mobiltelefonen).
  • Auslesen von Hardware-Monitoren und Diagnosesensoren, z. B. der Drehzahl eines Lüfters.
  • Einschalten und Ausschalten der Stromversorgung von Systemkomponenten.

Eine besondere Stärke von I2C ist die Fähigkeit eines Mikrocontrollers, ein Netzwerk von Gerätechips mit nur zwei Allzweck-E/A-Pins und Software zu steuern. Viele andere Bustechnologien, die in ähnlichen Anwendungen eingesetzt werden, wie der Serial Peripheral Interface Bus (SPI), benötigen mehr Pins und Signale, um mehrere Geräte anzuschließen.

Überarbeitungen

Geschichte der I2C-Spezifikation
Jahr Version Anmerkungen Verweise
1981 Patent U.S.-Patent 4,689,740, eingereicht am 2. November 1981 von der U.S. Philips Corporation.
1982 Ursprünglich Das 100 kbit/s I2C-System wurde als einfaches internes Bussystem für den Aufbau von Steuerelektronik mit verschiedenen Philips-Chips entwickelt.
1992 1 Es wurden ein 400 kbit/s Fast-Mode (Fm) und ein 10-Bit-Adressierungsmodus hinzugefügt, um die Kapazität auf 1008 Knoten zu erhöhen. Dies war die erste standardisierte Version.
1998 2 Hinzufügen des 3,4 Mbit/s High-Speed-Modus (Hs) mit energiesparenden Anforderungen an elektrische Spannung und Strom.
2000 2.1 Geklärte Version 2, ohne wesentliche funktionale Änderungen.
2007 3 Hinzufügung von 1 Mbit/s Fast-mode plus (Fm+) (unter Verwendung von 20-mA-Treibern) und eines Geräte-ID-Mechanismus.
2012 4 Hinzufügung von 5 Mbit/s Ultra Fast-mode (UFm) für neue USDA- (Daten) und USCL- (Takt) Leitungen unter Verwendung von Push-Pull-Logik ohne Pull-up-Widerstände,
und Hinzufügen einer Tabelle mit zugewiesener Hersteller-ID. Es handelt sich nur um einen unidirektionalen Bus.
2012 5 Fehler korrigiert.
2014 6 Zwei Diagramme korrigiert.
2021 7 Die Begriffe "Master/Slave" wurden in "Controller/Target" geändert, um mit der I3C-Bus-Spezifikation übereinzustimmen.
Aktualisierte Tabelle 5 zugewiesene Hersteller-IDs. Abschnitt 9 Übersicht über den I3C-Bus hinzugefügt. Dies ist der aktuelle Standard (Login erforderlich).

Entwurf

Ein Beispielschaltplan mit einem Controller (einem Mikrocontroller), drei Zielknoten (einem ADC, einem DAC und einem Mikrocontroller) und Pull-up-Widerständen Rp

I2C verwendet nur zwei bidirektionale Open-Collector- oder Open-Drain-Leitungen: die serielle Datenleitung (SDA) und die serielle Taktleitung (SCL), die mit Widerständen hochgezogen werden. Typische Spannungen sind +5 V oder +3,3 V, obwohl auch Systeme mit anderen Spannungen zulässig sind.

Das I2C-Referenzdesign hat einen 7-Bit-Adressraum mit einer selten verwendeten 10-Bit-Erweiterung. Gängige I2C-Busgeschwindigkeiten sind der 100 kbit/s-Standardmodus und der 400 kbit/s-Schnellmodus. Es gibt auch einen 10-kbit/s-Low-Speed-Modus, aber auch beliebig niedrige Taktfrequenzen sind zulässig. Spätere I2C-Versionen können mehr Knoten aufnehmen und mit höheren Geschwindigkeiten arbeiten (400 kbit/s fast mode, 1 Mbit/s fast mode plus, 3,4 Mbit/s high-speed mode und 5 Mbit/s ultra-fast mode). Diese Geschwindigkeiten sind auf eingebetteten Systemen weiter verbreitet als auf PCs.

Beachten Sie, dass die Bitraten für die Übertragungen zwischen Controller und Ziel ohne Clock-Stretching oder anderen Hardware-Overhead angegeben sind. Der Protokoll-Overhead umfasst eine Zieladresse und möglicherweise eine Registeradresse innerhalb des Zielgeräts sowie ACK/NACK-Bits pro Byte. Daher ist die tatsächliche Übertragungsrate der Nutzdaten niedriger, als es diese Spitzenbitraten allein vermuten lassen. Wenn beispielsweise bei jeder Interaktion mit einem Zielgerät ineffizienterweise nur 1 Byte an Daten übertragen werden kann, beträgt die Datenrate weniger als die Hälfte der Spitzenbitrate.

Die Anzahl der Knoten, die an einem bestimmten I2C-Bus vorhanden sein können, ist durch den Adressraum und auch durch die Gesamtkapazität des Busses von 400 pF begrenzt, was die praktischen Kommunikationsentfernungen auf einige Meter beschränkt. Die relativ hohe Impedanz und die geringe Störfestigkeit erfordern ein gemeinsames Massepotential, was wiederum die praktische Verwendung auf die Kommunikation innerhalb derselben PC-Platine oder eines kleinen Systems von Platinen beschränkt.

I2C-Betriebsarten
Modus Maximale
Geschwindigkeit
Maximale
Kapazität
Antrieb Richtung
Standardmodus (Sm) 100 kbit/s 400 pF Offener Drain* Bidirektional
Schneller Modus (Fm) 400 kbit/s 400 pF Offener Drain* Bidirektional
Schneller Modus plus (Fm+) 1 Mbit/s 550 pF Offener Drain* Bidirektional
Hochgeschwindigkeitsmodus (Hs) 1,7 Mbit/s 400 pF Offener Drain* Bidirektional
Hochgeschwindigkeitsmodus (Hs) 3,4 Mbit/s 100 pF Offener Drain* Bidirektional
Ultra-schneller Modus (UFm) 5 Mbit/s ? Push-Pull Unidirektional

Referenzdesign

Bei dem vorgenannten Referenzdesign handelt es sich um einen Bus mit einer Takt- (SCL) und einer Datenleitung (SDA) mit 7-Bit-Adressierung. Der Bus hat zwei Rollen für Knoten, entweder Controller oder Ziel:

  • Controller-Knoten: Knoten, der den Takt erzeugt und die Kommunikation mit den Zielen initiiert.
  • Zielknoten: Knoten, der den Takt empfängt und antwortet, wenn er von der Steuerung angesprochen wird.

Der Bus ist ein Multi-Controller-Bus, was bedeutet, dass eine beliebige Anzahl von Controller-Knoten vorhanden sein kann. Darüber hinaus können die Rollen von Steuerung und Ziel zwischen den Nachrichten (nach dem Senden eines STOPP) geändert werden.

Es gibt vier mögliche Betriebsarten für ein bestimmtes Busgerät, obwohl die meisten Geräte nur eine einzige Rolle und deren zwei Modi verwenden:

  • Controller senden: Der Controller-Knoten sendet Daten an ein Ziel.
  • Controller-Empfang: Der Controller-Knoten empfängt Daten von einem Ziel.
  • Ziel senden: Der Zielknoten sendet Daten an die Steuerung.
  • Ziel empfangen: Der Zielknoten empfängt Daten vom Controller.

Zusätzlich zu den Datenbits 0 und 1 erlaubt der I2C-Bus spezielle START- und STOP-Signale, die als Nachrichtenbegrenzer fungieren und von den Datenbits getrennt sind. (Dies steht im Gegensatz zu den bei der asynchronen seriellen Kommunikation verwendeten Start- und Stoppbits, die sich nur durch ihr Timing von den Datenbits unterscheiden).

Der Controller befindet sich zunächst im Controller-Sendemodus, indem er ein START sendet, gefolgt von der 7-Bit-Adresse des Ziels, mit dem er kommunizieren möchte, gefolgt von einem einzelnen Bit, das angibt, ob er in das Ziel schreiben (0) oder von ihm lesen (1) möchte.

Wenn das Ziel auf dem Bus vorhanden ist, antwortet es mit einem ACK-Bit (active low für acknowledged) für diese Adresse. Der Controller fährt dann entweder im Sende- oder im Empfangsmodus fort (je nach dem gesendeten Lese-/Schreibbit), und das Ziel fährt im komplementären Modus fort (Empfang bzw. Senden).

Die Adresse und die Datenbytes werden mit dem höchstwertigen Bit zuerst gesendet. Die Startbedingung wird durch einen High-to-Low-Übergang von SDA mit SCL High angezeigt; die Stoppbedingung wird durch einen Low-to-High-Übergang von SDA mit SCL High angezeigt. Alle anderen Übergänge von SDA erfolgen mit SCL low.

Wenn der Controller in das Ziel schreiben will, sendet er wiederholt ein Byte, wobei das Ziel ein ACK-Bit sendet. (In dieser Situation befindet sich die Steuerung im Sendebetrieb der Steuerung und das Ziel im Empfangsbetrieb des Ziels).

Möchte die Steuerung vom Ziel lesen, so empfängt sie wiederholt ein Byte vom Ziel, wobei die Steuerung nach jedem Byte außer dem letzten ein ACK-Bit sendet. (In dieser Situation befindet sich der Controller im Controller-Empfangsmodus und das Target im Target-Sendemodus.)

Eine I2C-Transaktion kann aus mehreren Nachrichten bestehen. Der Controller beendet eine Nachricht mit einer STOP-Bedingung, wenn dies das Ende der Transaktion ist, oder er kann eine weitere START-Bedingung senden, um die Kontrolle über den Bus für eine weitere Nachricht zu behalten (eine Transaktion im "kombinierten Format").

Nachrichtenprotokolle

I2C definiert grundlegende Arten von Transaktionen, die jeweils mit einem START beginnen und mit einem STOPP enden:

  • Einzelne Nachricht, bei der ein Controller Daten in ein Ziel schreibt.
  • Einzelne Nachricht, bei der eine Steuereinheit Daten von einem Ziel liest.
  • Kombiniertes Format, bei dem eine Steuereinheit mindestens zwei Lese- oder Schreibvorgänge in einem oder mehreren Zielen ausführt.

Bei einer kombinierten Transaktion beginnt jeder Lese- oder Schreibvorgang mit einem START und der Zieladresse. Die START-Bedingungen nach dem ersten werden auch als wiederholte START-Bits bezeichnet. Den wiederholten START-Bits gehen keine STOP-Bedingungen voraus, so dass die Ziele wissen, dass die nächste Nachricht Teil derselben Transaktion ist.

Ein bestimmtes Ziel reagiert nur auf bestimmte Nachrichten, wie in der Produktdokumentation angegeben.

Reine I2C-Systeme unterstützen beliebige Nachrichtenstrukturen. SMBus ist auf neun dieser Strukturen beschränkt, z. B. read word N und write word N, die ein einziges Ziel betreffen. PMBus erweitert SMBus um ein Gruppenprotokoll, mit dem mehrere solcher SMBus-Transaktionen in einer kombinierten Nachricht gesendet werden können. Das abschließende STOP gibt an, wann diese gruppierten Aktionen wirksam werden sollen. Beispielsweise könnte eine PMBus-Operation drei Netzteile neu konfigurieren (unter Verwendung von drei verschiedenen I2C-Zieladressen), und ihre neuen Konfigurationen würden zur gleichen Zeit wirksam werden: wenn sie dieses STOP empfangen.

Bis auf wenige Ausnahmen definieren weder I2C noch SMBus eine Message-Semantik, wie z. B. die Bedeutung von Datenbytes in Messages. Die Message-Semantik ist ansonsten produktspezifisch. Zu diesen Ausnahmen gehören Nachrichten, die an die allgemeine I2C-Aufrufadresse (0x00) oder an die SMBus-Alert-Response-Adresse adressiert sind, sowie Nachrichten, die am SMBus Address Resolution Protocol (ARP) für die dynamische Adresszuweisung und -verwaltung beteiligt sind.

In der Praxis verwenden die meisten Ziele Anfrage-Antwort-Kontrollmodelle, bei denen ein oder mehrere Bytes nach einem Schreibbefehl als Befehl oder Adresse behandelt werden. Diese Bytes bestimmen, wie nachfolgend geschriebene Bytes behandelt werden oder wie das Ziel auf nachfolgende Lesevorgänge reagiert. Die meisten SMBus-Operationen umfassen Ein-Byte-Befehle.

Beispiel für Nachrichtenübermittlung: 24C32 EEPROM

STMicroelectronics 24C08: serielles EEPROM mit I2C-Bus

Ein spezifisches Beispiel ist das EEPROM des Typs 24C32, das zwei Anforderungsbytes verwendet, die als Address High und Address Low bezeichnet werden. (Dementsprechend sind diese EEPROMs für reine SMBus-Hosts, die nur Ein-Byte-Befehle oder -Adressen unterstützen, nicht verwendbar). Diese Bytes werden zur Adressierung von Bytes innerhalb des 32 KBit (oder 4 kB) großen EEPROM-Adressraums verwendet. Die gleiche Zwei-Byte-Adressierung wird auch von größeren EEPROMs verwendet, wie dem 24C512, der 512 KBit (oder 64 kB) speichert. Für das Schreiben und Lesen von Daten in diese EEPROMs wird ein einfaches Protokoll verwendet: Die Adresse wird geschrieben, und dann werden die Daten bis zum Ende der Nachricht übertragen. Der Datentransferteil des Protokolls kann auf dem SMBus Probleme verursachen, da den Datenbytes keine Zählung vorangestellt wird und mehr als 32 Bytes auf einmal übertragen werden können. I2C EEPROMs, die kleiner als 32 kbit sind, wie der 2 kbit 24C02, werden oft am SMBus mit ineffizienten Einzelbyte-Datenübertragungen verwendet, um dieses Problem zu umgehen.

Eine einzige Nachricht schreibt in das EEPROM. Nach dem START sendet der Controller die Busadresse des Chips mit klarem Richtungsbit (Schreiben), dann die Zwei-Byte-Adresse der Daten im EEPROM und dann die zu schreibenden Datenbytes, beginnend bei dieser Adresse, gefolgt von einem STOP. Wenn mehrere Bytes geschrieben werden, müssen sich alle Bytes in derselben 32-Byte-Seite befinden. Während diese Bytes im Speicher gespeichert werden, reagiert das EEPROM nicht auf weitere I2C-Anfragen. (Das ist eine weitere Inkompatibilität mit SMBus: SMBus-Geräte müssen immer auf ihre Busadressen reagieren.)

Um ab einer bestimmten Adresse im EEPROM zu lesen, wird eine kombinierte Nachricht verwendet. Nach einem START schreibt der Controller zuerst die Busadresse dieses Chips mit dem Richtungsbit klar (schreiben) und dann die zwei Bytes der EEPROM-Datenadresse. Dann sendet er ein (wiederholtes) START und die Busadresse des EEPROMs mit gesetztem Richtungsbit (Lesen). Das EEPROM antwortet daraufhin mit den Datenbytes ab der angegebenen EEPROM-Datenadresse - eine kombinierte Nachricht: zuerst ein Schreiben, dann ein Lesen. Der Controller gibt nach jedem Lesebyte außer dem letzten Byte ein ACK und dann ein STOP aus. Das EEPROM inkrementiert die Adresse nach jedem übertragenen Datenbyte; Multi-Byte-Lesevorgänge können den gesamten Inhalt des EEPROMs mit einer kombinierten Nachricht abrufen.

Physikalische Schicht

I2C-Bus: Rp sind Pull-up-Widerstände, Rs sind optionale Vorwiderstände.

Auf der physikalischen Ebene sind sowohl SCL- als auch SDA-Leitungen als Open-Drain- (MOSFET) oder Open-Collector- (BJT) Bus ausgelegt, so dass für jede Leitung ein Pull-up-Widerstand erforderlich ist. Eine logische "0" wird ausgegeben, indem die Leitung auf Masse gezogen wird, und eine logische "1" wird ausgegeben, indem man die Leitung schweben lässt (hohe Ausgangsimpedanz), so dass der Pull-up-Widerstand sie hochzieht. Eine Leitung wird nie aktiv hochgezogen. Durch diese Verdrahtung können mehrere Knoten an den Bus angeschlossen werden, ohne dass es zu Kurzschlüssen aufgrund von Signalkonkurrenz kommt. Bei Hochgeschwindigkeitssystemen (und einigen anderen) kann eine Stromquelle anstelle eines Widerstands verwendet werden, um nur SCL oder sowohl SCL als auch SDA hochzuziehen, um eine höhere Buskapazität und schnellere Anstiegszeiten zu ermöglichen.

Eine wichtige Folge hiervon ist, dass mehrere Knoten die Leitungen gleichzeitig ansteuern können. Wenn ein beliebiger Knoten die Leitung mit einem niedrigen Wert ansteuert, ist sie niedrig. Knoten, die versuchen, eine logische Eins zu übertragen (d. h. die Leitung auf High zu lassen), können dies erkennen und daraus schließen, dass ein anderer Knoten zur gleichen Zeit aktiv ist.

Bei Verwendung auf SCL wird dies als Clock-Stretching bezeichnet und ist ein Flusskontrollmechanismus für Ziele. Bei Verwendung auf SDA wird dies Arbitrierung genannt und stellt sicher, dass es immer nur einen Sender gibt.

Im Ruhezustand sind beide Leitungen high. Um eine Transaktion zu starten, wird SDA auf low gezogen, während SCL auf high bleibt. Es ist illegal, eine Stoppmarke zu senden, indem man SDA wieder auf High setzt (obwohl eine solche "void message" normalerweise harmlos ist), also ist der nächste Schritt, SCL auf Low zu ziehen.

Abgesehen von den Start- und Stoppsignalen ändert sich die SDA-Leitung nur, während der Takt niedrig ist; die Übertragung eines Datenbits besteht darin, die Taktleitung hoch zu pulsieren, während die Datenleitung konstant auf dem gewünschten Pegel gehalten wird.

Während SCL niedrig ist, setzt der Sender (anfangs der Controller) SDA auf den gewünschten Wert und lässt (nach einer kleinen Verzögerung, damit sich der Wert ausbreiten kann) SCL hoch schweben. Der Controller wartet dann darauf, dass SCL tatsächlich auf High geht; dies wird durch die endliche Anstiegszeit des SCL-Signals (die RC-Zeitkonstante des Pull-up-Widerstands und die parasitäre Kapazität des Busses) verzögert und kann zusätzlich durch eine Taktverlängerung des Ziels verzögert werden.

Sobald SCL High ist, wartet der Controller eine Mindestzeit (4 μs für I2C mit Standardgeschwindigkeit), um sicherzustellen, dass der Empfänger das Bit gesehen hat, und zieht es dann wieder auf Low. Damit ist die Übertragung eines Bits abgeschlossen.

Nach jeweils 8 Datenbits in einer Richtung wird ein "Acknowledge"-Bit in die andere Richtung übertragen. Sender und Empfänger tauschen für ein Bit die Rollen, und der ursprüngliche Empfänger sendet ein einzelnes "0"-Bit (ACK) zurück. Wenn der Sender stattdessen ein "1"-Bit (NACK) sieht, lernt er das:

  • (Wenn der Controller an das Ziel sendet) Das Ziel ist nicht in der Lage, die Daten zu akzeptieren. Kein solches Ziel, Befehl nicht verstanden, oder nicht in der Lage, weitere Daten zu akzeptieren.
  • (Wenn das Ziel an den Controller sendet) Der Controller möchte, dass die Übertragung nach diesem Datenbyte beendet wird.

Nur die SDA-Leitung ändert während der Acknowledge-Bits ihre Richtung; SCL wird immer vom Controller gesteuert.

Nach dem Acknowledge-Bit wird die Taktleitung auf Low gesetzt, und der Controller kann eine der folgenden drei Aktionen ausführen:

  • Mit der Übertragung eines weiteren Datenbytes beginnen: Der Sender setzt SDA, und die Steuerung pulsiert SCL hoch.
  • Einen "Stop" senden: SDA auf low setzen, SCL auf high gehen lassen, dann SDA auf high gehen lassen. Dadurch wird der I2C-Bus freigegeben.
  • Senden Sie einen "Wiederholten Start": Setzen Sie SDA auf High, lassen Sie SCL auf High gehen und ziehen Sie dann SDA wieder auf Low. Dadurch wird eine neue I2C-Busnachricht gestartet, ohne den Bus freizugeben.

Taktdehnung mit SCL

Eine der wichtigsten Funktionen des I2C-Protokolls ist die Taktdehnung. Ein adressiertes Zielgerät kann die Taktleitung (SCL) nach dem Empfang (oder dem Senden) eines Bytes auf Low halten und damit anzeigen, dass es noch nicht bereit ist, weitere Daten zu verarbeiten. Der Controller, der mit dem Zielgerät kommuniziert, darf die Übertragung des aktuellen Bits nicht beenden, sondern muss warten, bis die Taktleitung tatsächlich auf High geht. Wenn das Ziel taktgebend ist, ist die Taktleitung immer noch niedrig (weil die Verbindungen Open-Drain sind). Das Gleiche gilt, wenn ein zweiter, langsamerer Controller versucht, den Takt gleichzeitig zu treiben. (Wenn es mehr als einen Controller gibt, verlieren normalerweise alle bis auf einen die Arbitrierung).

Der Controller muss warten, bis er beobachtet, dass die Taktleitung auf High geht, und eine zusätzliche minimale Zeit (4 μs für Standard 100 kbit/s I2C), bevor er den Takt wieder auf Low zieht.

Obwohl der Controller die SCL-Leitung auch so lange wie gewünscht niedrig halten kann (dies ist seit Rev. 6 des Protokolls nicht mehr erlaubt - Unterabschnitt 3.1.1), wird der Begriff "Taktdehnung" normalerweise nur verwendet, wenn Ziele dies tun. Obwohl theoretisch jeder Takt gestreckt werden kann, werden im Allgemeinen die Intervalle vor oder nach dem Bestätigungsbit verwendet. Handelt es sich bei dem Ziel beispielsweise um einen Mikrocontroller, könnte dessen I2C-Schnittstelle den Takt nach jedem Byte strecken, bis die Software entscheidet, ob eine positive Bestätigung oder ein NACK gesendet werden soll.

Die Taktdehnung ist die einzige Zeit in I2C, in der das Ziel SCL steuert. Viele Targets brauchen kein Clock-Stretching und behandeln SCL daher als reinen Eingang, der von keiner Schaltung angesteuert wird. Einige Controller, wie z. B. solche, die in kundenspezifischen ASICs zu finden sind, unterstützen möglicherweise kein Clock-Stretching; oft werden diese Geräte als "Zweidraht-Schnittstelle" und nicht als I2C bezeichnet.

Um einen minimalen Busdurchsatz zu gewährleisten, setzt SMBus Grenzen, wie weit Takte gestreckt werden dürfen. Hosts und Targets, die sich an diese Grenzen halten, können den Zugriff auf den Bus nicht länger als eine kurze Zeit blockieren, was bei reinen I2C-Systemen nicht gewährleistet ist.

Arbitrierung über SDA

Jeder Controller überwacht den Bus auf Start- und Stoppbits und beginnt keine Nachricht, während ein anderer Controller den Bus besetzt hält. Es kann jedoch vorkommen, dass zwei Controller etwa zur gleichen Zeit mit der Übertragung beginnen; in diesem Fall erfolgt eine Arbitrierung. Der Zielübertragungsmodus kann auch arbitriert werden, wenn eine Steuereinheit mehrere Ziele anspricht, aber dies ist weniger üblich. Im Gegensatz zu Protokollen (wie z.B. Ethernet), die zufällige Back-Off-Verzögerungen verwenden, bevor sie einen Wiederholungsversuch ausgeben, hat I2C eine deterministische Arbitrierungspolitik. Jeder Sender prüft den Pegel der Datenleitung (SDA) und vergleicht ihn mit den von ihm erwarteten Pegeln; stimmen sie nicht überein, hat dieser Sender die Arbitrierung verloren und steigt aus dieser Protokollinteraktion aus.

Wenn ein Sender SDA auf 1 setzt (kein Signal) und ein zweiter Sender es auf 0 setzt (auf Masse ziehen), ist das Ergebnis, dass die Leitung niedrig ist. Der erste Sender stellt dann fest, dass der Pegel der Leitung anders ist als erwartet, und schließt daraus, dass ein anderer Knoten sendet. Der erste Knoten, der eine solche Abweichung feststellt, verliert die Arbitrierung: er stellt die Ansteuerung von SDA ein. Wenn es sich um einen Controller handelt, stellt er auch die Ansteuerung von SCL ein und wartet auf einen STOPP; dann kann er versuchen, seine gesamte Nachricht erneut auszusenden. In der Zwischenzeit hat der andere Knoten keinen Unterschied zwischen dem erwarteten und dem tatsächlichen Pegel auf SDA festgestellt und setzt daher die Übertragung fort. Er kann dies ohne Probleme tun, weil das Signal bisher genau so war, wie er es erwartet hat; kein anderer Sender hat seine Nachricht gestört.

Wenn die beiden Steuerungen eine Nachricht an zwei verschiedene Ziele senden, "gewinnt" diejenige, die die niedrigere Zieladresse sendet, immer die Arbitrierung in der Adressstufe. Da die beiden Steuerungen Nachrichten an dieselbe Zieladresse senden können und sich die Adressen manchmal auf mehrere Ziele beziehen, muss die Arbitrierung manchmal bis in die Datenphasen fortgesetzt werden.

Die Arbitrierung kommt sehr selten vor, ist aber für die ordnungsgemäße Unterstützung mehrerer Controller erforderlich. Wie beim Clock-Stretching unterstützen nicht alle Geräte die Arbitrierung. Diejenigen, die dies tun, bezeichnen sich im Allgemeinen selbst als Unterstützer der "Multi-Controller"-Kommunikation.

Ein Fall, der in I2C-Implementierungen mit mehreren Controllern sorgfältig gehandhabt werden muss, ist der, dass die Controller miteinander sprechen. Ein Controller kann die Arbitrierung für eine eingehende Nachricht verlieren und muss seine Rolle vom Controller zum Target ändern, um seine eigene Adresse zu bestätigen.

In dem äußerst seltenen Fall, dass zwei Steuerungen gleichzeitig identische Nachrichten senden, wird die Kommunikation von beiden als erfolgreich angesehen, aber das Ziel sieht nur eine Nachricht. Aus diesem Grund muss, wenn auf ein Ziel von mehreren Steuerungen zugegriffen werden kann, jeder vom Ziel erkannte Befehl entweder idempotent sein oder es muss gewährleistet sein, dass er niemals von zwei Steuerungen gleichzeitig erteilt wird. (Beispielsweise muss ein Befehl, der nur von einer Steuereinheit erteilt wird, nicht idempotent sein, und es ist auch nicht notwendig, dass ein bestimmter Befehl idempotent ist, wenn ein Mechanismus zum gegenseitigen Ausschluss sicherstellt, dass nur eine Steuereinheit veranlasst werden kann, diesen Befehl zu einem bestimmten Zeitpunkt zu erteilen).

Arbitrierung im SMBus

Während I2C nur zwischen Controllern arbitriert, verwendet SMBus die Arbitrierung in drei zusätzlichen Kontexten, in denen mehrere Ziele auf den Controller antworten und eines seine Nachricht durchbekommt.

  • Obwohl es sich konzeptionell um einen Single-Controller-Bus handelt, fungiert ein Zielgerät, das das "Host-Notify-Protokoll" unterstützt, als Controller zur Durchführung der Benachrichtigung. Es belegt den Bus und schreibt eine 3-Byte-Nachricht an die reservierte "SMBus Host"-Adresse (0x08), wobei es seine Adresse und zwei Bytes Daten übergibt. Wenn zwei Ziele gleichzeitig versuchen, den Host zu benachrichtigen, wird eines von ihnen die Arbitrierung verlieren und muss es erneut versuchen.
  • Ein alternatives Zielbenachrichtigungssystem verwendet das separate SMBALERT#-Signal, um Aufmerksamkeit anzufordern. In diesem Fall führt der Host einen 1-Byte-Lesevorgang von der reservierten "SMBus Alert Response Address" (0x0C) durch, die eine Art Broadcast-Adresse ist. Alle alarmierenden Ziele antworten mit einem Datenbyte, das ihre eigene Adresse enthält. Wenn das Ziel seine eigene Adresse erfolgreich überträgt (und die Arbitrierung gegen andere gewinnt), hört es auf, diesen Interrupt auszulösen. Sowohl in diesem als auch im vorhergehenden Fall stellt die Arbitrierung sicher, dass die Nachricht eines Ziels empfangen wird und die anderen wissen, dass sie es erneut versuchen müssen.
  • SMBus unterstützt auch ein "Adressauflösungsprotokoll", bei dem Geräte eine 16-Byte-"universelle Geräte-ID" (UDID) zurücksenden. Es können mehrere Geräte antworten; das Gerät mit der niedrigsten UDID gewinnt das Schiedsverfahren und wird erkannt.

Arbitrierung in PMBus

PMBus Version 1.3 erweitert das SMBus-Alarm-Antwortprotokoll in seinem "Zone Read"-Protokoll. Ziele können in "Zonen" gruppiert werden, und alle Ziele in einer Zone können angesprochen werden, um zu antworten, wobei ihre Antworten maskiert (unerwünschte Informationen weggelassen), invertiert (so dass erwünschte Informationen als 0-Bits gesendet werden, die die Arbitrierung gewinnen) oder neu geordnet (so dass die wichtigsten Informationen zuerst gesendet werden) werden. Die Arbitrierung stellt sicher, dass die Antwort mit der höchsten Priorität als erstes an den Controller zurückgesendet wird.

PMBus reserviert die I2C-Adressen 0x28 und 0x37 für das Lesen bzw. Schreiben von Zonen.

Unterschiede zwischen den Modi

Für die I2C-Kommunikation gibt es mehrere mögliche Betriebsarten. Alle sind insofern kompatibel, als der 100 kbit/s-Standardmodus immer verwendet werden kann, aber die Kombination von Geräten mit unterschiedlichen Fähigkeiten auf demselben Bus kann zu Problemen führen:

  • Der Fast Mode ist hochkompatibel und verschärft lediglich einige der Timing-Parameter, um eine Geschwindigkeit von 400 kbit/s zu erreichen. Der Fast Mode wird von vielen I2C-Zielgeräten unterstützt, so dass ein Controller ihn verwenden kann, solange er weiß, dass die Buskapazität und die Pull-up-Stärke dies zulassen.
  • Der Fast Mode Plus erreicht bis zu 1 Mbit/s, wobei leistungsfähigere (20 mA) Treiber und Pull-ups verwendet werden, um schnellere Anstiegs- und Abfallzeiten zu erreichen. Die Kompatibilität mit Standard- und Fast-Mode-Bausteinen (mit 3-mA-Pull-Down-Fähigkeit) kann erreicht werden, wenn es eine Möglichkeit gibt, die Stärke der Pull-Ups bei der Kommunikation mit ihnen zu reduzieren.
  • Der Hochgeschwindigkeitsmodus (3,4 Mbit/s) ist mit normalen I2C-Bausteinen auf demselben Bus kompatibel, erfordert jedoch, dass der Controller über einen aktiven Pull-up auf der Taktleitung verfügt, der während Hochgeschwindigkeitsübertragungen aktiviert ist. Das erste Datenbit wird mit einer normalen steigenden Open-Drain-Taktflanke übertragen, die gedehnt werden kann. Für die verbleibenden sieben Datenbits und das ACK treibt der Controller den Takt zum richtigen Zeitpunkt hoch und das Ziel darf ihn nicht dehnen. Allen Hochgeschwindigkeitsübertragungen geht ein Ein-Byte-"Controller-Code" bei schneller oder Standardgeschwindigkeit voraus. Dieser Code dient drei Zwecken:
    1. Er teilt den Hochgeschwindigkeits-Zielgeräten mit, dass sie zu den Hochgeschwindigkeits-Timing-Regeln wechseln sollen,
    2. er stellt sicher, dass Geräte mit schneller oder normaler Geschwindigkeit nicht versuchen werden, an der Übertragung teilzunehmen (weil er nicht mit ihrer Adresse übereinstimmt), und
    3. da er den Controller identifiziert (es gibt acht Controller-Codes, und jeder Controller muss einen anderen verwenden), stellt er sicher, dass die Arbitrierung vor dem Hochgeschwindigkeits-Teil der Übertragung abgeschlossen ist, so dass der Hochgeschwindigkeits-Teil keine Rücksicht auf diese Fähigkeit nehmen muss.
  • Der Ultra-Fast-Modus ist im Wesentlichen ein schreibgeschütztes I2C-Subset, das mit anderen Modi nicht kompatibel ist, außer dass es einfach ist, die Unterstützung für diesen Modus zu einem bestehenden I2C-Schnittstellen-Hardware-Design hinzuzufügen. Es ist nur ein Controller zulässig, der die Datenleitungen jederzeit aktiv steuert, um eine Übertragungsrate von 5 Mbit/s zu erreichen. Taktdehnung, Arbitrierung, Leseübertragungen und Bestätigungen entfallen. Es ist vor allem für animierte LED-Anzeigen gedacht, bei denen ein Übertragungsfehler nur einen kurzen, unbedeutenden visuellen Ausrutscher verursachen würde. Die Ähnlichkeit mit anderen I2C-Bus-Modi beschränkt sich auf:
    • Die Start- und Stop-Bedingungen werden zur Abgrenzung von Übertragungen verwendet,
    • die I2C-Adressierung ermöglicht die gemeinsame Nutzung des Busses durch mehrere Zielgeräte ohne SPI-Bus-ähnliche Target-Select-Signale, und
    • ein neunter Takt wird pro übertragenem Byte gesendet, der die Position der unbenutzten Bestätigungsbits markiert.

Einige Hersteller bieten einen so genannten Nicht-Standard-Turbo-Modus mit einer Geschwindigkeit von bis zu 1,4 Mbit/s an.

In allen Modi wird die Taktfrequenz von dem/den Controller(n) gesteuert, und ein Bus, der länger als normal ist, kann durch Untertaktung mit einer niedrigeren Geschwindigkeit als der Nenngeschwindigkeit betrieben werden.

Verbindungen zwischen den Schaltkreisen

Eine 16-Bit-ADC-Karte mit I2C-Schnittstelle

I2C ist eine beliebte Schnittstelle für die Anbindung von Peripherieschaltungen an Prototyping-Systeme wie den Arduino und den Raspberry Pi. Für I2C gibt es keinen standardisierten Anschluss, aber die Entwickler von Platinen haben verschiedene Verdrahtungsschemata für I2C-Verbindungen entwickelt. Um mögliche Schäden durch das verkehrte Einstecken von 0,1-Zoll-Steckern zu minimieren, haben einige Entwickler vorgeschlagen, abwechselnde Signal- und Stromversorgungsanschlüsse der folgenden Verdrahtungsschemata zu verwenden: (GND, SCL, VCC, SDA) oder (VCC, SDA, GND, SCL).

In der überwiegenden Mehrheit der Anwendungen wird I2C so verwendet, wie es ursprünglich konzipiert wurde: Peripherie-ICs werden direkt mit einem Prozessor auf derselben Leiterplatte verdrahtet, und zwar über relativ kurze Entfernungen von weniger als 30 cm (1 Fuß) und ohne Steckverbinder. Mit einem Differentialtreiber kann eine alternative Version von I2C jedoch bis zu 20 Meter (möglicherweise über 100 Meter) über CAT5 oder ein anderes Kabel kommunizieren.

Mehrere Standardstecker können I2C-Signale übertragen. Der UEXT-Steckverbinder ist zum Beispiel für I2C geeignet; der 10-polige iPack-Steckverbinder überträgt I2C; der 6P6C-Steckverbinder von Lego Mindstorms NXT überträgt I2C; einige Leute verwenden die 8P8C-Steckverbinder und CAT5-Kabel, die normalerweise für die physikalische Schicht von Ethernet verwendet werden, um stattdessen differentiell kodierte I2C-Signale oder verstärkte Single-Ended-I2C-Signale zu übertragen; und alle HDMI- und die meisten DVI- und VGA-Anschlüsse übertragen DDC2-Daten über I2C.

Pufferung und Multiplexing

Wenn viele I2C-Geräte in einem System vorhanden sind, kann es erforderlich sein, Buspuffer oder Multiplexer einzubauen, um große Bussegmente in kleinere aufzuteilen. Dies kann notwendig sein, um die Kapazität eines Bussegments unter dem zulässigen Wert zu halten oder um zu ermöglichen, dass mehrere Geräte mit der gleichen Adresse durch einen Multiplexer getrennt werden können. Es gibt viele Arten von Multiplexern und Puffern, die alle die Tatsache berücksichtigen müssen, dass die I2C-Leitungen als bidirektional spezifiziert sind. Multiplexer können mit analogen Schaltern implementiert werden, die ein Segment mit einem anderen verbinden können. Analoge Schalter behalten den bidirektionalen Charakter der Leitungen bei, isolieren aber nicht die Kapazität eines Segments von einem anderen oder bieten Pufferungsmöglichkeiten.

Puffer können verwendet werden, um die Kapazität eines Segments von einem anderen zu isolieren und/oder um I2C über längere Kabel oder Leitungen zu übertragen. Puffer für bidirektionale Leitungen wie I2C müssen eines von mehreren Verfahren zur Verhinderung von Latch-up verwenden. I2C ist eine Open-Drain-Leitung, so dass Puffer auf der einen Seite einen Low-Wert liefern müssen, wenn sie auf der anderen Seite einen Low-Wert sehen. Eine Methode zur Verhinderung von Latch-up besteht darin, dass ein Puffer sorgfältig ausgewählte Eingangs- und Ausgangspegel hat, so dass der Ausgangspegel seines Treibers höher ist als sein Eingangsschwellenwert, wodurch er sich nicht selbst auslöst. Ein Puffer kann zum Beispiel einen Eingangsschwellenwert von 0,4 V für die Erkennung eines Low-Pegels haben, aber einen Low-Ausgangspegel von 0,5 V. Diese Methode erfordert, dass alle anderen Geräte auf dem Bus kompatible Schwellenwerte haben, und bedeutet oft, dass mehrere Puffer, die dieses Schema anwenden, nicht in Reihe geschaltet werden können.

Alternativ dazu gibt es andere Arten von Puffern, die Stromverstärker implementieren oder den Zustand verfolgen (d. h. welche Seite den Bus auf low gesetzt hat), um ein Latch-up zu verhindern. Die Zustandsmethode bedeutet typischerweise, dass während einer Übergabe ein unbeabsichtigter Impuls erzeugt wird, wenn eine Seite den Bus auf Low schaltet, dann die andere Seite ihn auf Low schaltet und dann die erste Seite loslässt (dies ist bei einer I2C-Bestätigung üblich).

Gemeinsame Nutzung von SCL durch mehrere Busse

Bei einem einzigen Controller ist es möglich, dass sich mehrere I2C-Busse dieselbe SCL-Leitung teilen. Die Pakete auf jedem Bus werden entweder nacheinander oder gleichzeitig gesendet. Dies ist möglich, weil die Kommunikation auf jedem Bus in abwechselnd kurze Perioden mit hohem SCL gefolgt von kurzen Perioden mit niedrigem SCL unterteilt werden kann. Und der Takt kann gedehnt werden, wenn ein Bus mehr Zeit in einem Zustand benötigt.

Vorteile sind die gleichzeitige Verwendung von Zielgeräten mit der gleichen Adresse und die Einsparung von Verbindungen oder ein schnellerer Durchsatz durch die gleichzeitige Verwendung mehrerer Datenleitungen.

Tabelle der Leitungszustände

Diese Tabellen zeigen die verschiedenen atomaren Zustände und Bitoperationen, die während einer I2C-Nachricht auftreten können.

Zustand der Leitung
Typ Inaktiver Bus

(N)

Start

(S)

Leerlauf

(i)

Stopp

(P)

Taktdehnung

(CS)

Hinweis Frei zur Beanspruchung der Arbitrierung Bus beansprucht (Controller) Bus beansprucht (Controller) Freigabe des Busses (Steuerung) Pausiert durch Ziel
SDA Passiver Pullup Fallende Flanke (Controller) Niedrig gehalten (Controller) Ansteigende Flanke (Controller) Unwichtig
SCL Passiver Pullup Passiver Pullup Passiver Pullup Passiver Pullup Niedrig gehalten (Ziel)
Zustand der Leitung
Typ Senden eines Datenbits (1) (0)

(SDA wird nach SCL gesetzt/abgetastet, um falsche Zustandserkennung zu vermeiden)

Antwort des Empfängers mit ACK-Bit

(Byte vom Absender empfangen)

Antwort des Empfängers mit NACK-Bit

(Byte vom Absender nicht empfangen)

Bitaufbau (Bs) Bereit zum Abtasten (Bx) Bitaufbau (Bs) ACK (A) Bitaufbau (Bs) NACK (A')
Hinweis Sender setzt Bit (Controller/Ziel) Abtastbit des Empfängers (Controller/Ziel) Sender Sender hi-Z Sender sieht SDA ist low Sender Sender hi-Z Sender sieht, dass SDA hoch ist
SDA Bit setzen (nachdem SCL fällt) Capture-Bit (nachdem SCL ansteigt) Vom Empfänger niedrig gehalten (nachdem SCL fällt) Vom Empfänger auf high (oder passiv high) gehalten (nachdem SCL fällt)
SCL Fallende Flanke (Controller) Ansteigende Flanke (Controller) Fallende Flanke (Controller) Ansteigende Flanke (Controller) Fallende Flanke (Controller) Ansteigende Flanke (Controller)
Leitungszustand (wiederholter Start)
Typ Einrichten für ein (Sr)-Signal nach einem ACK/NACK Wiederholter Start (Sr)
Hinweis Start hier von ACK Vermeiden des Stop-Zustands (P) Start hier von NACK Wie das Startsignal (S)
SDA Wurde für ACK niedrig gehalten Steigende Flanke Passiv hoch Passiv hoch Fallende Flanke (Controller)
SCL Fallende Flanke (Controller) Niedrig gehalten Ansteigende Flanke (Controller) Passiv hoch Passiver Pullup

Struktur der Adressierung

7-Bit-Adressierung

Feld: S I2C-Adressfeld R/W' A I2C-Nachrichten-Sequenzen... P
Typ Start Byte 1 ACK Byte X usw...

Der Rest der Lese- oder Schreib

Nachricht kommt hierher

Stopp
Bitposition in Byte X 7 6 5 4 3 2 1 0
7-Bit-Adresse pos 7 6 5 4 3 2 1
Hinweis MSB LSB 1 = Lesen
0 = Schreiben

10-Bit-Adressierung

Feld: S 10-Bit-Modus-Anzeige Oberes Adreßfeld R/W' A Unteres Adressfeld I2C-Nachrichtensequenzen P
Typ Start Byte 1 ACK Byte 2 Byte X usw.

Rest des Lese- oder Schreibvorgangs

Nachricht kommt hierher

Stopp
Bitposition in Byte X 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
Bit-Wert 1 1 1 1 0 X X X X X X X X X X X
10-Bit-Adresse pos 10 9 8 7 6 5 4 3 2 1
Hinweis Zeigt den 10-Bit-Modus an MSB 1 = Lesen LSB
0 = Schreiben

Reservierte Adressen im 7-Bit-Adressraum

Zwei Gruppen von Adressen sind für spezielle Funktionen reserviert:

  • 0000 XXX
  • 1111 XXX
Reserviert
Adresse
Index
8-Bit-Byte Beschreibung
7-Bit-Adresse R/W-Wert
MSB
(4-Bit)
LSB
(3-Bit)
1-Bit
1 0000 000 0 Allgemeiner Aufruf
2 0000 000 1 Startbyte
3 0000 001 X CBUS-Adresse
4 0000 010 X Reserviert für anderes Busformat
5 0000 011 X Reserviert für zukünftige Zwecke
6 0000 1XX X HS-Mode Controller Code
7 1111 1XX 1 Geräte-ID
8 1111 0XX X 10-Bit-Zieladressierung

SMBus reserviert einige zusätzliche Adressen. Insbesondere ist 0001 000 für den SMBus-Host reserviert, der von Controller-fähigen Geräten verwendet werden kann, 0001 100 ist die "SMBus-Alert-Response-Adresse", die vom Host nach einem Out-of-Band-Interrupt abgefragt wird, und 1100 001 ist die Standardadresse, die zunächst von Geräten verwendet wird, die eine dynamische Adresszuweisung vornehmen können.

Damit bleiben insgesamt 107 nicht reservierte 7-Bit-Adressen übrig, die I2C, SMBus und PMBus gemeinsam haben.

Nicht reservierte Adressen im 7-Bit-Adressraum

MSB (4-Bit) Typische Verwendung
0001 Digitalempfänger, SMBus
0010 TV-Videozeilendekoder, IPMB
0011 AV-Codecs
0100 Video-Encoder, GPIO-Erweiterungen
0101 ACCESS.bus, PMBus
0110 VESA DDC, PMBus
0111 Display-Controller
1000 TV-Signalverarbeitung, Audioverarbeitung, SMBus
1001 AV-Umschaltung, ADCs und DACs, IPMB, SMBus
1010 Arbeitsspeicher, Echtzeituhr
1011 AV-Prozessoren
1100 PLLs und Tuner, Modulatoren und Demodulatoren, SMBus
1101 AV-Prozessoren und Decoder, Audio-Leistungsverstärker, SMBus
1110 AV-Farbraumkonverter

Obwohl das MSB 1111 für die Geräte-ID und die 10-Bit-Zieladressierung reserviert ist, wird es auch von VESA-DDC-abhängigen Geräten wie Zeigegeräten verwendet.

Transaktionsformat

Eine I2C-Transaktion besteht aus einer oder mehreren Nachrichten. Jede Nachricht beginnt mit einem Startsymbol, und die Transaktion endet mit einem Stoppsymbol. Startsymbole nach dem ersten, die eine Nachricht, aber keine Transaktion beginnen, werden als wiederholte Startsymbole bezeichnet.

Jede Nachricht ist ein Lese- oder Schreibvorgang. Eine Transaktion, die aus einer einzigen Nachricht besteht, wird entweder als Lese- oder als Schreibtransaktion bezeichnet. Eine Transaktion, die aus mehreren Nachrichten besteht, wird als kombinierte Transaktion bezeichnet. Die häufigste Form ist eine Schreibnachricht, die geräteinterne Adressinformationen liefert, gefolgt von einer Lesenachricht.

Viele I2C-Geräte unterscheiden nicht zwischen einer kombinierten Transaktion und denselben Nachrichten, die als separate Transaktionen gesendet werden, aber nicht alle. Das Device-ID-Protokoll erfordert eine einzige Transaktion; die Zielgeräte dürfen nicht antworten, wenn sie ein Stopp-Symbol sehen. Konfigurations-, Kalibrierungs- oder Selbsttestmodi, die das Zielgerät zu einer ungewöhnlichen Reaktion veranlassen, werden ebenfalls oft automatisch am Ende einer Transaktion beendet.

Timing-Diagramm

Ablauf der Datenübertragung ⓘ
  1. Die Datenübertragung wird mit einer Startbedingung (S) eingeleitet, die dadurch signalisiert wird, dass SDA auf low gezogen wird, während SCL auf high bleibt.
  2. SCL wird auf Low gezogen, und SDA setzt den ersten Datenbitpegel, während SCL auf Low gehalten wird (während der Blue-Bar-Zeit).
  3. Die Daten werden abgetastet (empfangen), wenn SCL für das erste Bit (B1) ansteigt. Damit ein Bit gültig ist, darf sich SDA zwischen einer steigenden Flanke von SCL und der darauf folgenden fallenden Flanke nicht ändern (die gesamte grüne Balkenzeit).
  4. Dieser Vorgang wiederholt sich, wobei SDA wechselt, während SCL niedrig ist, und die Daten gelesen werden, während SCL hoch ist (B2 bis Bn).
  5. Auf das letzte Bit folgt ein Taktimpuls, während dessen SDA zur Vorbereitung des Stoppbits auf low gezogen wird.
  6. Eine Stoppbedingung (P) wird signalisiert, wenn SCL ansteigt, gefolgt von einem Anstieg von SDA.

Um eine falsche Marker-Erkennung zu vermeiden, gibt es eine Mindestverzögerung zwischen der fallenden SCL-Flanke und der Änderung von SDA sowie zwischen der Änderung von SDA und der steigenden SCL-Flanke. Beachten Sie, dass eine I2C-Nachricht mit n Datenbits (einschließlich Acknowledges) n + 1 Taktimpulse enthält.

Software-Entwurf

I2C eignet sich für ein "Bustreiber"-Softwaredesign. Software für angeschlossene Geräte wird so geschrieben, dass sie einen "Bustreiber" aufruft, der die eigentliche Low-Level-I2C-Hardware handhabt. Dadurch lässt sich der Treibercode für angeschlossene Geräte leicht auf andere Hardware portieren, einschließlich eines Bit-Banging-Designs.

Beispiel für Bit-Banging des I2C-Protokolls

Nachfolgend finden Sie ein Beispiel für das Bit-Banging des I2C-Protokolls als I2C-Controller. Das Beispiel ist in Pseudo-C geschrieben. Es veranschaulicht alle zuvor beschriebenen I2C-Funktionen (Clock-Stretching, Arbitration, Start/Stop-Bit, Ack/Nack).

// Hardwarespezifische Unterstützungsfunktionen, die angepasst werden MÜSSEN:
#define I2CSPEED 100
void I2C_delay(void);
bool read_SCL(void); // Rückgabe des aktuellen Pegels der SCL-Leitung, 0 oder 1
bool read_SDA(void); // Rückgabe des aktuellen Pegels der SDA-Leitung, 0 oder 1
void set_SCL(void); // SCL nicht treiben (Pin hochohmig setzen)
void clear_SCL(void); // Aktives Treiben des SCL-Signals auf low
void set_SDA(void); // SDA nicht treiben (Pin hochohmig setzen)
void clear_SDA(void); // SDA-Signal aktiv auf low setzen
void arbitration_lost(void); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

bool started = false; // globale Daten <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

void i2c_start_cond(void) {
  if (gestartet) { 
    // falls gestartet, eine Neustartbedingung ausführen
    // SDA auf 1 setzen
    set_SDA();
    I2C_delay();
    set_SCL();
    while (read_SCL() == 0) { // Taktstreckung
      // Diese Schleife sollte mit einem Timeout versehen werden
    } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

    // Wiederholte Start-Setup-Zeit, mindestens 4,7us
    I2C_delay();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  if (read_SDA() == 0) {
    arbitration_lost();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL ist high, SDA von 1 auf 0 setzen.
  clear_SDA();
  I2C_delay();
  clear_SCL();
  gestartet = true;
} <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

void i2c_stop_cond(void) {
  // SDA auf 0 setzen
  clear_SDA();
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  set_SCL();
  // Taktdehnung
  while (read_SCL() == 0) {
    // Timeout zu dieser Schleife hinzufügen.
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // Stoppbit-Einrichtungszeit, mindestens 4us
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL ist high, SDA von 0 auf 1 setzen
  set_SDA();
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  if (read_SDA() == 0) {
    arbitration_lost();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  gestartet = false;
} <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

// Ein Bit auf den I2C-Bus schreiben
void i2c_write_bit(bool bit) {
  if (bit) {
    set_SDA();
  } else {
    clear_SDA();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SDA-Änderungslaufzeit
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL hochsetzen, um anzuzeigen, dass ein neuer gültiger SDA-Wert verfügbar ist
  set_SCL(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // Warten auf das Lesen des SDA-Wertes durch das Ziel, mindestens 4us für den Standardmodus
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  while (read_SCL() == 0) { // Taktstreckung
    // Diese Schleife sollte mit einer Zeitüberschreitung versehen werden
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL ist high, jetzt sind die Daten gültig
  // Wenn SDA high ist, prüfen, dass niemand sonst SDA steuert
  if (bit && (read_SDA() == 0)) {
    arbitration_lost();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL in Vorbereitung auf die nächste Änderung auf low setzen
  clear_SCL();
} <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

// Ein Bit vom I2C-Bus lesen
bool i2c_read_bit(void) {
  bool bit; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // Lassen Sie das Ziel Daten treiben
  set_SDA(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // Warten auf das Schreiben des SDA-Werts durch das Ziel, mindestens 4us für den Standardmodus
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL hochsetzen, um anzuzeigen, dass ein neuer gültiger SDA-Wert verfügbar ist
  set_SCL(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  while (read_SCL() == 0) { // Taktstreckung
    // Diese Schleife sollte mit einer Zeitüberschreitung versehen werden
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // Warten auf das Schreiben des SDA-Werts durch das Ziel, mindestens 4us für den Standardmodus
  I2C_delay(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL ist high, Bit auslesen
  bit = read_SDA(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  // SCL auf low setzen als Vorbereitung für die nächste Operation
  clear_SCL(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  bit zurückgeben;
} <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

// Ein Byte auf den I2C-Bus schreiben. Rückgabe 0, wenn das Ziel dies bestätigt.
bool i2c_write_byte(bool send_start,
                    bool send_stop,
                    unsigned char byte) {
  Bit ohne Vorzeichen;
  bool nack; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  if (send_start) {
    i2c_start_cond();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  for (bit = 0; bit < 8; ++bit) {
    i2c_write_bit((byte & 0x80) != 0);
    byte <<= 1;
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  nack = i2c_read_bit(); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  if (send_stop) {
    i2c_stop_cond();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  return nack;
} <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

// Ein Byte vom I2C-Bus lesen
unsigned char i2c_read_byte(bool nack, bool send_stop) {
  unsigned char byte = 0;
  unsigned char bit; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  for (bit = 0; bit < 8; ++bit) {
    byte = (byte << 1) | i2c_read_bit();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  i2c_write_bit(nack); <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  if (send_stop) {
    i2c_stop_cond();
  } <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  return byte;
} <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

void I2C_delay(void) { 
  volatile int v;
  int i; <span title="Aus: Englische Wikipedia, Abschnitt &quot;Example of bit-banging the I2C protocol&quot;" class="plainlinks">[https://en.wikipedia.org/wiki/I²C#Example_of_bit-banging_the_I2C_protocol <span style="color:#dddddd">ⓘ</span>]</span>

  for (i = 0; i < I2CSPEED / 2; ++i) {
    v;
  }
}

Unterstützung für das Betriebssystem

  • Unter AmigaOS kann man die Komponente i2c.resource für AmigaOS 4.x und MorphOS 3.x oder die Shared Library i2c.library von Wilhelm Noeker für ältere Systeme verwenden.
  • Arduino-Entwickler können die "Wire"-Bibliothek verwenden.
  • Maximite unterstützt I2C-Kommunikation nativ als Teil seines MMBasic.
  • PICAXE verwendet die Befehle i2c und hi2c.
  • eCos unterstützt I2C für verschiedene Hardware-Architekturen.
  • ChibiOS/RT unterstützt I2C für verschiedene Hardware-Architekturen.
  • FreeBSD, NetBSD und OpenBSD bieten ebenfalls ein I2C-Framework mit Unterstützung für eine Reihe von gängigen Controllern und Sensoren.
    • Seit OpenBSD 3. 9 (veröffentlicht am 1. Mai 2006; vor 16 Jahren) testet ein zentrales i2c_scan-Subsystem alle möglichen Sensorchips auf einmal während des Bootens, indem es ein Ad-hoc-Gewichtungsschema und eine lokale Caching-Funktion zum Lesen von Registerwerten von den I2C-Zielen verwendet; dies macht es möglich, Sensoren auf allgemeiner Standard-i386/amd64-Hardware während des Bootens zu testen, ohne dass der Benutzer etwas konfigurieren muss oder eine merkliche Verzögerung beim Testen entsteht; die Abgleichprozeduren der einzelnen Treiber müssen sich dann nur noch auf einen String-basierten "Friendly-Name" für den Abgleich verlassen; als Ergebnis sind die meisten I2C-Sensortreiber automatisch standardmäßig in den entsprechenden Architekturen aktiviert, ohne dass dies negative Auswirkungen auf die Stabilität hat; einzelne Sensoren, sowohl I2C als auch andere, werden in das Userland durch das sysctl hw exportiert. Sensors Framework exportiert. Mit Stand vom März 2019 hat OpenBSD über zwei Dutzend Gerätetreiber auf I2C, die irgendeine Art von Sensor durch das hw.sensors-Framework exportieren, und die Mehrheit dieser Treiber ist standardmäßig in i386/amd64 GENERIC-Kerneln von OpenBSD vollständig aktiviert.
    • In NetBSD gibt es mehr als zwei Dutzend I2C-Zielgeräte, die über Hardwareüberwachungssensoren verfügen, die über das sysmon-envsys-Framework als Eigenschaftslisten zugänglich sind. Auf Allzweck-Hardware muss jeder Treiber sein eigenes Probing durchführen, daher sind alle Treiber für die I2C-Ziele in NetBSD in GENERIC i386/amd64-Builds standardmäßig deaktiviert.
  • Unter Linux wird I2C mit einem Gerätetreiber für das spezifische Gerät und einem weiteren für den I2C- (oder SMBus-) Adapter, an den es angeschlossen ist, behandelt. Hunderte solcher Treiber sind Teil der aktuellen Linux-Kernel-Versionen.
  • In Mac OS X gibt es etwa zwei Dutzend I2C-Kernelerweiterungen, die mit Sensoren kommunizieren, um Spannung, Strom, Temperatur, Bewegung und andere physikalische Zustände zu erfassen.
  • In Microsoft Windows wird I2C von den jeweiligen Gerätetreibern eines Großteils der in der Industrie verfügbaren Hardware implementiert. Für HID-Embedded/SoC-Geräte verfügen Windows 8 und höher über einen integrierten I²C-Bustreiber.
  • In Windows CE wird I2C von den entsprechenden Gerätetreibern für einen Großteil der in der Branche erhältlichen Hardware implementiert.
  • Unison OS, ein POSIX RTOS für IoT, unterstützt I2C für verschiedene MCU- und MPU-Hardwarearchitekturen.
  • In RISC OS wird I2C über eine generische I2C-Schnittstelle vom IO-Controller bereitgestellt und vom Betriebssystem-Modulsystem unterstützt.
  • In den Betriebssystemen Sinclair QDOS und Minerva QL wird I2C durch eine Reihe von Erweiterungen unterstützt, die von TF Services bereitgestellt werden.

Entwicklungswerkzeuge

Bei der Entwicklung oder Fehlersuche in Systemen, die I2C verwenden, kann die Sichtbarkeit auf der Ebene der Hardwaresignale wichtig sein.

Host-Adapter

Es gibt eine Reihe von I2C-Hostadapter-Hardwarelösungen für die Herstellung einer I2C-Controller- oder Target-Verbindung zu Host-Computern, auf denen Linux, Mac oder Windows läuft. Die meisten Optionen sind USB-zu-I2C-Adapter. Nicht alle von ihnen erfordern proprietäre Treiber oder APIs.

Protokoll-Analysatoren

I2C-Protokollanalysatoren sind Tools, die einen I2C-Bus abtasten und die elektrischen Signale dekodieren, um eine übergeordnete Ansicht der auf dem Bus übertragenen Daten zu liefern.

Logik-Analysatoren

Bei der Entwicklung und/oder Fehlersuche am I2C-Bus kann die Untersuchung von Hardwaresignalen sehr wichtig sein. Logikanalysatoren sind Werkzeuge, die Signale sammeln, analysieren, dekodieren und speichern, so dass man sich die Hochgeschwindigkeitswellenformen in aller Ruhe ansehen kann. Logikanalysatoren zeigen Zeitstempel für jede Änderung des Signalpegels an, was bei der Suche nach Protokollproblemen hilfreich sein kann. Die meisten Logikanalysatoren sind in der Lage, Bussignale in High-Level-Protokolldaten zu dekodieren und ASCII-Daten anzuzeigen.

Beschränkungen

Bei Systemen mit geringem Stromverbrauch können die Pull-up-Widerstände mehr Strom verbrauchen als der gesamte Rest des Designs zusammen. In diesen Fällen werden die Widerstände oft von einer schaltbaren Spannungsquelle gespeist, z. B. einem DIO von einem Mikrocontroller. Die Pull-ups begrenzen auch die Geschwindigkeit des Busses und verursachen geringe zusätzliche Kosten. Daher wenden sich einige Entwickler anderen seriellen Bussen zu, z. B. I3C oder SPI, die keine Pull-ups benötigen.

Die Zuweisung von Zieladressen ist eine Schwäche von I2C. Sieben Bits sind zu wenig, um Adressenkollisionen zwischen den vielen tausend verfügbaren Geräten zu verhindern. Das Problem der Adressenkollisionen zwischen verschiedenen Herstellern wird dadurch entschärft, dass die Hersteller Pins vorsehen, über die die Zieladresse auf eine von wenigen Adressoptionen pro Gerät eingestellt werden kann, was den Anschluss mehrerer identischer Geräte ermöglicht. Typisch sind zwei oder drei Pins, und bei vielen Geräten gibt es drei oder mehr Verdrahtungsoptionen pro Adresspin.

10-Bit-I2C-Adressen sind noch nicht weit verbreitet, und viele Host-Betriebssysteme unterstützen sie nicht. Auch das komplexe SMBus-"ARP"-Schema für die dynamische Zuweisung von Adressen wird nicht unterstützt (außer bei PCI-Karten mit SMBus-Präsenz, für die es erforderlich ist).

Die automatische Buskonfiguration ist ein verwandtes Thema. Eine bestimmte Adresse kann von einer Reihe verschiedener protokoll-inkompatibler Geräte in verschiedenen Systemen verwendet werden, und kaum ein Gerätetyp kann zur Laufzeit erkannt werden. So kann beispielsweise 0x51 von einem 24LC02 oder 24C32 EEPROM mit inkompatibler Adressierung verwendet werden; oder von einer PCF8563 RTC, die von beiden nicht zuverlässig unterschieden werden kann (ohne den Gerätezustand zu ändern, was möglicherweise nicht erlaubt ist). Die einzigen zuverlässigen Konfigurationsmechanismen, die den Hosts zur Verfügung stehen, sind Out-of-Band-Mechanismen wie Tabellen, die von der System-Firmware bereitgestellt werden und in denen die verfügbaren Geräte aufgelistet sind. Auch dieses Problem kann teilweise durch ARP in SMBus-Systemen gelöst werden, insbesondere wenn Hersteller- und Produktkennungen verwendet werden; dies hat sich jedoch nicht wirklich durchgesetzt. Die Version 3 der I2C-Spezifikation fügt einen Geräte-ID-Mechanismus hinzu.

I2C unterstützt eine begrenzte Anzahl von Geschwindigkeiten. Hosts, die die Multi-Megabit-Geschwindigkeiten unterstützen, sind selten. Die Unterstützung für die Fm+-Geschwindigkeit von 1 Mbit/s ist weiter verbreitet, da es sich bei der Elektronik um einfache Varianten dessen handelt, was bei niedrigeren Geschwindigkeiten verwendet wird. Viele Geräte unterstützen die Geschwindigkeit von 400 kbit/s nicht (zum Teil, weil SMBus sie noch nicht unterstützt). I2C-Knoten, die in Software implementiert sind (anstelle von dedizierter Hardware), unterstützen möglicherweise nicht einmal die Geschwindigkeit von 100 kbit/s; daher ist der gesamte in der Spezifikation festgelegte Bereich selten nutzbar. Alle Geräte müssen zumindest teilweise die höchste verwendete Geschwindigkeit unterstützen, da sie sonst ihre Geräteadresse fälschlicherweise erkennen.

Den Geräten ist es erlaubt, die Taktzyklen so zu dehnen, dass sie ihren besonderen Bedürfnissen entsprechen, was die von schnelleren Geräten benötigte Bandbreite einschränken und die Latenzzeiten bei Gesprächen mit anderen Geräteadressen erhöhen kann. Die Buskapazität stellt ebenfalls eine Grenze für die Übertragungsgeschwindigkeit dar, insbesondere wenn keine Stromquellen verwendet werden, um die Signalanstiegszeiten zu verringern.

Da es sich bei I2C um einen gemeinsam genutzten Bus handelt, besteht die Möglichkeit, dass ein beliebiges Gerät einen Fehler hat und den gesamten Bus lahmlegt. Wenn beispielsweise ein Gerät die SDA- oder SCL-Leitung auf Low hält, verhindert dies, dass der Controller START- oder STOP-Befehle zum Zurücksetzen des Busses senden kann. Daher ist es üblich, ein Reset-Signal vorzusehen, das eine externe Methode zum Zurücksetzen der Busgeräte bietet. Viele Geräte verfügen jedoch nicht über einen dedizierten Reset-Pin, so dass der Entwickler gezwungen ist, eine Schaltung einzubauen, die es ermöglicht, die Geräte mit Strom zu versorgen, wenn sie zurückgesetzt werden müssen.

Aufgrund dieser Einschränkungen (Adressverwaltung, Buskonfiguration, mögliche Fehler, Geschwindigkeit) haben nur wenige I2C-Bussegmente auch nur ein Dutzend Geräte. Es ist üblich, dass Systeme mehrere solcher Segmente haben. Ein Segment kann für Hochgeschwindigkeits-Bausteine reserviert sein, um die Stromversorgung mit geringer Latenz zu verwalten. Ein anderes könnte zur Steuerung einiger weniger Geräte verwendet werden, bei denen Latenz und Durchsatz keine Rolle spielen; ein weiteres Segment könnte nur zum Lesen von EEPROM-Chips verwendet werden, die Zusatzkarten beschreiben (wie der SPD-Standard, der mit DRAM-Sticks verwendet wird).

Abgeleitete Technologien

I2C ist die Grundlage für den ACCESS.bus, die VESA Display Data Channel (DDC)-Schnittstelle, den System Management Bus (SMBus), Power Management Bus (PMBus) und den Intelligent Platform Management Bus (IPMB, eines der Protokolle von IPMI). Diese Varianten unterscheiden sich in den Spannungs- und Taktfrequenzbereichen und können über Interruptleitungen verfügen.

Hochverfügbare Systeme (AdvancedTCA, MicroTCA) verwenden 2-Wege-redundantes I2C für das Shelf-Management. Die I2C-Fähigkeit mehrerer Controller ist in diesen Systemen eine Voraussetzung.

TWI (Two-Wire Interface) oder TWSI (Two-Wire Serial Interface) ist im Wesentlichen derselbe Bus, der auf verschiedenen System-on-Chip-Prozessoren von Atmel und anderen Anbietern implementiert ist. Die Hersteller verwenden den Namen TWI, obwohl I2C seit dem 07.11.2014 kein eingetragenes Warenzeichen mehr ist. Markenschutz besteht nur für das jeweilige Logo (siehe obere rechte Ecke), und die Patente auf I2C sind inzwischen erloschen. Nach Angaben von Microchip Technology gibt es zwischen TWI und I2C einige Unterschiede. Einer davon ist, dass TWI kein START-Byte unterstützt.

In einigen Fällen deutet die Verwendung des Begriffs "Zweidrahtschnittstelle" auf eine unvollständige Implementierung der I2C-Spezifikation hin. Eine häufige Einschränkung ist die fehlende Unterstützung von Arbitrierung oder Clock-Stretching, was für einen einzelnen Controller, der mit einfachen Zielen kommuniziert, die den Takt nie strecken, immer noch nützlich ist.

Der MIPI I3C-Sensorschnittstellenstandard (I3C) ist eine Weiterentwicklung von I2C, die 2017 entwickelt wird.

Bussystem

I²C ist als Master-Slave-Bus konzipiert. Ein Datentransfer wird immer durch einen Master initiiert; der über eine Adresse angesprochene Slave reagiert darauf. Mehrere Master sind möglich (Multimaster-Betrieb). Wenn im Multimaster-Betrieb ein Master-Baustein auch als Slave arbeitet, kann ein anderer Master direkt mit ihm kommunizieren, indem er ihn als Slave anspricht.

Übertragungsprotokoll

Der Beginn einer Übertragung wird mit dem Start-Signal vom Master angezeigt, dann folgt die Adresse. Diese wird durch das ACK-Bit vom entsprechenden Slave bestätigt. Abhängig vom R/W-Bit werden nun Daten byteweise geschrieben (Daten an Slave) oder gelesen (Daten vom Slave). Das ACK beim Schreiben wird vom Slave gesendet und beim Lesen vom Master. Das letzte Byte eines Lesezugriffs wird vom Master mit einem NACK quittiert, um das Ende der Übertragung anzuzeigen. Eine Übertragung wird durch das Stop-Signal beendet. Alternativ kann auch ein Repeated-Start am Beginn einer erneuten Übertragung gesendet werden, ohne die vorhergehende Übertragung mit einem Stop-Signal zu beenden.

Alle Bytes werden dabei „Most Significant Bit First“ übertragen.

Für den High-Speed-Mode wird zuerst im Fast oder Standard Mode ein Master-Code geschickt, bevor auf die erhöhte Frequenz umgeschaltet wird. Dadurch wird zum einen der High-Speed-Mode signalisiert, zum anderen haben nicht High-Speed-taugliche Busteilnehmer die Chance, innerhalb ihrer Spezifikation zu erkennen, dass sie nicht angesprochen wurden. Im Multimasterbetrieb muss jeder Busmaster einen eigenen Master-Code benutzen. So ist sichergestellt, dass die Busarbitrierung (s. u.) abgeschlossen ist, bevor in den High-Speed-Mode gewechselt wird.

Arbitrierung im Multimaster-Betrieb

Die Arbitrierung (Zugriffsregelung auf den Bus) ist durch die Spezifikation geregelt: Der Bus ist zwischen Start- und Stoppsignal belegt. Busmaster müssen daher immer auf Start- und Stoppsignale achten, um den Überblick über den Busstatus zu behalten. So können sie warten, bis der Bus frei ist, sollte (evtl. unvorhergesehen) eine Übertragung anstehen.

Sollten mehrere Busmaster gleichzeitig mit einer Transaktion starten wollen, so sehen sie den Bus als frei an und starten gleichzeitig mit der Übertragung. Sind die Master unterschiedlich schnell, erfolgt die Übertragung nun zunächst so schnell, wie der langsamste der beteiligten Busmaster arbeitet, da das Taktsignal eines langsameren Busmasters per Clock-Stretching die schnelleren ausbremst. Alle Busmaster lauschen auf die von ihnen selbst gesendeten Daten. In dem Augenblick, wenn ein Busmaster eine „0“ und ein anderer eine „1“ übertragen will, nimmt die Bus-Leitung (aufgrund der Wired-And-Schaltung aller Busteilnehmer) „0“-Pegel an. Gemäß dem I²C-Protokoll verlieren in diesem Augenblick die Busmaster mit der „1“ den Bus, ziehen sich zurück und warten auf das Stoppsignal, um dann ihr Glück erneut zu versuchen. Die anderen Busmaster machen weiter, bis schließlich nur noch einer übrigbleibt. Sollte ein unterlegener Busmaster-Baustein auch Slave-Dienste anbieten, muss er allerdings gleichzeitig darauf achten, ob der gewinnende Busmaster ihn gerade ansprechen will und daher gerade dabei ist, ihn zu adressieren.

Das Verfahren geht so weit, dass gar keine Arbitrierung stattfindet, wenn mehrere Busmaster zufällig – über mehrere Bytes hinweg von Anfang bis zum Abschluss ihrer jeweiligen Transaktionen hinweg – identische Daten an denselben Slave-Baustein senden: Die betreffenden Busmaster merken nichts voneinander – eventuelles Clock-Stretching durch einen langsameren Master ist gemäß Protokoll nicht von Clock-Stretching durch den Slave zu unterscheiden; der angesprochene Slave-Baustein kommuniziert mit den betreffenden Busmastern gleichzeitig, ohne dass es von den Beteiligten bemerkt wird. Diese Tatsache ist zu berücksichtigen, und ihr muss, sofern sie sich störend auswirken könnte, anderweitig Abhilfe geschaffen werden.

Verwendung

Serielles EEPROM mit I²C-Bus von STMicroelectronics

Eine Eigenschaft von I²C ist die Tatsache, dass ein Mikrocontroller ein ganzes Netzwerk an integrierten Schaltungen mit nur zwei I/O-Pins und einfacher Software kontrollieren kann. Busse dieses Typs wurden realisiert, da ein nicht unerheblicher Teil der Kosten einer integrierten Schaltung und der verwendeten Leiterplatte von der Größe des Gehäuses und der Anzahl der Pins abhängt. Ein großes IC-Gehäuse hat mehr Pins, braucht mehr Platz auf der Leiterplatte und hat mehr Verbindungen, die versagen können. All das steigert die Produktions- und Testkosten.

Obwohl langsamer als neuere Bus-Systeme, ist I²C wegen des geringen Aufwands vorteilhaft für Peripheriegeräte, die nicht schnell zu sein brauchen. Häufig wird er für die Übertragung von Steuer- und Konfigurationsdaten verwendet. Beispiele sind Lautstärkeregler, Analog-Digital- oder Digital-Analog-Wandler mit niedriger Abtastrate, Echtzeituhren, kleine, nichtflüchtige Speicher oder bidirektionale Schalter und Multiplexer. Auch elektronische Sensoren haben oft einen Analog-Digital-Wandler mit I²C-Schnittstelle integriert.

Während des Betriebes können Chips zum Bus hinzugefügt oder entfernt werden (Hot-Plugging).

I²C wird auch als Basis für ACCESS.bus und VESAs Monitordaten-Interface (Display Data Channel, kurz DDC) benutzt. Der vom Prozessorhersteller Intel für die Kommunikation von Mainboard-Komponenten definierte SMBus ist dem I²C-Bus sehr ähnlich, die meisten ICs erlauben einen Betrieb an beiden Bussen.

Große Bedeutung hatte das I²C-Protokoll in der Vergangenheit im Chipkartenbereich. Die in Deutschland bis Ende 2014 verwendete Krankenversichertenkarte war eine I²C-Karte, d. h. unter den goldenen Kontaktflächen der Chipkarte befand sich ein einfaches I²C-EEPROM, das vom Kartenleser über das I²C-Protokoll ausgelesen und beschrieben werden konnte.

Stabilität

Das Protokoll des I²C-Bus ist von der Definition her recht einfach, aber auch recht störanfällig. Diese Tatsache schränkt die Verwendung auf störarme Umgebungen ein, wo weder mit Übersprechen, Rauschen, EMV-Problemen noch mit Kontaktproblemen (Stecker, Buchsen) zu rechnen ist. Auch ist er ungeeignet zur Überbrückung größerer Entfernungen, wie es beispielsweise für Feldbusse typisch ist.

Der Bus kann jedoch mit speziellen Treibern auf einen höheren Strom- oder Spannungspegel umgesetzt werden, wodurch der Störabstand und die mögliche Leitungslänge steigen. Ein noch größerer Störabstand ist durch eine Umsetzung auf den physikalischen Layer des CAN-Busses möglich, der mit differentiellen Open-Collector-Signalen arbeitet. Störungen sowohl des SDA- als auch des SCL-Signals resultieren in fehlerhaft übertragenen Daten, die vor allem bei Störungen auf SDA oft nicht erkannt werden können. Lediglich bei geringen, zeitlich begrenzten Störungen, z. B. weit oberhalb der Signalfrequenz, kann das System mittels Signalverarbeitung stabiler gemacht werden.

Die eigentliche I²C-Spezifikation beinhaltet (anders als die SMBus-Spezifikation) keinen Timeout; dadurch kann es unter bestimmten Umständen dazu kommen, dass Busteilnehmer den Bus blockieren. Falls ein Slave-Chip gerade die Datenleitung auf „0“ zieht, während der Master den Transfer (beispielsweise durch einen Reset) abbricht, bleibt die Datenleitung für unbestimmte Zeit auf „0“. Somit bleibt der gesamte I²C-Bus mit allen angeschlossenen Teilnehmern (Chips) blockiert. Daher sollen im Falle eines Resets auch alle Busteilnehmer zurückgesetzt werden, ggf. durch Unterbrechen der Spannungsversorgung. Alternativ wird ein Bus clear durchgeführt: Der Master generiert bis zu neun Taktimpulse; spätestens dann sollte die Datenleitung freigegeben sein. Selbst wenn sich der Slave-Baustein noch mitten in einer Übertragung befindet und die Datenleitung nur freigegeben ist, weil er gerade eine „1“ ausgibt, wird er (bzw. dessen I²C-Komponente) durch das nächste Start-Signal zurückgesetzt. Analog Devices empfiehlt, zunächst ein Stopp-Signal zu senden.

Erweiterungen

Die MIPI Alliance hat 2014 ein I3C genanntes, zu I²C abwärtskompatibles Interface vorgestellt. Es wird als Nachfolger von I²C propagiert. Es enthält Erweiterungen wie eine höhere Übertragungsgeschwindigkeit (High Data Rate – HDR) und kann damit bei mittleren Geschwindigkeiten auch das Serial Peripheral Interface (SPI) ersetzen.