I2C-Tutorial

Unter Verwendung des I2C Bus

Der Wert der Widerstände ist nicht kritisch. Ich habe nichts von 1k8 gesehen (1800 Ohm) bis 47k (47000 Ohm) verwendet. 1k8, 4k7 und 10k sind gemeinsame Werte, aber alles, was in diesem Bereich soll OK arbeiten. Ich empfehle 1k8, da dies die beste Leistung bietet. Wenn die Widerstände fehlen, werden die SCL und SDA Linien immer niedrig sein - fast 0 Volt - und der I2C-Bus wird nicht funktionieren.

Masters und Slaves
Die Geräte auf dem I2C-Bus sind entweder Master oder Slave. Der Master ist immer das Gerät, das die Taktleitung SCL antreibt. Die Sklaven sind die Geräte, die an den Master zu antworten. Ein Slave kann nicht mit der Übertragung über den I2C-Bus initiieren, nur ein Master kann das tun. Es kann sein, und in der Regel sind, mehrere Slaves auf dem I2C-Bus, aber es normalerweise nur ein Master ist. Es ist möglich, mehrere Master zu haben, aber es ist ungewöhnlich, und hier nicht behandelt. Auf dem Roboter, wird die Master-Steuerung und die Sklaven werden unsere Module wie die SRF08 oder CMPS03 sein. Slaves initiieren nie einen Transfer. Beiden Master und Slave können Daten über den I2C-Bus übertragen, aber das Transfer wird immer vom Master gesteuert.

Die Daten werden in Sequenzen von 8 Bit übertragen. Die Bits werden auf der SDA-Leitung mit dem MSB (Most Significant Bit) ausgehend angeordnet. Die SCL-Leitung wird dann gepulst, hoch ist, dann niedrig. Denken Sie daran, dass der Chip nicht wirklich die Linie hoch fahren kann, ist es einfach „lets go“ von ihm und der Widerstand zieht es tatsächlich hoch. Für alle 8 Bits übertragen werden, sendet das Gerät die Daten empfängt ein Bit Rückquittierungs, so gibt es tatsächlich 9 Taktimpulse SCL je 8 Bit Byte Daten zu übertragen. Wenn die Empfangsvorrichtung einen niedrigen ACK-Bit sendet, dann hat er die Daten empfing und ist bereit, ein weiteres Byte zu akzeptieren. Wenn es eine hohe sendet dann wird es anzeigt, kann keine weiteren Daten annehmen und die Master sollte die Übertragung durch Senden einer Stoppsequenz beenden.

Wie schnell?
Die Standardtakt (SCL) Geschwindigkeit für I2C bis zu 100 kHz. Philips noch schnellere Geschwindigkeiten definieren: Fast-Modus, der bis zu 400 kHz und High-Speed-Modus, der bis zu 3,4 MHz ist. Alle unsere Module mit bis zu 100 kHz arbeiten sollen. Wir haben unsere Module bis zu 1 MHz getestet, aber dies braucht eine kleine Verzögerung von einigen uS zwischen jedem Byte übertragen. In der Praxis Roboter haben, hatten wir nie eine Notwendigkeit, hohe SCL Geschwindigkeiten zu verwenden. Halten Sie SCL bei oder unter 100 kHz und dann vergessen Sie es.

I2C Geräteadressierung
Alle I2C-Adressen sind entweder 7 Bits oder 10 Bits. Die Verwendung von 10-Bit-Adressen ist selten und wird hier nicht behandelt. Alle unsere Module und die gemeinsamen Chips, die Sie 7-Bit-Adressen müssen verwenden. Das bedeutet, dass Sie bis zu 128 Geräte auf dem I2C-Bus haben kann, da eine 7-Bit-Zahl von 0 bis 127 sein kann, wenn die 7 Adreßbit aussendet, haben wir noch immer 8 Bit senden. Das zusätzliche Bit wird verwendet, um den Slave zu informieren, wenn der Master es schreibt oder von ihnen lesen. Wenn das Bit Null ist der Master zum Slave schreibt. Wenn das Bit 1 ist der Master vom Slave liest. Die 7-Bit-Adresse in den oberen 7 Bits des Byte und das Lesen / Schreiben (R / W) Bit gesetzt wird, ist in dem LSB (Least Significant Bit).

