IIC協議解釋
(1)概述
I2C(Inter-Integrated Circuit BUS) 集成電路總線,該總線由NXP(原PHILIPS)公司設計,多用於主控制器和從器件間的主從通信,在小數據量場合使用,傳輸距離短,任意時刻只能有一個主機等特性。
經常IIC和SPI接口被認為指定是一種硬件設備,但其實這樣的說法是不盡准確的,嚴格的說他們都是人們所定義的軟硬結合體,分為物理層(四線結構)和協議層(主機,從機,時鍾極性,時鍾相位)。
IIC,SPI的區別不僅在與物理層,IIC比SPI有着一套更為復雜的協議層定義。下面來分別說明一下IIC的物理層和協議層。
(2)IIC的物理層
a.只要求兩條總線線路,一條是串行數據線SDA,一條是串行時鍾線SCL。(IIC是半雙工,而不是全雙工)。
b.每個連接到總線的器件都可以通過唯一的地址和其它器件通信,主機/從機角色和地址可配置,主機可以作為主機發送器和主機接收器。
c.IIC是真正的多主機總線,(而這個SPI在每次通信前都需要把主機定死,而IIC可以在通訊過程中,改變主機),如果兩個或更多的主機同時請求總線,可以通過沖突檢測和仲裁防止總線數據被破壞。
d.傳輸速率在標准模式下可以達到100kb/s,快速模式下可以達到400kb/s。
e.連接到總線的IC數量只是受到總線的最大負載電容400pf限制。
一個典型的IIC接口如下圖(1)所示
圖(1)
(3)IIC的協議層
IIC的協議層才是掌握IIC的關鍵。現在簡單概括如下:
a.數據的有效性
在時鍾的高電平周期內,SDA線上的數據必須保持穩定,數據線僅可以在時鍾SCL為低電平時改變。
如圖(2)所示:
圖(2)
b.起始和結束條件
起始條件:當SCL為高電平的時候,SDA線上由高到低的跳變被定義為起始條件,結束條件:當SCL為高電平的時候,SDA線上由低到高的跳變被定義為停止條件,要注意起始和終止信號都是由主機發出的,連接到I2C總線上的器件,若具有I2C總線的硬件接口,則很容易檢測到起始和終止信號。總線在起始條件之后,視為忙狀態,在停止條件之后被視為空閑狀態,對起始條件和結束條件的描述如下圖(3)所示。
圖(3)
c.應答
每當主機向從機發送完一個字節的數據,主機總是需要等待從機給出一個應答信號,以確認從機是否成功接收到了數據,從機應答主機所需要的時鍾仍是主機提供的,應答出現在每一次主機完成8個數據位傳輸后緊跟着的時鍾周期,低電平0表示應答,1表示非應答,如圖(4)所示。
圖(4)
d.數據幀格式




//產生起始信號 void I2C_Start(void) { I2C_SDA_OUT();//配置一下引腳,引腳設置為輸出 I2C_SDA_H;//把數據線拉高 I2C_SCL_H;//把時鍾線拉高 delay_us(5);//延時5微秒,要求大於4.7微秒 I2C_SDA_L; //拉低,產生下降沿 delay_us(6);//這個過程大於4微秒 I2C_SCL_L;//最后一定要把這個時鍾線拉低,因為只有時鍾線拉低的時候才允許數據 變化。 } //產生停止信號 void I2C_Stop(void) { I2C_SDA_OUT(); I2C_SCL_L; I2C_SDA_L; I2C_SCL_H; delay_us(6); I2C_SDA_H; delay_us(6); } //主機產生應答信號ACK void I2C_Ack(void) { I2C_SCL_L; I2C_SDA_OUT(); I2C_SDA_L; delay_us(2); I2C_SCL_H; delay_us(5); I2C_SCL_L; } //主機不產生應答信號NACK void I2C_NAck(void) { I2C_SCL_L; I2C_SDA_OUT(); I2C_SDA_H; delay_us(2); I2C_SCL_H; delay_us(5); I2C_SCL_L; } //等待從機應答信號,我們只負責主機應答信號的產生,從機應答信號 //我們不控制。 //返回值:1 接收應答失敗 // 0 接收應答成功 u8 I2C_Wait_Ack(void) { u8 tempTime=0; I2C_SDA_IN(); //配置為上拉輸入。 I2C_SDA_H; //主機釋放數據總線,等待從機產生應答信號 delay_us(1); I2C_SCL_H; delay_us(1); //等待從機對數據總線的操作。低電平代表應答 while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA)) { tempTime++; //這個屬於軟件延時,不一定准確。 if(tempTime>250) //如果時間超時,沒有應答就停止。 { I2C_Stop(); return 1; //沒有響應的話返回1. } } I2C_SCL_L; return 0; //如果有響應的話就返回0. }
針對於不同的IIC設備,IIC協議可能會有一定的區別,有的地址需要左移一位,把最低位騰出來做讀寫位。