Unterrichts- und Lernmaterial für Mikrocontroller
Unterrichts- und Lernmaterial fürMikrocontroller

1 - Der I2C Bus

Der I2C-Bus ist als Zweidrahtverbindung zwischen einem Master (Controller) und an ihn angeschlossene Sensoren oder IC-Bausteine (Slaves) für kurze Distanzen konzipiert worden. Nur der Master steuert die Verbindung zwischen ihm und den Slaves.

An einer Kommunikation können auch mehrere Master und bis zu 128 Slaves beteiligt sein. Die beiden dazu notwendigen Datenleitungen, neben den Versorgungsspannungsleitungen, bezeichnen wir mit SDA (Datenleitung) und SCL (Taktleitung); SDA und SCL bilden den Datenbus.

Die Daten- und Taktleitung sind open drain, was so viel heißt, die angeschlossenen elektronischen Bauteile können ihren Ausgang auf LOW legen, aber nicht aktiv auf HIGH. Letzteres erfolgt über Pull-up Widerstände RPU, die in beiden Leitungen einmal eingebaut sind und deren Wert irgendwo zwischen 1kOhm und 10kOhm liegen kann.

Abbildung 1 - I2C-Bus mit zwei Mikrocontrollern sowie den Pull-up Widerständen für die SDA- und SCL Leitung

2 - Die I2C Adressierung

Nur Master können Slaves ansprechen, umgekehrt geht das nicht - also eine klare Hierarchie. Um eine Kommunikation zu beginnen, muss der Master den Bus übernehmen und die Adresse des Slaves angeben, mit dem er Daten austauschen möchte.

Am häufigsten werden für die Adressierung 7 Bit verwendet (es gibt auch eine 10 Bit Variante). Damit stehen insgesamt 2^7 = 128 Adressen für 128 Geräte (Slaves) zur Verfügung. Bei der Übertragung einer 7 Bit Adresse werden immer 8 Bit gesendet. Das 8. Bit (LSB) informiert den Slave, ob der Master zum Slave überträgt (write) oder vom Slave zum Master etwas gesendet werden soll (read).

  • 0 bedeutet, der Master überträgt an den Slave (write)
    
    1 bedeutet, der Master liest vom Slave (read)
    

Der Master teilt dem Slave mit, ob er Daten senden oder empfangen möchte und danach werden die Daten (entweder vom Master oder vom Slave) auf den Bus gelegt. Mit Abschluss des Lese-/Schreibvorgangs gibt der Master den Bus wieder frei.

Die Start- und Stoppsequenzen sind die einzigen Vorgänge, bei denen die SDA-Leitung von HIGH auf LOW (Start) bzw. LOW auf HIGH (Stopp) gelegt werden darf, während gleichzeitig die SCL-Leitung auf HIGH liegt.

Abbildung 2 - Start- und Stoppsequenz

Daten werden in Sequenzen von 8 Bit übertragen. Die Bits werden auf die SDA Leitung gelegt (MSB zuerst). Auf SCL wird eine Impulsfolge gelegt; nach jeweils 8 übertragenen Bit sendet das Empfangsgerät ein LOW-ACK-Bit (Acknowledge LOW) zurück und zeigt damit an, dass es weitere 8 Bit empfangen kann. Wird ein HIGH-ACK-Bit zurückgesandt, beendet der Master die Übertragung und sendet eine Stopp-Sequenz.

Abbildung 3 - 8-Bit Datenfolge wird übertragen; das ACK-Bit (9. Bit) ist LOW; die Übertragung wird fortgesetzt.

Die Adressierung eines Slaves

Die Adresse eines Slaves baut sich aus sieben Bit auf, die der Hersteller eines I2C-Bauteils in seinem Datenblatt veröffentlicht. Von diesen sieben Bit sind häufig die höchstwertigen fest vorgegeben und die niederwertigen variabel und durch den Anwender einstellbar.

 

Beispiel

Als I2C-Baustein nehmen wir den LED Treiberbaustein TLC59116. Im Datenblatt des Herstellers wird seine Adresse (device address) auf S. 23 beschrieben. Von den sieben Adressbits sind die ersten drei fest vorgegeben, während sich die letzten vier über Hardwareeinstellungen individuell durch den Nutzer einstellen lassen. In diesem Beispiel werden die Pins [A3:A0] hardwaremäßig auf 0 gelegt. Die sich daraus ergebende Slaveadresse zeigt Abb. 4.

