(redigieren Sie: Um klar zu sein, haben viele der folgenden Interessen mit der Signalintegrität zu tun, die durch die Board-to-Board-Verwendung von I2C / SPI-Geräten verursacht wird, wie Olin richtig hervorhebt.)
Wenn Sie keine Einschränkungen haben, die Sie stark in Richtung weniger Drähte drücken (wir hatten ein Projekt mit einem hermetisch abgedichteten Steckverbinder, bei dem jeder zusätzliche Kontakt ziemlich teuer war), vermeiden Sie I2C, wenn möglich, und bleiben Sie bei SPI.
SPI ist auf Hardware- und Softwarebasis recht 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 vom Master generierten gemeinsam genutzten Takt und eine Chipauswahl pro Gerät. Die CS-Leitung geht auf LOW, der Takt zykliert und verschiebt im wesentlichen die Eingangsbits und verschiebt die Ausgangsbits, bis die Transaktion beendet ist. An diesem Punkt geht die CS-Leitung auf HIGH. 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 andere ihn verwenden können.
Wenn Sie einen Mikrocontroller mit mehreren SPI-Geräten und einem integrierten SPI-Peripheriegerät haben, 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 auf Hoch angehoben wurde.
Da alle SPI-Signale unidirektional sind, können sie gepuffert, über eine Isolationsbarriere mit digitalen Isolatoren verwendet und mit Leitungstreibern wie LVDS von Karte zu Karte gesendet werden. Das einzige, worüber Sie sich Sorgen machen müssen, ist die Umlaufverzögerung, die Ihre maximale Frequenz begrenzt.
I2C ist eine ganz andere Geschichte. Vom Standpunkt der Verdrahtung ist es zwar viel einfacher, mit nur zwei Drähten SCL und SDA, aber beide Leitungen sind 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.
Vom Standpunkt der Hardware aus ist es sehr schwierig, I2C in Systemen zu verwenden, die signifikante Störungen 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 in einem Projekt verwendet und festgestellt, dass Sie einen Isolator verwenden können, 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 in Reihe auftretende Abfälle waren zwei große.
Die Schwellenwerte für den Logikpegel von I2C hängen von Vcc ab. Sie müssen also sehr vorsichtig sein, wenn Sie 3-V- / 3,3-V- und 5-V-Geräte im selben System verwenden.
Alle Signale, die ein Kabel mit einer Länge von mehr als einem oder zwei Fuß verwenden, müssen sich um die Kabelkapazität kümmern. Eine Kapazität von 100pf / Meter ist für Mehrleiterkabel nicht ungewöhnlich. Dies führt dazu, dass Sie den Bus verlangsamen oder niedrigere Pullup-Widerstände verwenden müssen, um in der Lage zu sein, mit der zusätzlichen Kapazität richtig umzugehen und die Anforderungen an die Anstiegszeit zu erfüllen.
Nehmen wir also an, Sie haben ein System, das Ihrer Meinung nach gut entwickelt ist, 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:
Slave-Gerät erkennt ein bestimmtes Byte nicht. Sie müssen dies erkennen und die Kommunikationssequenz stoppen und neu starten. (Mit SPI können Sie normalerweise die 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 ist aufgrund von Rauschen auf der Taktleitung "hypnotisiert": Sie haben die erforderlichen 8 Takte zum Lesen dieses Bytes gesendet, aber das Slave-Gerät denkt es aufgrund von Rauschen hat 7 Takte empfangen und sendet immer noch eine 0 auf der Datenleitung. Wenn das Gerät den achten Takt empfangen hätte, hätte es die Datenleitung auf Hochpegel freigegeben, so dass der Master die Datenleitung anheben oder absenken könnte, um ein ACK- oder NACK-Bit zu senden, oder der Master könnte eine Stoppbedingung (P) senden. Aber der Slave hält die Datenleitung immer noch niedrig und wartet vergeblich auf eine weitere Uhr. Wenn ein Master nicht bereit ist, zusätzliche Uhren zu testen, steckt der I2C-Bus in einem Deadlock. Während ich mehrere Mikrocontroller verwendet habe, die die normalen ACK / NACK-Bedingungen handhaben,
Der wirklich schreckliche Fall ist, wenn ein Master Daten auf ein Slave-Gerät schreibt und ein anderer Slave die Geräteadresse falsch interpretiert und der Meinung ist, dass die übertragenen Daten für dieses Gerät bestimmt sind. Es gab I2C-Geräte (I / O-Expander), bei denen die Register gelegentlich falsch eingestellt waren. Es ist fast unmöglich, diesen Fall zu erkennen, und um robust gegen Rauschen zu sein, müssen Sie regelmäßig alle Register einstellen, damit dieser Fehler nach kurzer Zeit behoben wird, wenn Sie auf diesen Fehler stoßen. (SPI hat dieses Problem nie - wenn Sie zufällig einen Fehler in der CS-Leitung haben, wird dieser niemals lange anhalten und Sie erhalten keine Daten, die versehentlich vom falschen Slave-Gerät gelesen wurden.)
Viele dieser Bedingungen könnten im Protokoll ordnungsgemäß behandelt werden, wenn Fehlererkennung (CRC-Codes) vorhanden wäre, aber nur wenige Geräte verfügen über diese.
Ich stelle fest, dass ich in meinem I2C-Master-Gerät komplexe Software erstellen muss, um diesen Bedingungen gerecht zu werden. Meiner Meinung nach lohnt es sich nur, wenn die Einschränkungen bei der Verkabelung uns zwingen, I2C und nicht SPI zu verwenden.