IIC原理超詳細講解---值得一看

IIC 簡介

        IIC(Inter-Integrated Circuit)總線是一種由NXP(原PHILIPS)公司開發的兩線式串行總線,用於連接微控制器及其外圍設備。多用於主控制器和從器件間的主從通信,在小數據量場合使用,傳輸距離短,任意時刻只能有一個主機等特性。

在 CPU 與被控 IC 之間、IC 與 IC 之間進行雙向傳送,高速 IIC 總線一般可達 400kbps 以上。
在這裏插入圖片描述

IIC的物理層

IIC一共有隻有兩個總線: 一條是雙向的串行數據線SDA,一條是串行時鐘線SCL

  • SDA(Serial data)是數據線,D代表Data也就是數據,Send Data 也就是用來傳輸數據的

  • SCL(Serial clock line)是時鐘線,C代表Clock 也就是時鐘 也就是控制數據發送的時序的

所有接到I2C總線設備上的串行數據SDA都接到總線的SDA上,各設備的時鐘線SCL接到總線的SCL上。I2C總線上的每個設備都自己一個唯一的地址,來確保不同設備之間訪問的準確性。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-fxNfPPim-1586571859509)(C:\Users\48013\AppData\Roaming\Typora\typora-user-images\image-20200331212342296.png)]

IIC主要特點:

通常我們爲了方便把IIC設備分爲主設備和從設備,基本上誰控制時鐘線(即控制SCL的電平高低變換)誰就是主設備。**

  • IIC主設備功能:主要產生時鐘,產生起始信號和停止信號

  • IIC從設備功能:可編程的IIC地址檢測,停止位檢測

  • IIC的一個優點是它支持多主控(multimastering), 其中任何一個能夠進行發送和接收的設備都可以成爲主總線。一個主控能夠控制信號的傳輸和時鐘頻率。當然,在任何時間點上只能有一個主控。

  • 支持不同速率的通訊速度,標準速度(最高速度100kHZ),快速(最高400kHZ)

  • SCL和SDA都需要接上拉電阻 (大小由速度和容性負載決定一般在3.3K-10K之間) 保證數據的穩定性,減少干擾。

  • IIC是半雙工,而不是全雙工 ,同一時間只可以單向通信

  • 爲了避免總線信號的混亂,要求各設備連接到總線的輸出端時必須是漏極開路(OD)輸出或集電極開路(OC)輸出。這一點在等下我們會講解

IIC的高阻態

漏極開路(Open Drain)即高阻狀態,適用於輸入/輸出,其可獨立輸入/輸出低電平和高阻狀態,若需要產生高電平,則需使用外部上拉電阻

高阻狀態:高阻狀態是三態門電路的一種狀態。邏輯門的輸出除有高、低電平兩種狀態外,還有第三種狀態——高阻狀態的門電路。電路分析時高阻態可做開路理解

我們知道IIC的所有設備是接在一根總線上的,那麼我們進行通信的時候往往只是幾個設備進行通信,那麼這時候其餘的空閒設備可能會受到總線干擾,或者干擾到總線,怎麼辦呢?

爲了避免總線信號的混亂,IIC的空閒狀態只能有外部上拉, 而此時空閒設備被拉到了高阻態,也就是相當於斷路, 整個IIC總線只有開啓了的設備纔會正常進行通信,而不會干擾到其他設備。

在這裏插入圖片描述

IIC器件地址: 每一個IIC器件都有一個器件地址,有的器件地址在出廠時地址就設定好了,用戶不可以更改,比如OV7670的地址爲0x42。有的器件例如EEPROM,前四個地址已經確定爲1010,後三個地址是由硬件鏈接確定的,所以一IIC總線最多能連8個EEPROM芯片。

IIC物理層總結:

I2C 總線在物理連接上非常簡單,分別由SDA(串行數據線)和SCL(串行時鐘線)及上拉電阻組成。通信原理是通過對SCL和SDA線高低電平時序的控制,來產生I2C總線協議所需要的信號進行數據的傳遞。在總線空閒狀態時,SCL和SDA被上拉電阻Rp拉高,使SDA和SCL線都保持高電平。

I2C通信方式爲半雙工,只有一根SDA線,同一時間只可以單向通信,485也爲半雙工,SPI和uart通信爲全雙工。

主機和從機的概念

