Welche Kompromisse sollte ich berücksichtigen, wenn ich mich für die Verwendung einer SPI- oder I2C-Schnittstelle entscheide?
Dieses Accelerometer/Gyro Breakout Board ist in zwei Modellen erhältlich, eines für jede Schnittstelle. Wäre eines der beiden einfacher in ein Arduino-Projekt zu integrieren?
http://www.sparkfun.com/products/11028
Zusammenfassung
I2C ist ein Bussystem mit bidirektionalen Daten auf der SDA-Leitung. SPI ist eine Punkt-zu-Punkt-Verbindung mit Dateneingang und Datenausgang auf getrennten Leitungen (MOSI und MISO).
Im Wesentlichen besteht SPI aus zwei Schieberegistern, in denen Sie Daten in ein Schieberegister eintakten, während Sie Daten aus dem anderen austakten. Normalerweise werden Daten in Bytes geschrieben, indem jedes Mal 8 Taktimpulse hintereinander vorliegen, aber das ist keine SPI-Anforderung. Sie können auch Wortlängen von 16 Bit oder sogar 13 Bit haben, wenn Sie möchten. Während in I2C die Synchronisation durch die Startsequenz in SPI erfolgt, erfolgt dies durch SS, das hoch geht (SS ist aktiv niedrig). Nach wie vielen Takten das ist, entscheiden Sie selbst. Wenn Sie 13-Bit-Wörter verwenden, speichert der SS die letzten getakteten Bits nach 13 Taktimpulsen.
Da sich die bidirektionalen Daten auf zwei getrennten Leitungen befinden, ist die Schnittstelle einfach.
SPI im Standardmodus benötigt mindestens vier Leitungen: SCLK (Serial Clock), MOSI (Master Out Slave In), MISO (Master In Slave Out) und SS (Slave Select). Im bideroktionalen Modus werden mindestens drei Leitungen benötigt: SCLK (serielle Uhr), MIMO (Master In Master Out), das eine der MOSI- oder MISO-Leitungen ist, und SS (Slave Select). Bei Systemen mit mehr als einem Slave benötigt man für jeden Slave eine SS-Leitung, damit z Sklaven, die du hast Linien im Standardmodus und Leitungen im bidirektionalen Modus. Wenn Sie das nicht möchten, können Sie die Slaves im Standardmodus verketten, indem Sie das MOSI-Signal eines Slaves mit dem MISO des nächsten verbinden. Dies verlangsamt die Kommunikation, da Sie alle Slave-Daten durchlaufen müssen.
Wie tcrosley sagt, kann SPI mit einer viel höheren Frequenz arbeiten als I2C.
I2C ist etwas komplexer. Da es sich um einen Bus handelt, benötigen Sie eine Möglichkeit, Geräte zu adressieren. Ihre Kommunikation beginnt mit einer einzigartigen Startsequenz: Die Datenleitung (SDA) wird niedrig gezogen, während der Takt (SCL) hoch ist, denn der Rest der Kommunikationsdaten darf sich nur ändern, wenn der Takt niedrig ist. Diese Startsequenz synchronisiert jede Kommunikation.
Da die Kommunikation die Adressierung beinhaltet, werden für beliebig viele Geräte (bis zu 127) nur zwei Leitungen benötigt.
Bearbeiten
Es ist offensichtlich, dass die Datenleitung bidirektional ist, aber es ist erwähnenswert, dass dies auch für die Taktleitung gilt. Slaves können den Takt dehnen , um die Busgeschwindigkeit zu steuern. Dies macht I2C weniger geeignet für Pegelverschiebung oder Pufferung. (SPI-Leitungen im Standardmodus sind alle unidirektional.)
Nachdem jedes Byte (Adresse oder Daten) gesendet wurde, muss der Empfänger den Empfang bestätigen, indem er einen Bestätigungsimpuls auf SDA legt. Wenn Ihr Mikrocontroller über eine I2C-Schnittstelle verfügt, wird dies automatisch erledigt. Sie können es immer noch bitbangen, wenn Ihr Mikrocontroller dies nicht unterstützt, aber Sie müssen den E / A-Pin für jede Bestätigung oder jedes Lesen von Daten von Ausgang auf Eingang umschalten, es sei denn, Sie verwenden einen E / A-Pin zum Lesen und eine zum Schreiben.
Bei 400 kHz ist Standard-I2C viel langsamer als SPI. Es gibt Hochgeschwindigkeits-I2C-Geräte, die mit 1 MHz arbeiten, immer noch viel langsamer als 20 MHz SPI.
(Bearbeiten: Um es klar zu sagen, viele der folgenden Bedenken haben mit der Signalintegrität zu tun, die durch die Board-to-Board-Nutzung von I2C/SPI-Geräten verursacht wird, wie Olin richtig hervorhebt.)
Wenn Sie keine Einschränkungen haben, die Sie stark zu weniger Drähten drängen (wir hatten ein Projekt mit einem hermetisch abgedichteten Stecker, bei dem jeder zusätzliche Kontakt ziemlich teuer war), vermeiden Sie nach Möglichkeit I2C und bleiben Sie bei SPI.
SPI ist auf Hardware- und Softwarebasis ziemlich einfach zu handhaben. In der Hardware gibt es zwei gemeinsam genutzte Datenleitungen, Master In Slave Out (MISO oder SOMI) und Master Out Slave In (MOSI oder SIMO), einen gemeinsam genutzten Takt, der vom Master generiert wird, und eine Chipauswahl pro Gerät. Die CS-Leitung geht auf Low, der Takt läuft und verschiebt im Wesentlichen Eingabebits hinein und Ausgangsbits heraus, bis die Transaktion beendet ist, an welchem Punkt die CS-Leitung auf High geht. Wenn ihre CS-Leitung hoch ist, kommunizieren Slave-Geräte nicht: Sie ignorieren die CLK- und MOSI-Leitungen und versetzen ihren MISO-Pin in einen hochohmigen Zustand, damit jemand anderes ihn verwenden kann.
Wenn Sie einen Mikrocontroller haben, der mehrere SPI-Geräte verwendet und über ein eingebautes SPI-Peripheriegerät verfügt, senden Sie den CS-Ausgang des Mikrocontrollers an einen Demultiplexer (z. B. 74HC138) und steuern Sie die Adressleitungen, um das Gerät zwischen SPI-Transaktionen auszuwählen. Sie schreiben Wörter in ein Register, um sie für die Ausgabe in die Warteschlange zu stellen, und lesen sie zurück, nachdem der CS-Pin hoch angehoben wurde.
Da SPI-Signale alle unidirektional sind, können sie gepuffert, mit digitalen Isolatoren über eine Isolationsbarriere hinweg verwendet und mit Leitungstreibern wie LVDS von Platine zu Platine gesendet werden. Das einzige, worüber Sie sich Sorgen machen müssen, ist die Round-Trip-Ausbreitungsverzögerung, die Ihre maximale Frequenz begrenzt.
I2C ist eine ganz andere Geschichte. Obwohl es vom Verkabelungsstandpunkt viel einfacher ist, mit nur zwei Drähten SCL und SDA, sind diese beiden Leitungen gemeinsam genutzte bidirektionale Leitungen, die Open-Drain-Geräte mit einem externen Pullup verwenden. Es gibt ein Protokoll für I2C, das mit der Übertragung einer Geräteadresse beginnt, sodass mehrere Geräte verwendet werden können, wenn jedes seine eigene Adresse hat.
Aus Hardware-Sicht ist es sehr schwierig, I2C in Systemen zu verwenden, die erhebliches Rauschen aufweisen. Um I2C-Leitungen zu puffern oder zu isolieren, müssen Sie auf exotische ICs zurückgreifen – ja, es gibt sie, aber es gibt nicht viele: Wir haben eins zu einem Projekt verwendet und festgestellt, dass Sie einen Isolator verwenden könnten, aber nicht Verwenden Sie zwei in Reihe - es wurden kleine Spannungsabfälle verwendet, um herauszufinden, welche Seite das treibende Ende der Dinge war, und zwei Reihenabfälle waren zwei viel.
Die Logikpegelschwellen von I2C hängen von Vcc ab, daher müssen Sie wirklich vorsichtig sein, wenn Sie 3V/3,3V- und 5V-Geräte im selben System verwenden.
Alle Signale, die ein Kabel von mehr als einem oder zwei Fuß verwenden, müssen sich Gedanken über die Kabelkapazität machen. Eine Kapazität von 100 pf/Meter ist für mehradrige Kabel nicht ungewöhnlich. Dies führt dazu, dass Sie den Bus verlangsamen oder niedrigere Pullup-Widerstände verwenden müssen, um die zusätzliche Kapazität richtig handhaben zu können und die Anforderungen an die Anstiegszeit zu erfüllen.
Nehmen wir also an, Sie haben ein System, von dem Sie denken, dass Sie es gut entworfen haben, und Sie können die meisten Probleme mit der Signalintegrität lösen, und Rauschen ist selten (aber immer noch vorhanden). Worüber müssen Sie sich Sorgen machen?
Es gibt eine Reihe von Fehlerbedingungen, auf die Sie vorbereitet sein müssen:
Das Slave-Gerät bestätigt ein bestimmtes Byte nicht. Sie müssen dies erkennen und die Kommunikationssequenz stoppen und neu starten. (Mit SPI können Sie normalerweise die von Ihnen gesendeten Daten zurücklesen, wenn Sie sicherstellen möchten, dass sie fehlerfrei empfangen wurden.)
Sie lesen ein Datenbyte von einem Slave-Gerät, und das Gerät wird aufgrund von Rauschen auf der Taktleitung "hypnotisiert": Sie haben die erforderlichen 8 Takte gesendet, um dieses Byte zu lesen, aber aufgrund von Rauschen denkt das Slave-Gerät es hat 7 Takte empfangen und sendet immer noch eine 0 auf der Datenleitung. Wenn das Gerät den 8. Takt empfangen hätte, hätte es die Datenleitung hoch freigegeben, so dass der Master die Datenleitung anheben oder absenken könnte, um ein ACK- oder NACK-Bit zu übertragen, oder der Master könnte eine Stoppbedingung (P) übertragen. Aber der Slave hält die Datenleitung immer noch niedrig und wartet vergeblich auf einen weiteren Takt. Wenn ein Master nicht bereit ist, zusätzliche Takte auszuprobieren, bleibt der I2C-Bus in einem Deadlock stecken. Obwohl ich mehrere Mikrocontroller verwendet habe, die die normalen ACK/NACK-Bedingungen handhaben,
Der wirklich schreckliche Fall ist, wenn ein Master Daten an ein Slave-Gerät schreibt und ein anderer Slave die Geräteadresse falsch interpretiert und denkt, dass die übertragenen Daten für ihn bestimmt sind. Wir hatten I2C-Geräte (E/A-Expander), bei denen aus diesem Grund gelegentlich Register falsch eingestellt waren. Es ist fast unmöglich, diesen Fall zu erkennen, und um robust gegenüber Rauschen zu sein, müssen Sie regelmäßig alle Register einstellen, damit dieser Fehler zumindest nach kurzer Zeit behoben wird, wenn Sie auf diesen Fehler stoßen. (SPI hat dieses Problem nie – wenn Sie zufällig eine Störung auf der CS-Leitung haben, wird sie nie lange andauern und Sie werden keine Daten versehentlich vom falschen Slave-Gerät lesen.)
Viele dieser Bedingungen könnten im Protokoll richtig behandelt werden, wenn Fehlererkennung (CRC-Codes) vorhanden wäre, aber nur wenige Geräte haben dies.
Ich finde, dass ich komplexe Software in meinem I2C-Master-Gerät bauen muss, um diese Bedingungen zu bewältigen. Meiner Meinung nach lohnt es sich einfach nicht, es sei denn, die Einschränkungen bei der Verkabelung zwingen uns, I2C und nicht SPI zu verwenden.
Das Breakout-Board für Geräte bei SparkFun ist eigentlich nur für die I2C-Version (MPU-6500). Die MPU-6000-Version hat sowohl SPI- als auch I2C-Schnittstellen auf demselben Chip, und ich sehe nicht, dass SparkFun ein Board mit diesem Chip hat. Ich glaube also, dass Sie auf die Verwendung von I2C beschränkt sind, wenn Sie dieses bestimmte Board verwenden möchten. Aber ich wollte I2C trotzdem in Ihrer Situation aus den folgenden Gründen empfehlen.
Im Allgemeinen werden Sie feststellen, dass der I2C-Bus aus Hardware-Sicht einfacher zu verwenden ist als der SPI-Bus. I2C ist ein 2-Draht-Bus (SCL/SDA):
SCL – Serial clock.
SDA – Serial data (bidirectional).
SPI ist ein 4-Draht-Bus (SCLK/MOSI/MISO/CS):
SCLK– Serial clock.
MOSI – Master-out, Slave-in. Data from the CPU to the peripheral.
MISO – Master-in, Slave out. Data from the peripheral back to the CPU.
CS – Chip select.
Sie können mehrere Geräte an einen I2C-Bus anschließen. Jedes Gerät hat seinen eigenen Satz von Adressen, die in den Chip eingebaut sind. Die Adresse wird tatsächlich als erstes Byte jedes Befehls (zusammen mit einem Lese-/Schreibbit) über den Bus gesendet. Dies erfordert zusammen mit einigen anderen Overheads, dass mehr Bits über einen I2C-Bus als über SPI für die gleiche Funktionalität gesendet werden.
Unterschiedliche Geräteklassen (Speicher, E/A, LCD usw.) haben unterschiedliche Adressbereiche. Einige Geräte, die üblicherweise mehr als einmal in einem System verwendet werden (z. B. der E/A-Expander PCF8574), verwenden eine oder mehrere Adressleitungen (AD0-2 für den PCF8574), die hoch oder niedrig gebunden werden können, um die niedrigen Bits anzugeben der Adresse. Die MPU-6500 hat eine solche Adressleitung (AD0), sodass zwei davon im selben System verwendet werden können.
Sie können auch mehrere Geräte an einem SPI-Bus haben, aber jedes Gerät muss seine eigene Chip-Select-Leitung (CS) haben. Daher ist die 4-Draht-Beschreibung etwas irreführend – es handelt sich tatsächlich um eine Drei-Draht-Schnittstelle + ein zusätzliches Kabel pro Gerät. Ich habe keine Erfahrung mit der Arduino-Serie von Boards, aber ich glaube, dies würde die Verwendung von SPI auf dem Arduino erschweren, da dies mit den üblichen Pin-Zuweisungen, die von den verschiedenen Shields verwendet werden, umständlich werden würde, wenn Sie viele Chip-Select-Leitungen benötigen würden .
Ich glaube, die meisten Arduino-Boards laufen mit 5 Volt, einige neuere mit 3,3 V. Die MPU-6500 läuft mit 3,3 V. Wenn die minimale "hohe" Eingangsspannung für den I2C-Bus auf einer 5-V-CPU 3 V oder weniger beträgt, können Sie Pegelumwandlungsprobleme vermeiden, indem Sie einfach 10-K-Pullup-Widerstände auf 3,3 V auf den SCL- und SDA-Leitungen bereitstellen, da der Bus offen ist. Kollektor. Stellen Sie sicher, dass alle internen 5-V-Pullups auf einer CPU deaktiviert sind.
Ich habe jedoch das Datenblatt für den ATmega2560 überprüft (am Beispiel des ADK 5v Arduino), und seine minimale „hohe“ Eingangsspannung beträgt 0,7 * Vcc oder 3,5 V, was größer als 3,3 V ist. Sie benötigen also eine Art aktiven Pegel Der TI PCA9306 , der Pullups-Widerstände sowohl auf der 5-V- als auch auf der 3,3-V-Seite des Chips benötigt, kostet nur 78 Cent in Einzelstückzahlen.
Warum dann jemals SPI über I2C wählen? Hauptsächlich, weil SPI viel viel schneller ausgeführt werden kann - in einigen Fällen bis zu vielen 10 MHz. I2C ist im Allgemeinen auf 400 KHz begrenzt. Aber das ist nicht wirklich ein Problem für den MPU-6050/6000-Beschleunigungsmesser, da er mit 400 KHz für I2C und nur 1 MHz für SPI läuft – kein großer Unterschied.
Im Allgemeinen ist SPI ein schnellerer Bus – die Taktfrequenz kann im MHz-Bereich liegen. SPI erfordert jedoch mindestens 3 Leitungen für die bidirektionale Kommunikation und einen zusätzlichen Slave-Select für jedes Gerät am Bus.
I2C benötigt nur 2 Leitungen, unabhängig davon, wie viele Geräte Sie haben (in Grenzen natürlich). Die Geschwindigkeit liegt jedoch im Bereich von kHz (typisch sind 100-400 kHz).
Die meisten Mikrocontroller haben heutzutage Hardwareunterstützung für beide Busse, sodass beide gleichermaßen einfach zu verwenden sind.
I2C is designed for on-board applications.
- Anscheinend sind I2C-Gerätehersteller anderer Meinung als Sie. Nimm den TMP100 . Auf der Produktseite heißt es explizit: The TMP100 and TMP101 are ideal for extended temperature measurement in a variety of communication, computer, consumer, environmental, industrial, and instrumentation applications.
Gleiches gilt für den TMP75SPI kann viel schneller ausgeführt werden als I2C (einige SPI-Geräte gehen über 60 MHz; ich weiß nicht, ob die "offizielle" I2C-Spezifikation Geräte über 1 MHz zulässt). Die Implementierung eines Slave-Geräts unter Verwendung beider Protokolle erfordert Hardwareunterstützung, während beide eine einfache Implementierung von "Software-Bit-Bang"-Mastern ermöglichen. Mit relativ minimaler Hardware kann man einen I2C-kompatiblen Slave konstruieren, der auch dann korrekt funktioniert, wenn der Host willkürlich entscheidet, den Bus für bis zu 500 us gleichzeitig zu ignorieren, ohne dass zusätzliche Handshaking-Kabel erforderlich sind. Ein zuverlässiger SPI-Betrieb erfordert jedoch, selbst mit Hardwareunterstützung , im Allgemeinen, dass entweder ein Handshake-Kabel hinzugefügt wird oder dass der Host "manuell" nach jedem Byte eine Verzögerung hinzufügt, die der Worst-Case-Antwortzeit des Slaves entspricht.
Wenn ich meine Druther hätte, würde die SPI-Unterstützung der Controller ein paar einfache zusätzliche Funktionen enthalten, um 8-Bit-transparente bidirektionale Datenübertragungen zwischen Controllern mit Handshaking- und Wake-up-Fähigkeiten bereitzustellen, wobei insgesamt drei unidirektionale Drähte verwendet werden (Clock und MOSI [master -out-slave-in] vom Master; MISO [master-in-slave-out] vom Slave). Im Vergleich dazu erfordert eine effiziente und zuverlässige Kommunikation zwischen Mikrocontrollern mit "Standard" -SPI-Ports, wenn beide Prozessoren unabhängig voneinander für beliebige Zeiträume verzögert werden können, die Verwendung von viel mehr Drähten (Chip-Select, Clock, MISO und MOSI zum Starten). mit plus einer Art Bestätigungsleitung vom Slave. Wenn der Slave möglicherweise asynchron Daten zu senden beginnt (z. B. weil jemand einen Knopf gedrückt hat), muss man entweder eine weitere Leitung als "Weck" verwenden
I2C bietet nicht alle Fähigkeiten, die mein "verbessertes" SPI haben würde, aber es bietet integrierte Handshaking-Fähigkeiten, die SPI fehlt, und in vielen Implementierungen kann es auch zum Aufwecken verwendet werden, selbst wenn der Master ein ist Software-Bit-Bang. Für die Kommunikation zwischen Prozessoren würde ich daher dringend I2C über SPI empfehlen, außer wenn höhere Geschwindigkeiten benötigt werden, als SPI liefern kann, und die Verwendung zusätzlicher Pins akzeptabel ist. Für die Kommunikation zwischen Prozessoren, bei der eine geringe Anzahl von Pins erforderlich ist, haben UARTs viele Vorteile.
Diese Frage wurde in den hervorragenden Antworten hier gründlich untersucht, aber vielleicht gibt es noch einen weiteren Standpunkt zu I 2 C, den ich aus Sicht eines Chipherstellers anbieten könnte.
Die elektrische Schnittstelle des I 2 C ist ein offener Kollektor . Jetzt atmen Sie und denken Sie an die Auswirkungen. Mit I 2 C kann ich einen Chip entwerfen, der völlig unabhängig von der Betriebsspannung des Busses ist. Alles, was ich tun muss, ist, die SDA-Leitung nach Belieben nach unten zu ziehen und die Spannungen von SCL und SDA mit einer massebezogenen Schwellenspannung zu vergleichen, die ich wählen kann. Und wenn ich die normalen High-Side-Schutzstrukturen weglasse und durch andere Strukturen ersetze, kann ich einen Chip herstellen, der unabhängig vom Rest des Systems sein eigenes Leben führen kann - SCL, SDA speisen meinen Chip und mich niemals mit Strom wird diesen Pins sicherlich keinen Strom zuführen. Deshalb ist es so ein schöner Bus für Echtzeituhren und andere Dinge mit geringem Stromverbrauch.
Eine Sache, die ich in den anderen Antworten nicht erwähnt habe, ist, dass I2C mehrere Master auf demselben Bus unterstützt. Wenn Sie eine bidirektionale Kommunikation benötigen und keine abfragebasierte Methode verwenden möchten, erledigt I2C die Arbeit.
Über längere Distanzen hat CAN die gleiche Leistungsfähigkeit und ist robuster. CAN ist jedoch ein asynchrones Protokoll, das Hardwareunterstützung und einen Transceiver erfordert, sodass es in einem kostengünstigen System möglicherweise keine Option ist.
Verwenden Sie das SPI-Protokoll und schreiben Sie Ihre Bits direkt auf das Gerät, wenn die Synchronisierungsuhr steigt. Die xnor-Logikschaltung kann verwendet werden, um die "hausgemachte" Adresse aus einem Speicher abzugleichen, um das gewünschte Gerät auszuwählen, als ob es ein i2c-Gerät wäre.
Der i2c integriert die Autorenschaltung in das Format des Geräts, Standard ... usw. sind komplex und unterschiedlich. Mit einem Spi können Sie einen Spi-Speicher verwenden, um ein Video auf dem Bildschirm anzuzeigen, aber nicht i2c.
I2C ist ein Bus mit Datenadressen. SPI ist ein Bus mit physikalischen Adressen.
I2C, wie oben erwähnt, ist ohne einen Hardware-Controller nicht einfach oder einfach.
Im Übrigen ist SPI ohne einen Hardware-Controller im Kontext dieser Diskussion auch nicht einfach. Vor allem, weil das Timing so schnell ist, kann es schwierig sein, es vorherzusehen, und jedes Gerät hat sein eigenes Protokoll und seine eigenen Anomalien.
Mein Vorschlag ist, diese Entscheidung basierend auf der Bandbreite zu treffen.
Wenn Ihre Anwendung von Zeitpräzision und Datenrate profitiert. Insbesondere wenn I2C nicht die volle Bandbreite bietet, verwenden Sie SPI.
Wahrscheinlich existiert für beide eine Bibliothek zur Schnittstelle oder wird es in Kürze geben. Wenn nicht, löse ich persönlich SPI-Probleme lieber als I2C-Probleme.
Wenn Sie keines dieser Themen betrifft. Verwenden Sie I2C einfach, weil es wahrscheinlicher ist, dass Code vorhanden ist und weniger Verbindungen hergestellt werden müssen.
Hans
Armandas
Jason S
Hans
Jon L
trosley
Superkatze