IIC協議解釋


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.數據幀格式

 

I2 C總線上傳送的數據信號是廣義的,既包括地址信號,又包括真正的數據信號。
在起始信號后必須傳送一個從機的地址(7位),第8位是數據的傳送方向位(R/T),用“0”表示主機發送數據(T),“1”表示主機接收數據(R)。{這里小編在驅動MPU6050模塊的時候,就犯過這樣的錯誤,它寫的MPU6050從機地址是0x68,因為發送從機地址的時候,要加一位讀寫方向位,因為剛開始應該是向這個MPU6050里寫從機里某個寄存器的地址,所以應該是7位地址   0x68(1101000)+二進制位0=11010000)也就是0xD0,表示要向該IIC設備里寫東西,然后再緊接着寫入IIC設備里的寄存器地址,而我直接寫入了0x68,導致出錯},每次數據傳送總是由主機產生的終止信號結束。但是,若主機希望繼續占用總線進行新的數據傳送,則可以不產生終止信號,馬上再次發出起始信號對另一從機進行尋址。
在總線的一次數據傳輸過程中,可以有以下幾種組合方式:
[1] 
主機向從機發送數據,數據傳送方向在整個傳送過程中不變:
注:有陰影部分表示數據由主機向從機傳送,無陰影部分則表示 數據由從機向主機傳送。
    A 表示應答(低電平),  A 非表示非應答(高電平)。 S 表示起始信號, P 表示終止信號。
[2]主機在第一個字節后,立即從從機讀數據:

[3]在傳送過程中,當需要改變傳送方向時,起始信號和從機地址都被重復產生一次,但兩次讀/寫方向位正好反相:

一般情況下,[3]是比較常見的,比如MPU6050模塊,
發送起始信號
等待從機應答
寫一個從機地址+0(表示寫),
等待從機應答
發送一個字節的MPU6050加速度存儲寄存器地址,
等待從機應答
再發送一次起始信號
等待從機應答
寫一個從機地址+1(表示讀)
等待從機應答
讀取MPU6050傳感器數據
主機非應答
e.IIC信號的模擬
主機可以采用不帶I2C總線接口的單片機,如80C51、AT89C2051等單片機,利用軟件實現I2C總線的數據傳送,即軟件與硬件結合的信號模擬。即使是含有IIC硬件的單片機(如stm32 103系列)也有一定的缺陷,所以一般也會模擬IIC的時序。現將具體時間截圖如下:

具體的程序代碼如下:
 
//產生起始信號
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協議可能會有一定的區別,有的地址需要左移一位,把最低位騰出來做讀寫位。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM