1、 概述html
1. IIC總線是PHILIPS公司推出的一種串口總線,是具有多主機系統所需的包括總線裁決和高低速器件同步功能的高性能串口總線。編程
2. IIC總線只有兩根雙向信號線。一根是數據線SDA,一根是時鐘線SCL。函數
3. 鏈接到相同總線的IC數量,受總線最大電容400pF的限制。性能
4. IIC總線經過上拉電阻接正電源。當總線空閒時,兩根線均爲高電平。連到總線上的任何一個器件輸出的低電平,都將使總線的信號變低,spa
即各器件的SDA和SCL都是線「與」的關係。3d
5. 每一個連到總線上的器件都有一個惟一的地址。主機與其餘器件的數據傳送可使主機發送數據到其餘器件,這時主機就是發送器。在總線上code
接受數據的器件則爲接收器。htm
6. 在多主機系統中,可能同時有幾個主機企圖啓動總線發送數據,爲了不混亂,IIC總線要經過總線仲裁,以決定由哪一臺主機控制總線。blog
2、 IIC總線的數據傳送接口
1. 數據位的有效性
IIC總線在進行數據傳送時,時鐘信號爲高電平期間,數據線上的數據必須保持穩定;只有在時鐘線上的信號是低電平時,數據線上的電平才容許變化。
2. 起始和終止信號
SCL線爲高電平期間,SDA線由高到低變化表示起始。
SCL線爲高電平期間,SDA線由低到高變化表示終止。
起始和終止都是主機發出的,在起始信號開始後,總線就處於被佔用狀態;在終止信號產生後,總線就處於空閒狀態。
鏈接到IIC總線上的設備,若是具備IIC總線的硬件接口,很容易檢測到起始和終止信號。
接收器收到一個完整的數據字節後,有可能須要完成一些其餘工做,可能沒法馬上接收下一個字節,這時接收器能夠將SCL線拉低,
從而使主機處於等待狀態。直到slave device準備好接收下一個字節時,再釋放SCL線使之爲高電平,從而數據傳輸continue.
3、 數據傳送格式
1. 字節傳送與應答
每一個字節必須是8bit長度。數據傳送時,先傳最高位MSB,每個被傳送字節後面必須跟一個應答位(即一幀共9個bit)。
若是slave不對master作尋址信號應答時,slave必須將數據線SDA置於高電平,而由主機產生一個STOP信號以結束傳送。
若是slave對master尋址應答後,但在數據傳送一段時間後沒法繼續接收更多數據時,slave能夠對沒法接收的第一個數據字節「非應答」
通知主機。主機則發出STOP信號以結束數據傳送。
當主機接收數據時,它收到最後一個數據字節後,必須向從機發出一個結束傳送的信號。這個信號是對從機的「非應答」來實現的。而後,
從機釋放SDA線,容許主機產生STOP信號。
2. 數據幀格式
IIC總線上傳送的數據信號是廣義的。既包括地址信號,也包含真正的數據信號。
在起始信號後必須傳送一個從機的地址(7bit),第8位是數據的傳送方向位(R/T)。「0」表示主機發送數據(T/write),「1」表示主機
接收數據(R/Read)。每次數據傳送老是由主機產生終止信號。
可是,若是主機但願繼續佔用總線進行新的數據傳送,則能夠不產生終止信號,立刻再次發出起始信號對另外一個從機進行尋址。
在總線的一次數據傳送中,能夠有如下幾種組合方式:
(陰影部分表示數據從主機向從機傳送,無陰影部分表示數據由從機向主機傳送。A表示應答,A非表示非應答(高電平)。S是起始信號,P表示終止信號。)
1)主機向從機發送數據,數據傳送方向在整個傳送過程當中不變:
2)主機在第一個字節後,當即從從機讀數據。
3)在傳送過程當中,當須要改變傳送方向時,起始信號和從機地址都被重複產生一次,但兩次讀寫方向位正好反相。
4、IIC總線的尋址
IIC總線有明確規定:採用7bit尋址字節(尋址字節是起始信號後的第一個字節)。
D7~D1位組成從機的地址。D0位是數據傳送方向位。"0"表示主機向從機寫數據,"1"表示主機向從機讀數據。
主機發送地址時,總線上的每一個從機都將這7位地址碼和本身的地址比較,若是相同,則認爲本身被主機尋址,根據R/T位將本身確認爲發送器
或者接收器。
從機的地址由固定部分和可編程部分組成。在一個系統中,可能但願接入多個相同的從機,從機地址中能夠編程的部分決定了可接入總線該類器件
的最大數目。
(基本的I2C總線規範於20年前發佈,其數據傳輸速率最高爲100Kbits/s,採用7位尋址。可是因爲數據傳輸速率和應用功能的迅速增長,I2C總線
也加強爲快速模式(400Kbits/s)和10位尋址以知足更高速度和更大尋址空間的需求。
I2C總線始終和先進技術保持同步,但仍然保持其向下兼容性。而且最近還增長了高速模式,其速度可達3.4Mbits/s。它使得I2C總線可以支持現有
以及未來的高速串行傳輸應用,例如EEPROM和Flash存儲器。)
參考來源:紅茶的博客->IIC總線 http://blog.sina.com.cn/s/blog_9815359e01012c6k.html
附:模擬IIC代碼
/************************************************************** * 函數名:IIC_Start * 描 述:產生起始信號 * 說 明:SCL爲高電平時,SDA降低沿啓動信號 **************************************************************/ void IIC_Start(void) { IIC_SDA_OUT(); // SDA線設置爲輸出 IIC_SDA_SET(); // SDA線輸出高電平 delay_us(5); IIC_SCL_SET(); // SCL線輸出高電平 delay_us(5); IIC_SDA_CLR(); // SDA線產生降低沿 delay_us(5); IIC_SCL_CLR(); // 鉗住I2C總線,準備發送或接收數據 }
/************************************************************** * 函數名:IIC_Stop * 描 述:產生中止信號 * 說 明:SCL爲高電平時,SDA一個上升沿中止信號 **************************************************************/ void IIC_Stop(void) { IIC_SDA_OUT(); // SDA線設置爲輸出 IIC_SCL_CLR(); // SCL線輸出低電平 delay_us(5); IIC_SDA_CLR(); // SDA線輸出低電平 delay_us(5); IIC_SCL_SET(); // SCL線輸出高電平 delay_us(5); IIC_SDA_SET(); // SDA線輸出高電平 delay_us(5); }
/************************************************************** * 函數名:IIC_Wait_Ack * 描 述:等待接收應答信號 * 說 明:每傳送一個字節的數據(地址及命令)後,接收設備都會產生 一個應答信號。SCL爲高電平期間,接受設備將SDA拉低表示應答, 不然爲非應答 * 返回值:1,接收應答失敗 0,接收應答成功 **************************************************************/ unsigned char IIC_Wait_Ack(void) { unsigned char ucErrTime=0; IIC_SDA_SET(); IIC_SDA_IN(); IIC_SCL_SET(); while(READ_SDA()) { ucErrTime++; if(ucErrTime>250) { IIC_Stop(); return 1; } } IIC_SCL_CLR(); return 0; }
/************************************************************** * 函數名:IIC_Ack or IIC_NACK * 描 述:產生應答信號 * 說 明:SCL爲高電平期間,SDA爲低電平表示應答,不然爲非應答 **************************************************************/ // 應答 void IIC_Ack(void) { IIC_SCL_CLR(); // SCL線輸出低電平 IIC_SDA_OUT(); // SDA線設置爲輸出 IIC_SDA_CLR(); // SDA線輸出低電平 delay_us(5); IIC_SCL_SET(); // SCL線輸出高電平 delay_us(5); IIC_SCL_CLR(); // SCL線輸出低電平 } // 非應答 void IIC_NACK(void) { IIC_SCL_CLR(); // SCL線輸出低電平 IIC_SDA_OUT(); // SDA線設置爲輸出 IIC_SDA_SET(); // SDA線輸出高電平 delay_us(5); IIC_SCL_SET(); // SCL線輸出高電平 delay_us(5); IIC_SCL_CLR(); // SCL線輸出低電平 }
/************************************************************** * 函數名:IIC_Send_Byte * 描 述:發送一個字節的數據(地址或命令) * 輸 入:txd,須要發送的數據 * 說 明:IIC總線進行數據傳輸時,SCL爲高電平期間SDA上的數據必須 保持穩定,只有SCL爲低電平期間SDA上的數據才容許變化。 數據傳送時,先傳高位後傳低位。 **************************************************************/ void IIC_Send_Byte(unsigned char txd) { signed char t; IIC_SDA_OUT(); IIC_SCL_CLR(); // 拉低時鐘線SCL,開始數據傳輸 for(t=7; t>=0; t--) { if( 0 != (txd & (1 << t)) ) // 若是data的第i位不爲0 { IIC_SDA_SET(); // SDA線輸出高電平 } else { IIC_SDA_CLR(); // 不然SDA線輸出低電平 } delay_us(5); IIC_SCL_SET(); delay_us(5); IIC_SCL_CLR(); delay_us(5); } IIC_Wait_Ack(); }
/************************************************************** * 函數名:IIC_Read_Byte * 描 述:接收一個字節的數據(地址或命令) * 輸 入:rxd,在IIC總線上讀取的數據 * 說 明:IIC總線進行數據傳輸時,SCL爲高電平期間數據纔是穩定的, 因此在SCL高的時候讀取SDA上的數據。 **************************************************************/ unsigned char IIC_Read_Byte(unsigned char ack) { unsigned char i,rxd=0; IIC_SDA_IN(); for( i=0;i<8;i++ ) { IIC_SCL_CLR(); delay_us(5); IIC_SCL_SET(); delay_us(5); rxd<<=1; if(READ_SDA()) rxd++; } if(!ack) IIC_NACK(); else IIC_Ack(); return rxd; }