|
(1)概述 I2C(Inter-Integrated Circuit BUS) 集成電路總線,該總線由NXP(原PHILIPS)公司設(shè)計,多用于主控制器和從器件間的主從通信,在小數(shù)據(jù)量場合使用,傳輸距離短,任意時刻只能有一個主機(jī)等特性。 經(jīng)常IIC和SPI接口被認(rèn)為指定是一種硬件設(shè)備,但其實這樣的說法是不盡準(zhǔn)確的,嚴(yán)格的說他們都是人們所定義的軟硬結(jié)合體,分為物理層(四線結(jié)構(gòu))和協(xié)議層(主機(jī),從機(jī),時鐘極性,時鐘相位)。 IIC,SPI的區(qū)別不僅在與物理層,IIC比SPI有著一套更為復(fù)雜的協(xié)議層定義。下面來分別說明一下IIC的物理層和協(xié)議層。 (2)IIC的物理層 a.只要求兩條總線線路,一條是串行數(shù)據(jù)線SDA,一條是串行時鐘線SCL。(IIC是半雙工,而不是全雙工)。 b.每個連接到總線的器件都可以通過唯一的地址和其它器件通信,主機(jī)/從機(jī)角色和地址可配置,主機(jī)可以作為主機(jī)發(fā)送器和主機(jī)接收器。 c.IIC是真正的多主機(jī)總線,(而這個SPI在每次通信前都需要把主機(jī)定死,而IIC可以在通訊過程中,改變主機(jī)),如果兩個或更多的主機(jī)同時請求總線,可以通過沖突檢測和仲裁防止總線數(shù)據(jù)被破壞。 d.傳輸速率在標(biāo)準(zhǔn)模式下可以達(dá)到100kb/s,快速模式下可以達(dá)到400kb/s。 e.連接到總線的IC數(shù)量只是受到總線的最大負(fù)載電容400pf限制。 一個典型的IIC接口如下圖(1)所示 圖(1) (3)IIC的協(xié)議層 IIC的協(xié)議層才是掌握IIC的關(guān)鍵?,F(xiàn)在簡單概括如下: a.數(shù)據(jù)的有效性 在時鐘的高電平周期內(nèi),SDA線上的數(shù)據(jù)必須保持穩(wěn)定,數(shù)據(jù)線僅可以在時鐘SCL為低電平時改變。 如圖(2)所示: 圖(2) b.起始和結(jié)束條件 起始條件:當(dāng)SCL為高電平的時候,SDA線上由高到低的跳變被定義為起始條件,結(jié)束條件:當(dāng)SCL為高電平的時候,SDA線上由低到高的跳變被定義為停止條件,要注意起始和終止信號都是由主機(jī)發(fā)出的,連接到I2C總線上的器件,若具有I2C總線的硬件接口,則很容易檢測到起始和終止信號。總線在起始條件之后,視為忙狀態(tài),在停止條件之后被視為空閑狀態(tài),對起始條件和結(jié)束條件的描述如下圖(3)所示。 圖(3) c.應(yīng)答 每當(dāng)主機(jī)向從機(jī)發(fā)送完一個字節(jié)的數(shù)據(jù),主機(jī)總是需要等待從機(jī)給出一個應(yīng)答信號,以確認(rèn)從機(jī)是否成功接收到了數(shù)據(jù),從機(jī)應(yīng)答主機(jī)所需要的時鐘仍是主機(jī)提供的,應(yīng)答出現(xiàn)在每一次主機(jī)完成8個數(shù)據(jù)位傳輸后緊跟著的時鐘周期,低電平0表示應(yīng)答,1表示非應(yīng)答,如圖(4)所示。 圖(4) d.數(shù)據(jù)幀格式
I2C總線上傳送的數(shù)據(jù)信號是廣義的,既包括地址信號,又包括真正的數(shù)據(jù)信號。
在起始信號后必須傳送一個從機(jī)的地址(7位),第8位是數(shù)據(jù)的傳送方向位(R/T),用“0”表示主機(jī)發(fā)送數(shù)據(jù)(T),“1”表示主機(jī)接收數(shù)據(jù)(R)。{這里小編在驅(qū)動MPU6050模塊的時候,就犯過這樣的錯誤,它寫的MPU6050從機(jī)地址是0x68,因為發(fā)送從機(jī)地址的時候,要加一位讀寫方向位,因為剛開始應(yīng)該是向這個MPU6050里寫從機(jī)里某個寄存器的地址,所以應(yīng)該是7位地址
0x68(1101000)+二進(jìn)制位0=11010000)也就是0xD0,表示要向該IIC設(shè)備里寫東西,然后再緊接著寫入IIC設(shè)備里的寄存器地址,而我直接寫入了0x68,導(dǎo)致出錯},每次數(shù)據(jù)傳送總是由主機(jī)產(chǎn)生的終止信號結(jié)束。但是,若主機(jī)希望繼續(xù)占用總線進(jìn)行新的數(shù)據(jù)傳送,則可以不產(chǎn)生終止信號,馬上再次發(fā)出起始信號對另一從機(jī)進(jìn)行尋址。
在總線的一次數(shù)據(jù)傳輸過程中,可以有以下幾種組合方式:
[1]
主機(jī)向從機(jī)發(fā)送數(shù)據(jù),數(shù)據(jù)傳送方向在整個傳送過程中不變:
注:有陰影部分表示數(shù)據(jù)由主機(jī)向從機(jī)傳送,無陰影部分則表示數(shù)據(jù)由從機(jī)向主機(jī)傳送。
A表示應(yīng)答(低電平), A非表示非應(yīng)答(高電平)。S表示起始信號,P表示終止信號。
[2]主機(jī)在第一個字節(jié)后,立即從從機(jī)讀數(shù)據(jù):
[3]在傳送過程中,當(dāng)需要改變傳送方向時,起始信號和從機(jī)地址都被重復(fù)產(chǎn)生一次,但兩次讀/寫方向位正好反相:
發(fā)送起始信號
等待從機(jī)應(yīng)答
寫一個從機(jī)地址+0(表示寫),
等待從機(jī)應(yīng)答
發(fā)送一個字節(jié)的MPU6050加速度存儲寄存器地址,
等待從機(jī)應(yīng)答
再發(fā)送一次起始信號
等待從機(jī)應(yīng)答
寫一個從機(jī)地址+1(表示讀)
等待從機(jī)應(yīng)答
讀取MPU6050傳感器數(shù)據(jù)
主機(jī)非應(yīng)答
e.IIC信號的模擬
主機(jī)可以采用不帶I2C總線接口的單片機(jī),如80C51、AT89C2051等單片機(jī),利用軟件實現(xiàn)I2C總線的數(shù)據(jù)傳送,即軟件與硬件結(jié)合的信號模擬。即使是含有IIC硬件的單片機(jī)(如stm32 103系列)也有一定的缺陷,所以一般也會模擬IIC的時序?,F(xiàn)將具體時間截圖如下:
具體的程序代碼如下:
void I2C_Start(void) { I2C_SDA_OUT();//配置一下引腳,引腳設(shè)置為輸出 I2C_SDA_H;//把數(shù)據(jù)線拉高 I2C_SCL_H;//把時鐘線拉高 delay_us(5);//延時5微秒,要求大于4.7微秒 I2C_SDA_L; //拉低,產(chǎn)生下降沿 delay_us(6);//這個過程大于4微秒 I2C_SCL_L;//最后一定要把這個時鐘線拉低,因為只有時鐘線拉低的時候才允許數(shù)據(jù)變化。 } //產(chǎn)生停止信號
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); } //主機(jī)產(chǎn)生應(yīng)答信號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; } //主機(jī)不產(chǎn)生應(yīng)答信號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; } //等待從機(jī)應(yīng)答信號,我們只負(fù)責(zé)主機(jī)應(yīng)答信號的產(chǎn)生,從機(jī)應(yīng)答信號
//我們不控制。 //返回值:1 接收應(yīng)答失敗 // 0 接收應(yīng)答成功 u8 I2C_Wait_Ack(void) { u8 tempTime=0; I2C_SDA_IN(); //配置為上拉輸入。 I2C_SDA_H; //主機(jī)釋放數(shù)據(jù)總線,等待從機(jī)產(chǎn)生應(yīng)答信號 delay_us(1); I2C_SCL_H; delay_us(1); //等待從機(jī)對數(shù)據(jù)總線的操作。低電平代表應(yīng)答 while(GPIO_ReadInputDataBit(GPIO_I2C,I2C_SDA)) { tempTime++; //這個屬于軟件延時,不一定準(zhǔn)確。 if(tempTime>250) //如果時間超時,沒有應(yīng)答就停止。 { I2C_Stop(); return 1; //沒有響應(yīng)的話返回1. } } I2C_SCL_L; return 0; //如果有響應(yīng)的話就返回0. }
|
|
|