Abbildung 4 - Aufbau einer Slaveadresse am Beispiel des LED Treiberbausteins TLC59116

Reihenfolge der Befehlssequenzen bei einer I2C-Verbindung

Die Kontaktaufnahme eines Masters (in diesem Beispiel ein Arduino UNO) mit einem Slave (hier: TLC59116) über einen I2C-Bus wird ebenfalls im Datenblatt des entsprechenden Bauteils beschrieben (Application Notes oder Application Information). Dort wird beschrieben, in welcher Reihenfolge in spezifische Register des Bauteils geschrieben oder aus ihnen etwas ausgelesen wird.

Abbildung 5 - Ablauffolge für das Schreiben in ein bestimmtes Register

Für den TLC59116 sind die Anwendungsinformationen auf Seite 26ff beschrieben und können dort nachgeschlagen werden. Um in ein bestimmtes Register etwas hineinzuschreiben, wird der Vorgang mit einer Startsequenz (S) und der Angabe der Slaveadresse (wer wird angeschrieben?) gestartet. Es handelt sich um einen Schreibvorgang, deshalb wird das R/W-Flag auf 0 gesetzt. Die Slaveadresse lautet damit:

  • TLC59116-Adresse (w): 1100_0000 oder 0xC0

bei einem Schreibvorgang und

  • TLC59116-Adresse (r): 1100_0001 oder 0xC1

bei einem Lesevorgang.

Adressierung - 7-Bit oder 8-Bit?

Arbeitet man mit einem Arduino-UNO und der I2C-Bibliothek Wire.h, dann errechnet sich die korrekte Slaveadresse dadurch, dass die 7-Bit Adresse (1100_000 ohne das R/W Bit) des Slave um eine Position nach rechts (in Richtung des R/W Bits) verschoben wird (Abb. 6).

Abbildung 6 - Die 7-Bit Adresse wird um eine Position nach rechts verschoben.

Wie man Abb. 6 entnehmen kann, wird aus der Slaveadresse 0xC0 (dezimal: 192) durch die Verschiebung 0x60 (dezimal: 96).

Bei der Programmiersoftware ist zu prüfen, ob bei einer I2C-Adressierung die 7-Bit Adresse ohne das R/W-Bit oder die 8-Bit Adresse mit R/W-Bit gemeint ist und dann entsprechend dem oben Gesagten zu verfahren.

Experiment 1 - Eine LED mit dem TLC59116 einschalten

Experiment 1 - LED einschalten
Material
  • 1x  Arduino UNO
  • 1x  I2C-Bus-LED Treiber Modul (Fa. ELV)
  • 1x  USB-Verbindungskabel
  • 4x  Steckdraht
Aufgaben
  • Verbinde das Arduino UNO Board mit dem Treiber-Modul.
  • Verbinde das Arduino Board über das USB-Kabel mit dem PC und übertrage anschließend das Programm led_TLC59116_1.ino in den Editor und speichere es ab.
  • Starte das Programm und überprüfe, ob LED1 auf dem Modulboard eingeschaltet wird.

Das Programm LED_TLC59116_1.ino

Wie arbeitet das Programm LED_TLC59116_1.ino?

In der Methode loop() gibt es drei "neue" Befehle und einen in der Methode setup().Was sie bewirken, soll die kurze Übersicht zeigen.

 

Wire.begin(optional: address)

Initiiert die Wire-Bibliothek und - falls die 7-Bit Slaveadresse angegeben wird - wird sie auf dem I2C-Bus als Slave, bei fehlender Adresse als Master gesehen.

Parameter

address             7-Bit Slaveadresse (optional); wenn nicht angegeben, Verbindung als Master.

In der Methode loop() werden drei Funktionen aus Wire.h aufgerufen. Gestartet wird mit

<>·Wire.beginTransmission(22);

 

Wire.beginTransmission(address)

Startet eine Übertragung zum I2C Slave mit der angegebenen Adresse (address). Anschließend werden Bytes mit der Funktion write() übertragen und mit der Funktion endTransmission() abgeschlossen.

Parameter

address             7-Bit Adresse des Slave-Device.

Die Adresse 96 ist hier dem Datenblatt zum TLC59116 des Herstellers entnommen. Die Syntax der Funktion

  • Wire.write()
    