主機就是負責整個系統的任務協調與分配,從機一般是通過接收主機的指令從而完成某些特定的任務,主機和從機之間通過總線連接,進行數據通訊。

  • 發佈主要命令的稱爲主機

  • 接受命令的稱爲從機

半雙工和全雙工:

IIC的協議層

I2C 總線在傳送數據過程中共有三種類型信號, 它們分別是:開始信號、結束信號和應答信號。

  • 開始信號:SCL 爲高電平時,SDA 由高電平向低電平跳變,開始傳送數據。
  • 結束信號:SCL 爲高電平時,SDA 由低電平向高電平跳變,結束傳送數據。
  • 應答信號:接收數據的 IC 在接收到 8bit 數據後,向發送數據的 IC 發出特定的低電平脈衝,表示已收到數據。CPU 向受控單元發出一個信號後,等待受控單元發出一個應答信號,CPU 接收到應答信號後,根據實際情況作出是否繼續傳遞信號的判斷。若未收到應答信號,由判斷爲受控單元出現故障。

這些信號中,起始信號是必需的,結束信號和應答信號,都可以不要。

IIC 總線時序圖

img

下面我們來詳細的介紹下IIC的通信協議流程:

初始(空閒)狀態

因爲IIC的 SCL 和SDA 都需要接上拉電阻,保證空閒狀態的穩定性

所以IIC總線在空閒狀態下SCL 和SDA都保持高電平

代碼:

void IIC_init()       //IIC初始化

{

       SCL=1; //首先把時鐘線拉高

       delay_us(4);//延時函數

       SDA=1; //在SCL爲高的情況下把SDA拉高

       delay_us(4); //延時函數

}

開始信號:

SCL保持高電平,SDA由高電平變爲低電平後,延時(>4.7us),SCL變爲低電平。

在這裏插入圖片描述

代碼表示:

//產生IIC起始信號
//1.先拉高SDA,再拉高SCL,空閒狀態
//2.拉低SDA
void IIC_Start()         //啓動信號

{

       SDA=1; //確保SDA線爲高電平

       delay_us(5);

       SCL=1;  //確保SCL高電平

       delay_us(5);

       SDA=0; //在SCL爲高時拉低SDA線,即爲起始信號

       delay_us(5);
    
}

停止信號

停止信號:SCL保持高電平。SDA由低電平變爲高電平。

在這裏插入圖片描述

//產生IIC停止信號
//1.先拉低SDA,再拉低SCL
//2.拉高SCL
//3.拉高SDA
//4.停止接收數據
void IIC_Stop(void)
{

	IIC_SCL=0;
	IIC_SDA=0;    //STOP:當SCL高時,數據由低變高
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;    //發送I2C總線結束信號
	delay_us(4);							   	
}

在起始條件產生後,總線處於忙狀態,由本次數據傳輸的主從設備獨佔,其他I2C器件無法訪問總線;而在停止條件產生後,本次數據傳輸的主從設備將釋放總線,總線再次處於空閒狀態。

在這裏插入圖片描述

數據有效性

IIC信號在數據傳輸過程中,當SCL=1高電平時,數據線SDA必須保持穩定狀態,不允許有電平跳變,只有在時鐘線上的信號爲低電平期間,數據線上的高電平或低電平狀態才允許變化。

SCL=1時 數據線SDA的任何電平變換會看做是總線的起始信號或者停止信號。

也就是在IIC傳輸數據的過程中,SCL時鐘線會頻繁的轉換電平,以保證數據的傳輸

在這裏插入圖片描述

img

應答信號

每當主機向從機發送完一個字節的數據,主機總是需要等待從機給出一個應答信號,以確認從機是否成功接收到了數據,

應答信號:主機SCL拉高,讀取從機SDA的電平,爲低電平表示產生應答

  • 應答信號爲低電平時,規定爲有效應答位(ACK,簡稱應答位),表示接收器已經成功地接收了該字節;
  • 應答信號爲高電平時,規定爲非應答位(NACK),一般表示接收器接收該字節沒有成功。

在這裏插入圖片描述

**每發送一個字節(8個bit)**在一個字節傳輸的8個時鐘後的第九個時鐘期間,接收器接收數據後必須回一個ACK應答信號給發送器,這樣才能進行數據傳輸。

應答出現在每一次主機完成8個數據位傳輸後緊跟着的時鐘週期,低電平0表示應答,1表示非應答,

在這裏插入圖片描述

