簡介
I2C(Inter-integrated Circuit)總線支持設備之間的短距離通信,用于處理器和一些外圍設備之間的接口,它只需要兩根信號線來完成信息交換。I2C最早是飛利浦在1982年開發設計并用于自己的芯片上,一開始只允許100kHz、7-bit標準地址。1992年,I2C的第一個公共規范發行,增加了400kHz的快速模式以及10-bit擴展地址。在I2C的基礎上,1995年Intel提出了“System Management Bus” (SMBus),用于低速設備通信,SMBus 把時鐘頻率限制在10kHz~100kHz,但I2C可以支持0kHz~5MHz的設備:普通模式(100kHz即100kbps)、快速模式(400kHz)、快速模式+(1MHz)、高速模式(3.4MHz)和超高速模式(5MHz)。
與串行端口、SPI對比
串行端口
串行端口是異步的(不傳輸時鐘相關數據),兩個設備在使用串口通信時,必須先約定一個數據傳輸速率,并且這兩個設備各自的時鐘頻率必須與這個速率保持相近,某一方的時鐘頻率相差很大都會導致數據傳輸混亂。
異步串行端口在每個數據幀中都要插入至少一個起始位和一個終止位,意味著每傳輸8bits的數據實際要花費10bits的傳輸時間,從而降低了數據傳輸速率。
另一個問題是異步串行端口的設計就是針對兩個設備之間通信的,那么如果有多個設備連接到一個串口上,就必須解決信號碰撞的問題(bus contention),通常要通過額外硬件來完成。
最后就是數據傳輸速率,異步串行通信并沒有一個理論上的速率限制,大部分UART設備只支持一些特定的波特率,最高通常在230400bps左右。
SPI
SPI最明顯的缺點就是引腳數量,使用SPI總線相連的一個master和一個slave需要四根線(MISO/MOSI/SCK/CS),每增加一個slave,就需要在master上增加一個CS引腳。當一個master接多個slaves的時候,瘋狂增長的引腳連接是難以忍受的,并且對緊湊的PCB layout是一個挑戰。
SPI總線上只允許有一個master,但可以有任意多個slaves(只受限于總線上設備的驅動程序的能力,以及設備上最多能有多少個CS引腳)。
SPI可以很好的用于高速率全雙工的連接,對一些設備可支持高達10MHz(10Mbps)的傳輸速率,因此SPI吞吐量大得多。SPI兩端的設備通常是一個簡單的移位寄存器,讓軟件的實現很簡單。
I2C
I2C最少只需要兩根線,和異步串口類似,但可以支持多個slave設備。和SPI不同的是,I2C可以支持mul-master系統,允許有多個master并且每個master都可以與所有的slaves通信(master之間不可通過I2C通信,并且每個master只能輪流使用I2C總線)。master是指啟動數據傳輸的設備并在總線上生成時鐘信號以驅動該傳輸,而被尋址的設備都作為slaves。
I2C的數據傳輸速率位于串口和SPI之間,大部分I2C設備支持100KHz和400KHz模式。使用I2C傳輸數據會有一些額外消耗:每發送8bits數據,就需要額外1bit的元數據(ACK或NACK)。I2C支持雙向數據交換,由于僅有一根數據線,故通信是半雙工的。
硬件復雜度也位于串口和SPI之間,而軟件實現可以相當簡單。
I2C協議
I2C協議把傳輸的消息分為兩種類型的幀:
一個地址幀 —— 用于master指明消息發往哪個slave;
一個或多個數據幀 —— 由master發往slave的數據(或由slave發往master),每一幀是8-bit的數據。
注:協議要求每次放到SDA上的字節長度必須為8位,并且每個字節后須跟一個ACK位,在下面會講到。
數據在SCL處于低電平時放到SDA上,并在SCL變為高電平后進行采樣。讀寫數據和SCL上升沿之間的時間間隔是由總線上的設備自己定義的,不同芯片可能有差異。
I2C數據傳輸的時序圖如下:
開始條件(start condition):
為了標識傳輸正式啟動,master設備會將SCL置為高電平(當總線空閑時,SDA和SCL都處于高電平狀態),然后將SDA拉低,這樣,所有slave設備就會知道傳輸即將開始。如果兩個master設備在同一時刻都希望獲得總線的所有權,那么誰先將SDA拉低,誰就贏得了總線的控制權。在整個通信期間,可以存在多個start來開啟每一次新的通信序列(communication sequence),而無需先放棄總線的控制權,后面會講到這種機制。
地址幀(address frame):
地址幀總是在一次通信的最開始出現。一個7-bit的地址是從最高位(MSB)開始發送的,這個地址后面會緊跟1-bit的操作符,1表示讀操作,0表示寫操作。
接下來的一個bit是NACK/ACK,當這個幀中前面8bits發送完后,接收端的設備獲得SDA控制權,此時接收設備應該在第9個時鐘脈沖之前回復一個ACK(將SDA拉低)以表示接收正常,如果接收設備沒有將SDA拉低,則說明接收設備可能沒有收到數據(如尋址的設備不存在或設備忙)或無法解析收到的消息,如果是這樣,則由master來決定如何處理(stop或repeated start condition)。
數據幀(data frames):
在地址幀發送之后,就可以開始傳輸數據了。Master繼續產生時鐘脈沖,而數據則由master(寫操作)或slave(讀操作)放到SDA上。每個數據幀8bits,數據幀的數量可以是任意的,直到產生停止條件。每一幀數據傳輸(即每8-bit)之后,接收方就需要回復一個ACK或NACK(寫數據時由slave發送ACK,讀數據時由master發送ACK。當master知道自己讀完最后一個byte數據時,可發送NACK然后接stop condition)。
停止條件(stop condition):
當所有數據都發送完成時,master將產生一個停止條件。停止條件定義為:在SDA置于低電平時,將SCL拉高并保持高電平,然后將SDA拉高。
注意,在正常傳輸數據過程中,當SCL處于高電平時,SDA上的值不應該變化,防止意外產生一個停止條件。
重復開始條件(repeated start condition):
有時master需要在一次通信中進行多次消息交換(例如與不同的slave傳輸消息,或切換讀寫操作),并且期間不希望被其他master干擾,這時可以使用“重復開始條件” —— 在一次通信中,master可以產生多次start condition,來完成多次消息交換,最后再產生一個stop condition結束整個通信過程。由于期間沒有stop condition,因此master一直占用總線,其他master無法切入。
為了產生一個重復的開始條件,SDA在SCL低電平時拉高,然后SCL拉高。接著master就可以產生一個開始條件繼續新的消息傳輸(按照正常的7-bit/10-bit地址傳輸時序)。重復開始條件的傳輸時序如下圖所示:
時鐘拉伸(clock stretching):
有時候,低速slave可能由于上一個請求還沒處理完,尚無法繼續接收master的后續請求,即master的數據傳輸速率超過了slave的處理能力。這種情況下,slave可以進行時鐘拉伸來要求master暫停傳輸數據 —— 通常時鐘都是由master提供的,slave只是在SDA上放數據或讀數據。而時鐘拉伸則是slave在master釋放SCL后,將SCL主動拉低并保持,此時要求master停止在SCL上產生脈沖以及在SDA上發送數據,直到slave釋放SCL(SCL為高電平)。之后,master便可以繼續正常的數據傳輸了。可見時鐘拉伸實際上是利用了時鐘同步的機制(見下文),只是時鐘由slave產生。
如果系統中存在這種低速slave并且slave實現了clock stretching,則master必須實現為能夠處理這種情況,實際上大部分slave設備中不包含SCL驅動器的,因此無法拉伸時鐘。
所以更完整的I2C數據傳輸時序圖為:
10-bit地址空間:
上面講到I2C支持10-bit的設備地址,此時的時序如下圖所示:
在10-bit地址的I2C系統中,需要兩個幀來傳輸slave的地址。第一個幀的前5個bit固定為b11110,后接slave地址的高2位,第8位仍然是R/W位,接著是一個ACK位,由于系統中可能有多個10-bit slave設備地址的高2bit相同,因此這個ACK可能由多有slave設備設置。第二個幀緊接著第一幀發送,包含slave地址的低8位(7:0),接著該地址的slave回復一個ACK(或NACK)。
注意,10-bit地址的設備和7-bit地址的設備在一個系統中是可以并存的,因為7-bit地址的高5位不可能是b11110。實際上對于7-bit的從設備地址,合法范圍為b0001XXX-b1110XXX,’X’表示任意值,因此該類型地址最多有112個(其他為保留地址[1])。
兩個地址幀傳輸完成后,就開始數據幀的傳輸了,這和7-bit地址中的數據幀傳輸過程相同。
時鐘同步和仲裁
如果兩個master都想在同一條空閑總線上傳輸,此時必須能夠使用某種機制來選擇將總線控制權交給哪個master,這是通過時鐘同步和仲裁來完成的,而被迫讓出控制權的master則需要等待總線空閑后再繼續傳輸。在單一master的系統上無需實現時鐘同步和仲裁。
時鐘同步
時鐘同步是通過I2C接口和SCL之間的線“與”(wired-AND)來完成的,即如果有多個master同時產生時鐘,那么只有所有master都發送高電平時,SCL上才表現為高電平,否則SCL都表現為低電平。
總線仲裁
總線仲裁和時鐘同步類似,當所有master在SDA上都寫1時,SDA的數據才是1,只要有一個master寫0,那此時SDA上的數據就是0。一個master每發送一個bit數據,在SCL處于高電平時,就檢查看SDA的電平是否和發送的數據一致,如果不一致,這個master便知道自己輸掉仲裁,然后停止向SDA寫數據。也就是說,如果master一直檢查到總線上數據和自己發送的數據一致,則繼續傳輸,這樣在仲裁過程中就保證了贏得仲裁的master不會丟失數據。
輸掉仲裁的master在檢測到自己輸了之后也不再產生時鐘脈沖,并且要在總線空閑時才能重新傳輸。
仲裁的過程可能要經過多個bit的發送和檢查,實際上兩個master如果發送的時序和數據完全一樣,則兩個master都能正常完成整個的數據傳輸。
評論
查看更多