zeigt das Programm LED_TLC59116.ino.

 

Wire.write()

Es werden Daten vom Master an den Slave übertragen. Voraussetzung ist, dass vorher Wire.beginTransmission gestartet und die Übertragung mit Wire.endTransmission() beendet wird.

 

Syntax

Wire.write(value)

Wire.write(string)

Wire.write(data, length)

 

Parameter

value                                  ein Wert, der als einfaches Byte gesendet wird

string                               ein String, der als Serie von Bytes übertragen wird

data                                    ein Datenfeld, das als Bytes übertragen wird

Rückgabewert                Anzahl der geschriebenen Bytes

 

Wire.endTransmission()

Beendet eine Übertragung an einen Slave, die mit beginTransmission() vorher gestartet wurde.

Argumente (optional)

true                                    sendet nach der Übertragung eine Stopp-Mitteilung und gibt den i2c Bus wieder frei

false                                  sendet eine Neustart-Meldung nach der Übertragung. Der Bus wird nicht freigegeben und lässt eine erneute Übertragung durch den Master zu. Andere Mastergeräte können in dieser Zeit keine Übertragungen vornehmen.

 

Syntax

Wire.endTransmission()

Wire.endTransmission(stop)

 

Parameter

stop                                   boolean                

                                            TRUE sendet Stoppsequen und gibt den Bus nach der Übertragung frei.

                                            FALSE löst Neustart aus und hält die Verbindung aktiv.

Rückgabewert               Byte, gibt Hinweis auf den Status der Übertragung

                                               0 - alles ok

                                               1 - Daten zu lang; passen nicht in den Übertragungspuffer

                                               2 - NACK erhalten bei Übertragung der Adresse

                                               3 - NACK erhalten bei Übertragung von Daten

                                               4 - sonstiger Fehler

3 - Die Zeitdiagramme

Abschließend schauen wir uns die Zeitdiagramme der einzelnen Programmschritte an. In der ersten Übertragungssequenz (Programmzeilen 10 - 13) werden die Grundeinstellungen vorgenommen; in der zweiten (Programmzeilen 15 - 21) werden die Ausgänge des TLC59116 Treiberbausteins so modifiziert, dass LED1 auf dem Modulboard eingeschaltet wird. Bis dahin ist das sicherlich nicht spektkulär, aber mit diesem Wissen lassen sich zukünftig mindestens 16 LEDs unabhängig voneinander steuern. Das Zeitdiagramm für diesen kleinen Versuchsaufbau zeigen die folgenden Diagramme (aufgenommen mit PicoScope 2205).

Abbildung 7 - Das Zeitdiagramm zeigt von links nach rechts die Befehlssequenz SC0 80 81 P
  1. Startsequenz mit der Bitfolge 1100_0000 (0xC0), abschlossen durch Ack =  0 (9. Bit).
  2. Bitfolge 1000_0000 (0x80 oder dezimal 128), abgeschlossen mit Ack = 0 (9. Bit).
  3. Bitfolge 1000_0001 (0x81 oder dezimal 129), abgeschlossen mit Ack =  0 (9. Bit).
  4. Stoppsequenz und Übergang des I2C-Bausteins in den Leerlauf.
Abbildung 8 - Aufgenommen wurde die Befehlssequenz SC0 94 01 00 00 00 P.
  1. Startsequenz mit der Bitfolge 1100_0000 (0xC0), abschlossen durch Ack =  0 (9. Bit).
  2. Bitfolge 1001_0100 (0x94 oder dezimal 148), abgeschlossen mit Ack = 0 (9. Bit).
  3. Bitfolge 0000_0001 (0x01 oder dezimal 1), abgeschlossen mit Ack =  0 (9. Bit).
  4. Bitfolge 0000_0000 (0x00 oder dezimal 0) , abgeschlossen mit Ack =  0 (9. Bit).
  5. Bitfolge 0000_0000 (0x00 oder dezimal 0) , abgeschlossen mit Ack =  0 (9. Bit).
  6. Bitfolge 0000_0000 (0x00 oder dezimal 0) , abgeschlossen mit Ack =  0 (9. Bit).
  7. Stoppsequenz und Übergang des I2C-Bausteins in den Leerlauf.
Druckversion Druckversion | Sitemap
© Reinhard Rahner - Gettorf