//主機產生應答信號ACK
//1.先拉低SCL,再拉低SDA
//2.拉高SCL
//3.拉低SCL## 標題
void I2C_Ack(void)
{
   IIC_SCL=0;   //先拉低SCL,使得SDA數據可以發生改變
   IIC_SDA=0;   
   delay_us(2);
   IIC_SCL=1;
   delay_us(5);
   IIC_SCL=0;
}


//主機不產生應答信號NACK
//1.先拉低SCL,再拉高SDA
//2.拉高SCL
//3.拉低SCL
void I2C_NAck(void)
{
   IIC_SCL=0;   //先拉低SCL,使得SDA數據可以發生改變
   IIC_SDA=1;   //拉高SDA,不產生應答信號
   delay_us(2);
   IIC_SCL=1;
   delay_us(5);
   IIC_SCL=0;
}

IIC數據傳送

數據傳送格式

SDA線上的數據在SCL時鐘“高”期間必須是穩定的,只有當SCL線上的時鐘信號爲低時,數據線上的“高”或“低”狀態纔可以改變。輸出到SDA線上的每個字節必須是8位,數據傳送時,先傳送最高位(MSB),每一個被傳送的字節後面都必須跟隨一位應答位(即一幀共有9位)。

當一個字節按數據位從高位到低位的順序傳輸完後,緊接着從設備將拉低SDA線,回傳給主設備一個應答位ACK, 此時才認爲一個字節真正的被傳輸完成 ,如果一段時間內沒有收到從機的應答信號,則自動認爲從機已正確接收到數據。

img

IIC寫數據:

img

多數從設備的地址爲7位或者10位,一般都用七位。
八位設備地址=7位從機地址+讀/寫地址,

再給地址添加一個方向位位用來表示接下來數據傳輸的方向,

  • 0表示主設備向從設備(write)寫數據,

  • 1表示主設備向從設備(read)讀數據

IIC的每一幀數據由9bit組成,

如果是發送數據,則包含 8bit數據+1bit ACK,

如果是設備地址數據,則8bit包含7bit設備地址 1bit方向
在這裏插入圖片描述
在起始信號後必須傳送一個從機的地址(7位) 1~7位爲7位接收器件地址,第8位爲讀寫位,用“0”表示主機發送數據(W),“1”表示主機接收數據 (R), 第9位爲ACK應答位,緊接着的爲第一個數據字節,然後是一位應答位,後面繼續第2個數據字節。

IIC發送一個字節數據:

//IIC發送一個字節
//返回從機有無應答
//1,有應答
//0,無應答            

//IIC_SCL=0;
//在SCL上升沿時準備好數據,進行傳送數據時,拉高拉低SDA,因爲傳輸一個字節,一個SCL脈衝裏傳輸一個位。
//數據傳輸過程中,數據傳輸保持穩定(在SCL高電平期間,SDA一直保持穩定,沒有跳變)
//只有當SCL被拉低後,SDA才能被改變
//總結:在SCL爲高電平期間,發送數據,發送8次數據,數據爲1,SDA被拉高,數據爲0,SDA被拉低。
//傳輸期間保持傳輸穩定,所以數據線僅可以在時鐘SCL爲低電平時改變。
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
    SDA_OUT();         
    IIC_SCL=0;//拉低時鐘開始數據傳輸
    for(t=0;t<8;t++)
    {              
        //IIC_SDA=(txd&0x80)>>7;   //獲取最高位
        //獲取數據的最高位,然後左移7位
        //如果某位爲1,則SDA爲1,否則相反
        if((txd&0x80)>>7)
            IIC_SDA=1;
        else
            IIC_SDA=0;
        txd<<=1;       
        delay_us(2);   
        IIC_SCL=1;
        delay_us(2); 
        IIC_SCL=0;    
        delay_us(2);
    }     
}       

IIC讀取一個字節數據:


//讀1個字節,ack=1時,發送ACK,ack=0,發送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();        //SDA設置爲輸入
    for(i=0;i<8;i++ )
	{
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();        //發送nACK
    else
        IIC_Ack();         //發送ACK   
    return receive;
}

IIC發送數據

在這裏插入圖片描述
在這裏插入圖片描述

Start: IIC開始信號,表示開始傳輸。
DEVICE_ADDRESS:: 從設備地址,就是7位從機地址
R/W: W(write)爲寫,R(read)爲讀
ACK: 應答信號
WORD_ADDRESS : 從機中對應的寄存器地址 比方說訪問 OLED中的 某個寄存器
DATA: 發送的數據
STOP: 停止信號。結束IIC