Die Anordnung der 7-Bit-Adresse in den oberen 7 Bits des Byte ist eine Quelle der Verwirrung für den Neuling. Es bedeutet, dass 21 zu schreiben, zu adressieren, müssen Sie tatsächlich 42 auszusenden, die 21 um 1 Bit verschoben ist vorbei. Es ist wahrscheinlich einfacher zu denken, der I2C-Bus-Adressen als 8-Bit-Adressen, mit geraden Adressen als nur schreiben, und den ungeraden Adressen als die Leseadresse für das gleiche Gerät. Um unsere CMPS03 zum Beispiel zu nehmen, ist dies bei der Adresse 0xC0 ($ C0). Sie würden verwendet 0xC0 zum CMPS03 und 0xC1 schreiben von ihm zu lesen. So ist die Lese / Schreib-Bit macht es nur eine gerade / ungerade Adresse.

Die I2C Software Protocol
Das erste, was passieren wird, ist, dass der Master eine Startsequenz aussenden. Dadurch werden alle Slave-Geräte auf dem Bus warnen, dass eine Transaktion gestartet wird, und sie sollten hören in einhüllen es für sie ist. Als nächstes wird der Master die Geräteadresse senden. Der Slave, der diese Adresse übereinstimmt mit der Transaktion fortfahren wird, alle anderen werden den Rest dieser Transaktion ignorieren und für die nächste warten. Mit adressiert das Slave-Gerät die Master nun die interne Position aussenden muss oder Nummer innerhalb des Slave-Register, die sie von zu oder lesen, schreiben möchte. Diese Zahl ist natürlich davon abhängig, was der Sklave tatsächlich ist und wie viele interne Register hat. Einige sehr einfache Geräte haben nicht, aber die meisten tun, einschließlich aller unserer Module. Unsere CMPS03 hat 16 Standorte nummeriert 0-15. Der SRF08 hat 36. Nachdem die I2C-Adresse und die interne Registeradresse der Master kann jetzt senden, um den Daten-Byte (oder Bytes, ist es nicht nur sein muß) gesendet. Der Master kann weiterhin Daten-Bytes an den Slave zu senden, und diese werden in der Regel in den folgenden Registern gesetzt werden, da der Slave nach jedem Byte die interne Registeradresse automatisch erhöht wird. Wenn der Master beendet hat, alle Daten an den Slave zu schreiben, sendet er eine Stop-Sequenz, die die Transaktion abgeschlossen ist. So schreibt zu einem Slave-Gerät:
1. Senden Sie eine Startsequenz
2. Senden der I2C-Adresse des Slave mit dem R / W-Bit niedrig ist (gerade Adresse)
3. Senden Sie die interne Registernummer, die Sie möchten, schreiben
4. Senden Sie die Daten-Byte
5. [Optional sendet keine weiteren Datenbytes]
6. Senden Sie die Stopp-Sequenz.

