在決定使用SPI或I2C接口時應該考慮哪些折衷?
該加速度計/陀螺儀分接板有兩種型號,每種接口一個。哪一個更容易集成到Arduino項目中?
http://www.sparkfun.com/products/11028
在決定使用SPI或I2C接口時應該考慮哪些折衷?
該加速度計/陀螺儀分接板有兩種型號,每種接口一個。哪一個更容易集成到Arduino項目中?
http://www.sparkfun.com/products/11028
摘要
I2C是在SDA線上具有雙向數據的總線系統。 SPI是點對點連接,數據輸入和數據輸出在單獨的線(MOSI和MISO)上。
基本上 SPI 由一對移位寄存器組成,在這裡您將數據移入一個移位寄存器,而將數據移出另一個。通常,每次連續8個時鐘脈衝以字節為單位寫入數據,但這不是SPI的要求。如果願意,您還可以設置16位甚至13位的字長。在I2C中,同步是通過SPI中的啟動序列完成的,而同步是由SS變為高電平(SS為低電平有效)來完成的。您可以在多少個時鐘脈衝後決定自己。如果使用13位字,SS將在13個時鐘脈衝後鎖存最後一個時鐘輸入位。
由於雙向數據位於兩條不同的線上,因此很容易接口。
標準模式下的SPI至少需要四行:SCLK(串行時鐘),MOSI(主輸出從動輸入),MISO(主輸入從動輸出)和SS(從選擇)。至少三條線:SCLK(串行時鐘),MIMO(主輸入主輸出)(MOSI或MISO線之一)和SS(從選擇),在具有多個從站的系統中,每個從站都需要一條SS線對於\ $ N \ $從站,在標準模式下有\ $ N + 3 \ $行,在雙向模式下有\ $ N + 2 \ $行。如果您不希望這樣做,則可以在標準模式下,通過將一個從站的MOSI信號連接到另一個從站的MISO信號,以菊花鏈方式連接從站。這將減慢通信速度,因為您必須循環訪問所有從機數據。
像tcrosley所說,SPI的工作頻率比I2C高得多。
I2C 有點複雜。由於它是總線,因此您需要一種尋址設備的方法。您的通信從一個獨特的開始序列開始:當時鐘(SCL)為高時,數據線(SDA)被拉低,而其餘的通信數據僅在時鐘為低時才被改變。此開始序列將同步每個通信。
由於通信包括尋址,所以對於任意數量的設備(最多127個)僅需要兩條線。
編輯
很明顯,數據線是雙向的,但值得注意的是,時鐘線也是如此。從站可以延長時鐘來控制總線速度。這使I2C不太方便進行電平轉換或緩衝。 (標準模式下的SPI線都是單向的。)
發送完每個字節(地址或數據)後,接收器必須通過在SDA上放置一個確認脈衝來確認接收。如果您的微控制器具有I2C接口,則將自動進行處理。如果您的微控制器不支持它,您仍然可以對其進行位衝擊,但是對於每個確認或讀取數據,您都必須將I / O引腳從輸出切換為輸入,除非您使用I / O引腳進行讀取和讀取。
在400kHz時,標準I2C比SPI慢得多。有些高速I2C器件的工作頻率為1MHz,但仍比20MHz的SPI慢得多。
(編輯:要清楚,以下許多問題與Ilin / Ilin正確指出的由闆對板使用I2C / SPI設備引起的信號完整性有關。)
除非您的約束會極大地推動您減少電線的數量(我們有一個項目採用的是密封連接器,每個額外的觸點都相當昂貴),盡可能避免使用I2C,並堅持使用SPI。
SPI相當易於在硬件和軟件基礎上進行處理。在硬件中,有兩條共享數據線,即主機輸入從機輸出(MISO或SOMI)和主機輸出從機輸入(MOSI或SIMO),主機生成的共享時鐘以及每個設備一個芯片選擇。 CS線變為低電平,時鐘週期並實質上移入輸入位並移出輸出位,直到事務完成為止,此時CS線變為高電平。當CS線為高電平時,從機設備不通信:它們忽略CLK和MOSI線,並將其MISO引腳置於高阻抗狀態,以供其他人使用。
使用多個SPI設備的微控制器,並且具有內置的SPI外設,將微控制器的CS輸出發送到解復用器(例如74HC138),並控制地址線在SPI事務之間選擇設備;您可以將字寫到寄存器中以使其排隊等待輸出,然後在CS引腳升為高電平後將其讀回。
由於SPI信號都是單向的,因此可以對其進行緩衝,並與隔離柵一起使用。數字隔離器,並且可以使用線路驅動器(如LVDS)從板到板發送。您唯一需要擔心的是往返傳播延遲,它將限制您的最大頻率。
I2C是一個完全不同的故事。儘管從佈線的角度來看要簡單得多,但只有兩條線SCL和SDA,這兩條線都是共享的雙向線,它們使用帶有外部上拉的開漏器件。有一個I2C協議以傳輸設備地址開始,因此如果每個設備都有自己的地址,則可以使用多個設備。
從硬件的角度來看,在具有以下條件的系統中很難使用I2C:任何明顯的噪音。為了緩衝或隔離I2C線路,您必須求助於奇異的IC-是的,它們存在,但數量不多:我們在一個項目上使用了一個,並意識到可以使用一個隔離器,但不能使用兩個串聯-它使用小的電壓降來確定物體的驅動端是哪一側,而兩個串聯的電壓降是兩個。
I2C的邏輯電平閾值取決於Vcc,因此如果在同一系統中使用3V / 3.3V和5V器件,則必須格外小心。
任何使用一英尺或兩英尺以上電纜的信號都必須擔心電纜電容。 100pf /米的電容與多芯電纜並不不同尋常。因此,您必須降低總線速度或使用較低的上拉電阻,才能正確處理額外的電容並滿足上升時間要求。
因此,假設您有一個系統,您的設計很好,就可以解決大多數信號完整性問題,並且噪聲很少(但仍然存在)。您要擔心什麼?
必須準備處理許多錯誤條件:
從設備無法識別特定字節。您必須檢測到這一點,然後停止並重新啟動通信序列。 (使用SPI,如果要確保已正確接收到數據,通常可以讀回發送的數據。)
您正在從從設備讀取一個字節的數據,並且該設備由於時鐘線上的噪聲而被“催眠”:您已發送必需的8個時鐘來讀取該字節,但由於噪聲,從設備認為它已收到7個時鐘,並且仍在數據線上發送0。如果設備已接收到第8個時鐘,它將釋放數據線為高電平,以便主機可以升高或降低數據線以發送ACK或NACK位,或者主機可以發送停止(P)條件。但是從機仍將數據線保持在低電平,徒勞地等待另一個時鐘。如果主機不准備嘗試額外的時鐘,則I2C總線將陷入死鎖。儘管我使用了幾種微控制器來處理正常的ACK / NACK條件,但我從未使用過一種能夠成功處理這種丟失的時鐘位(或額外的時鐘位)條件的微控制器,並且不得不退出自動I2C模式,進入位砰砰模式,添加時鐘直到數據線變高,然後重新進入自動I2C模式。另一個從站錯誤地解釋了設備地址,並認為發送的數據是為此目的而準備的。我們有一些I2C設備(I / O擴展器),因此有時會錯誤地設置寄存器。幾乎不可能檢測到這種情況,並且要對噪聲具有魯棒性,您必須定期設置所有寄存器,這樣,如果您確實遇到此錯誤,至少可以在短時間內將其修復。 (SPI永遠不會出現這個問題-如果您碰巧在CS線上出現故障,它將永遠不會持續很長時間,並且您不會被錯誤的從屬設備意外讀取數據。)
如果存在錯誤檢測(CRC碼),則協議中的許多情況都可以正確處理,但是很少有設備具備此功能。
我發現我必須在I2C主設備中構建複雜的軟件才能處理這些情況。我認為,除非接線方面的限制迫使我們使用I2C而不是SPI,否則這是不值得的。
SparkFun的設備分線板實際上僅適用於I2C版本(MPU-6500)。 MPU-6000版本在同一芯片上同時具有SPI和I2C接口,我看不到SparkFun在該芯片上有一塊板。因此,我相信如果您想使用該特定板子,則只能使用I2C。但是出於以下原因,我還是建議您在任何情況下都使用I2C。
通常,您會發現從硬件角度來看,I2C總線比SPI總線更易於使用。 I2C是2線總線(SCL / SDA):
SCL –串行時鐘。SDA–串行數據(雙向)。
SPI是4有線總線(SCLK / MOSI / MISO / CS):
SCLK –串行時鐘。MOSI–主輸出,從輸入。從CPU到外圍設備的數據。MISO–主輸入,從輸出。數據從外設返回到CPU。CS–片選。
您可以將多個設備連接到一條I2C總線。每個設備都有內置於芯片中的自己的一組地址。該地址實際上在總線上作為每個命令的第一個字節(連同讀/寫位)一起廣播。對於相同的功能,這以及其他一些開銷要求通過I2C總線與SPI發送更多位。
不同類別的設備(內存,I / O,LCD等)具有不同的地址範圍。某些設備在系統中通常不止一次使用(例如PCF8574 I / O擴展器),它們使用一條或多條地址線(對於PCF8574為AD0-2),可以將其綁定為高電平或低電平以指定低位地址的。 MPU-6500具有一條這樣的地址線(AD0),因此其中兩個可以在同一系統中使用。
您還可以在SPI總線上具有多個設備,但是每個設備必須具有自己的片選(CS)線。因此4線描述有點用詞不當-實際上是3線接口+每個設備增加一條線。我對Arduino系列板沒有經驗,但是我相信這會使在Arduino上使用SPI更加困難,因為如果您需要大量的芯片選擇線,那麼各種屏蔽使用的通用引腳分配將變得很麻煩。
我相信大多數Arduino板都以5伏電壓運行,而一些較新的板則以3.3v電壓運行。 MPU-6500在3.3v下運行。如果5v CPU上I2C總線的最小輸入“高”電壓為3v或以下,則可以通過在SCL和SDA線上僅提供10K上拉電阻至3.3v來避免電平轉換問題,因為總線是開放的,集電極。確保已禁用CPU上的任何5v內部上拉電阻。 ,或大於3.3v的3.5v,因此您需要某種有源電平轉換,TI PCA9306在芯片的5v和3.3v側均需要上拉電阻,成本僅為78
為什麼要在I2C上選擇SPI?主要是因為SPI的運行速度要快得多-在某些情況下高達10兆赫茲,而I2C通常限於400 KHz。對於MPU-6050 / 6000加速度計來說,這並不是真正的問題,因為它在I2C上以400 KHz運行,而在SPI上僅以1 MHz運行-差別不大。
通常,SPI是一條更快的總線-時鐘頻率可以在MHz範圍內。但是,SPI至少需要3條線進行雙向通信,並為總線上的每個設備選擇一個附加的從設備選擇。課程)。但是,速度在kHz範圍內(典型值為100-400kHz)。
如今,大多數微控制器都為兩條總線提供硬件支持,因此兩者的使用同樣簡單。
SPI的運行速度比I2C快得多(某些SPI設備的運行頻率超過60MHz;我不知道“官方” I2C規範是否允許設備超過1MHz)。使用任何一種協議來實現從設備都需要硬件支持,而兩者都可以輕鬆實現“軟件位爆炸”主設備。使用相對最少的硬件,就可以構造一個符合I2C標準的從設備,即使主機可以一次決定在500us的時間內無視總線,而又不需要額外的握手電纜,它也可以正常運行。但是,可靠的SPI操作,即使有硬件支持,也通常要求添加一條握手線,或者要求主機“手動”在每個字節等於從站的最壞情況響應後添加一個延遲。時間。
如果我有德魯特,控制器的SPI支持將包含一些簡單的額外功能,以提供具有握手和喚醒功能的控制器之間的8位透明雙向數據傳輸,總共使用三根單向電線(時鐘和來自主設備的MOSI [master-out-slave-in]; MISO [slave]中的MISO [master-in-slave-out])。相比之下,當帶有“備用” SPI端口的微控制器之間有效而可靠的通信時,兩個處理器都可能被獨立延遲任意長度的時間,則需要使用更多的電線(啟動芯片選擇,時鐘,MISO和MOSI)如果從站可能開始異步發送數據(例如,因為有人按下了按鈕),那麼一個從站必須要么使用另一根線作為“喚醒”信號,要么讓主站反复輪詢從站以查看是否有數據。
I2C並沒有提供我的“改進”的SPI所具有的所有功能,但它確實提供了SPI所缺乏的內置握手功能,並且在許多實現中,即使當I2C喚醒時,它也可能會被喚醒。大師是一個軟件位棒。因此,對於處理器間通信,我強烈建議通過SPI使用I2C,除非需要的速度比SPI所能提供的更高,並且可以使用額外的引腳。對於需要低引腳數的處理器間通信,UART有很多建議。
在這裡的出色答案中已經對這個問題進行了詳盡的探討,但是從芯片製造商的角度來看,I 2 SUP> CI可能還存在另一種觀點。
I 2 SUP> C的電氣接口是開放集電極。現在呼吸,思考其中的含義。使用I 2 SUP> C,我可以設計與總線的工作電壓完全無關的芯片。我需要做的就是將SDA線拉低(如果我願意),然後將SCL和SDA的電壓與一些我可以選擇的接地基準閾值電壓進行比較。而且,如果我不使用常規的高端保護結構並用其他結構替換,我可以製造出完全可以獨立於系統其餘部分使用的芯片-SCL,SDA永遠不會向我的芯片提供電流當然不會向這些引腳提供任何電流。這就是為什麼它對於實時時鐘和諸如此類的其他低功耗設備如此之好。
在其他答案中我沒有看到的一件事是I2C在同一總線上支持多個主機。如果您需要雙向通信並且不想使用基於輪詢的方法,則I2C將完成這項工作。
在更長的距離上,CAN具有相同的功能並且更加堅固。但是CAN是一種異步協議,需要硬件支持和收發器,因此在低成本系統中可能不是一個選擇。
使用SPI協議,只要同步時鐘上升,就將位直接寫入設備。xnor邏輯電路可用於匹配內存中的“自製”地址,以選擇所需設備,就好像它是i2c設備一樣。
i2c將授權電路集成到設備的格式中,標準...等複雜而又不同,使用spi,您可以使用spi存儲器在屏幕上顯示視頻,但不能使用i2c。