主機要向從機寫數據時:

  1. 主機首先產生START信號
  2. 然後緊跟着發送一個從機地址,這個地址共有7位,緊接着的第8位是數據方 向位(R/W),0表示主機發送數據(寫),1表示主機接收數據(讀)
  3. 主機發送地址時,總線上的每個從機都將這7位地址碼與自己的地址進行比較,若相同,則認爲自己正在被主機尋址,根據R/T位將自己確定爲發送器和接收器
  4. 這時候主機等待從機的應答信號(A)
  5. 當主機收到應答信號時,發送要訪問從機的那個地址, 繼續等待從機的應答信號
  6. 當主機收到應答信號時,發送N個字節的數據,繼續等待從機的N次應答信號,
  7. 主機產生停止信號,結束傳送過程。

IIC讀數據:

在這裏插入圖片描述
主機要從從機讀數據時

  1. 主機首先產生START信號
  2. 然後緊跟着發送一個從機地址,注意此時該地址的第8位爲0,表明是向從機寫命令,
  3. 這時候主機等待從機的應答信號(ACK)
  4. 當主機收到應答信號時,發送要訪問的地址,繼續等待從機的應答信號,
  5. 當主機收到應答信號後,主機要改變通信模式(主機將由發送變爲接收,從機將由接收變爲發送)所以主機重新發送一個開始start信號,然後緊跟着發送一個從機地址,注意此時該地址的第8位爲1,表明將主機設 置成接收模式開始讀取數據,
  6. 這時候主機等待從機的應答信號,當主機收到應答信號時,就可以接收1個字節的數據,當接收完成後,主機發送非應答信號,表示不在接收數據
  7. 主機進而產生停止信號,結束傳送過程。

以AT24C02爲例子

T24C02是一個2K位串行CMOS E2PROM,有一個16字節頁寫緩衝器。該器件通過IIC總線接口進行操作,有一個專門的寫保護功能, 如果WP管腳連接到Vcc,所有的內容都被寫保護只能讀。當WP管腳連接到Vss or GND 或懸空允許器件進行正常的讀/寫操作。

可以看出對於不同大小的24Cxx,具有不同的從器件地址。由於24C02爲2k容量,也就是說只需要參考圖中第一行的內容:
在這裏插入圖片描述
芯片的尋址:
AT24C02是的固定地址是1010A2A1A0R/W,A2A1A0這三位是由引腳確定的,一般都是000,

也就是說如果是寫24C02的時候,從器件地址爲10100000(0xA0);讀24C02的時候,從器件地址爲10100001(0xA1)。

片內地址尋址:

芯片尋址可對內部256B中的任一個進行讀/寫操作,其尋址範圍爲00~FF,共256個尋址單位。

對應的修改 A2A1A0 三位數據即可
在這裏插入圖片描述


//IIC發送數據
//address 要寫入的地址
//date 要寫入的數據
void write_add(uchar address,uchar date)
{
        IIC_Start();
        IIC_Send_Byte(0xA0);
       	delay(2);
        IIC_Send_Byte(address);
        delay(2);
        IIC_Send_Byte(date);
       delay(2);
        IIC_Stop();
}
//IIC讀取數據
// address 要讀取數據的地址
uchar read_add(uchar address)  //指定地址讀一個字節數據
{
	uchar add;
	IIC_Start();
	IIC_Send_Byte(0xA0);
	delay(2);
	IIC_Send_Byte(address);
	delay(2);
	IIC_Start();
	IIC_Send_Byte(0xA1);
	delay(2);
	dd=IIC_Read_Byte();
	 IIC_Stop();
	return add;
}

軟件IIC和硬件IIC

IIC分爲軟件IIC和硬件IIC

軟件IIC:軟件IIC通信指的是用單片機的兩個I/O端口模擬出來的IIC,用軟件控制管腳狀態以模擬I2C通信波形,軟件模擬寄存器的工作方式。

硬件IIC:一塊硬件電路,硬件I2C對應芯片上的I2C外設,有相應I2C驅動電路,其所使用的I2C管腳也是專用的,硬件(固件)I2C是直接調用內部寄存器進行配置。

硬件I2C的效率要遠高於軟件的,而軟件I2C由於不受管腳限制,接口比較靈活。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章