Als Beispiel haben Sie eine SRF08 im Werk Standardadresse 0xE0. So starten Sie den SRF08 Sie reichen würde bei 0x00 wie diese 0x51 in das Befehlsregister schreiben:
1. Senden Sie eine Startsequenz
2. Senden 0xE0 (I2C-Adresse des SRF08 mit dem R / W-Bit niedrig ist (gerade Adresse)
3. Senden 0x00 (interne Adresse des Befehlsregister)
4. Senden 0x51 (Der Befehl, um den SRF08 zu starten reicht)
5. Senden Sie die Stopp-Sequenz.

Lesung aus dem Slave
Dies ist ein wenig komplizierter - aber nicht zu viel mehr. Vor dem Lesen von Daten aus dem Slave-Gerät, müssen Sie es sagen, welche seiner internen Adressen, die Sie lesen möchten. So ein Lesen des Slave beginnt tatsächlich ab, um es durch das Schreiben. Dies ist das gleiche wie wenn Sie es schreiben wollen: Sie können die Startsequenz zu senden, die I2C-Adresse des Slave mit der R / W-Bit niedrig ist (gerade Adresse) und die internen Registernummer, die Sie schreiben möchten. Jetzt (manchmal auch einen Neustart) Sie einen anderen Startsequenz senden und die I2C-Adresse erneut - diesmal mit dem Lese-Bit gesetzt. Sie werden so viele Daten-Bytes gelesen, wie Sie wollen und die Transaktion mit einer Stoppsequenz beenden. So lesen Sie den Kompass Lager als ein Byte aus dem CMPS03 Modul:
1. Senden Sie eine Startsequenz
2. Senden 0xC0 (I2C-Adresse des CMPS03 mit dem R / W-Bit niedrig ist (gerade Adresse)
3. Senden 0x01 (interne Adresse des Lagerregister)
4. eine Startsequenz Senden wieder (wiederholter Start)
5. Senden 0xC1 (I2C-Adresse des CMPS03 mit dem R / W-Bit high (ungerade Adresse)
6. Lesen Datenbyte von CMPS03
7. Senden der Stopsequenz.

Die Bitfolge wird wie folgt aussehen:

Moment mal
Das ist fast es für einfache I2C-Kommunikation, aber es gibt eine weitere Komplikation. Wenn der Master vom Slave liest, seine Slave, der die Daten auf der SDA-Leitung legt, aber sein der Meister, der die Uhr steuert. Was passiert, wenn der Slave nicht bereit ist, die Daten zu senden! Mit Geräten wie EEPROMs ist dies kein Problem, aber wenn das Slave-Gerät tatsächlich ein Mikroprozessor mit anderen Dingen zu tun ist, kann es ein Problem sein. Der Mikroprozessor auf dem Slave-Gerät muss auf eine Interrupt-Routine gehen, speichern sie ihre Arbeitsregister, herauszufinden, welche Adresse der Meister will aus lesen, die Daten zu erhalten und sie in seinem Senderegister. Dies kann viele uS nehmen zu passieren, mittlerweile der Master wohlig wird Taktimpulse auf der SCL-Leitung aussendet, die der Slave nicht reagieren kann. Die I2C-Protokoll bietet eine Lösung für diese: der Slave darf die SCL-Leitung niedrig halten! Das heißt Uhr Stretching. Wenn der Slave den Lesebefehl vom Master erhält hält es die Linie niedrige Uhr. Der Mikroprozessor erhält dann die Daten angefordert hat, legt sie in dem Senderegister und gibt die Taktleitung ermöglicht den Pull-up-Widerstand, um schließlich es hoch zu ziehen. Vom Meister Sicht wird es den ersten Taktimpuls der indem SCL hoch lesen ausgeben und dann überprüfen, um zu sehen, ob es wirklich hoch gegangen ist. Wenn es nach wie vor niedrig, dann ist es das Slave, dass hält sie niedrig und der Master sollte warten, bis es vor dem Fortfahren hoch geht. Glücklicherweise sind die Hardware-I2C-Ports auf den meisten Mikroprozessoren wird dies automatisch handhaben.

Manchmal jedoch ist der Master I2C nur eine Sammlung von Subroutinen und es gibt ein paar Implementierungen gibt, die völlig ignorieren Uhr Stretching. Sie arbeiten mit Dingen wie EEPROMs, aber nicht mit Mikroprozessor-Slaves, die Uhr verwenden Stretching. Das Ergebnis ist, daß fehlerhafte Daten von der Slave gelesen werden. In acht nehmen!

Beispiel Mastercode
Dieses Beispiel zeigt, wie eine Software I2C-Master, einschließlich Uhr implementieren Stretching. Es ist in C für den PIC-Prozessor geschrieben, soll aber auf den meisten Prozessoren mit geringfügigen Änderungen an die I / O-Pin-Definitionen anwendbar. Es eignet sich für alle unsere I2C Robotermodule steuern. Da die SCL und SDA Linien-Typ mit offenem Drain sind, verwenden wir das Tristate-Steuerregister, um die Ausgabe zu steuern, das Ausgangsregister niedrig zu halten. Die Port-Pins müssen noch obwohl gelesen werden, so dass sie als SCL_IN und SDA_IN definiert. Diese Definition und die Initialisierung ist wahrscheinlich alles, was Sie für einen anderen Prozessor ändern müssen.

#define SCL TRISB4 // I2C-Bus
#define SDA TRISB1 //
#define SCL_IN RB4 //
#define SDA_IN RB1 //

Zu initialisieren, die Anschlüsse den Ausgang Resisters auf 0 und das Tristate-Register auf 1 gesetzt, die die Ausgänge deaktiviert und ermöglicht es ihnen, das durch die Widerstände hochgezogen werden.
SDA = SCL = 1;
SCL_IN = SDA_IN = 0;

Wir verwenden eine kleine Verzögerung Routine zwischen SDA und SCL Änderungen eine klare Reihenfolge auf dem I2C-Bus zu geben. Dies ist nichts anderes als ein Unterprogramm-Aufruf und Rückkehr.
nichtig i2c_dly (void)
>

Die folgenden 4 Funktionen bieten die primitive Start, Stopp, Lese- und Schreibsequenzen. Alle I2C-Transaktionen können von diesen aufgebaut werden.
Leere i2c_start (void)
SDA = 1; // i2c Start Bitsequenz
i2c_dly ();
SCL = 1;
i2c_dly ();
SDA = 0;
i2c_dly ();
SCL = 0;
i2c_dly ();
>

Leere i2c_stop (void)
SDA = 0; // i2c Stopp-Bit-Sequenz
i2c_dly ();
SCL = 1;
i2c_dly ();
SDA = 1;
i2c_dly ();
>

unsigned char i2c_rx (char ack)
char x, d = 0;
SDA = 1;
for (x = 0; x<8; x++) d <<= 1;
do SCL = 1;
>
while (SCL_IN == 0); // für jede SCL Uhr warten Stretching
i2c_dly ();
if (SDA_IN) d | = 1;
SCL = 0;
>
if (ack) SDA = 0;
sonst SDA = 1;
SCL = 1;
i2c_dly (); // senden (N) ACK-Bit
SCL = 0;
SDA = 1;
Rück d;
>

Bit i2c_tx (unsigned char d)
char x;
static Bit b;
for (x = 8, x; x--) if (d-0x80) SDA = 1;
sonst SDA = 0;
SCL = 1;
d <<= 1;
SCL = 0;
>
SDA = 1;
SCL = 1;
i2c_dly ();
b = SDA_IN; // möglich ACK-Bit
SCL = 0;
Rück b;
>

Die 4 primitiven Funktionen, die oben können leicht zusammengestellt werden vollständige I2C-Transaktionen zu bilden. Hier ist und beispielsweise ein SRF08 Bereich in cm zu starten:

i2c_start (); // Startsequenz senden
i2c_tx (0xE0); // SRF08 I2C-Adresse mit R / W-Bit klar
i2c_tx (0x00); // SRF08 Befehlsregisteradresse
i2c_tx (0x51); // Befehl zum Starten in cm Bereich
i2c_stop (); // Stoppsequenz senden

Jetzt, nach 65 ms für die Warte bis hin zu vollenden (I verlassen haben, dass Ihnen) das folgende Beispiel zeigt, wie der Lichtsensorwert aus dem Register 1 zu lesen und den Bereich resultieren aus den Registern 2 - 3.

i2c_start (); // Startsequenz senden
i2c_tx (0xE0); // SRF08 I2C-Adresse mit R / W-Bit klar
i2c_tx (0x01); // SRF08 Lichtsensor Registeradresse
i2c_start (); // eine Neustartsequenz senden
i2c_tx (0xE1); // SRF08 I2C-Adresse mit der R / W-Bit gesetzt
= Lichtsensor i2c_rx (1); // Lichtsensor erhalten und senden acknowledge. Interne Register-Adresse wird automatisch erhöht.
Rangehigh = i2c_rx (1); // das High-Byte des Bereichs erhalten und senden acknowledge.
rangelow = i2c_rx (0); // Low-Byte des Bereichs erhalten - beachten wir nicht das letzte Byte bestätigen.
i2c_stop (); // Stoppsequenz senden

In Verbindung stehende Artikel