一、 概述
1. IIC總線是PHILIPS公司推出的一種串口總線,是具備多主機系統所需的包括總線裁決和高低速器件同步功能的高性能串口總線。
2. IIC總線只有兩根雙向信號線。一根是數據線SDA,一根是時鍾線SCL。
3. 連接到相同總線的IC數量,受總線最大電容400pF的限制。
4. IIC總線通過上拉電阻接正電源。當總線空閑時,兩根線均為高電平。連到總線上的任何一個器件輸出的低電平,都將使總線的信號變低,
即各器件的SDA和SCL都是線“與”的關系。
5. 每個連到總線上的器件都有一個唯一的地址。主機與其他器件的數據傳送可以使主機發送數據到其他器件,這時主機就是發送器。在總線上
接受數據的器件則為接收器。
6. 在多主機系統中,可能同時有幾個主機企圖啟動總線發送數據,為了避免混亂,IIC總線要通過總線仲裁,以決定由哪一台主機控制總線。
二、 IIC總線的數據傳送
1. 數據位的有效性
IIC總線在進行數據傳送時,時鍾信號為高電平期間,數據線上的數據必須保持穩定;只有在時鍾線上的信號是低電平時,數據線上的電平才允許變化。
2. 起始和終止信號
SCL線為高電平期間,SDA線由高到低變化表示起始。
SCL線為高電平期間,SDA線由低到高變化表示終止。
起始和終止都是主機發出的,在起始信號開始后,總線就處於被占用狀態;在終止信號產生后,總線就處於空閑狀態。
連接到IIC總線上的設備,如果具有IIC總線的硬件接口,很容易檢測到起始和終止信號。
接收器收到一個完整的數據字節后,有可能需要完成一些其他工作,可能無法立刻接收下一個字節,這時接收器可以將SCL線拉低,
從而使主機處於等待狀態。直到slave device准備好接收下一個字節時,再釋放SCL線使之為高電平,從而數據傳輸continue.
三、 數據傳送格式
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)在傳送過程中,當需要改變傳送方向時,起始信號和從機地址都被重復產生一次,但兩次讀寫方向位正好反相。
四、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; }