I2C總線操作
對(duì)I2C總線的操作實(shí)際就是主從設(shè)備之間的讀寫操作。大致可分為以下三種操作情況:
第一,主設(shè)備往從設(shè)備中寫數(shù)據(jù)。數(shù)據(jù)傳輸格式如下:
第二,主設(shè)備從從設(shè)備中讀數(shù)據(jù)。數(shù)據(jù)傳輸格式如下:
第三,主設(shè)備往從設(shè)備中寫數(shù)據(jù),然后重啟起始條件,緊接著從從設(shè)備中讀取數(shù)據(jù);或者是主設(shè)備從從設(shè)備中讀數(shù)據(jù),然后重啟起始條件,緊接著主設(shè)備往從設(shè)備中寫數(shù)據(jù)。數(shù)據(jù)傳輸格式如下:
第三種操作在單個(gè)主設(shè)備系統(tǒng)中,重復(fù)的開啟起始條件機(jī)制要比用STOP終止傳輸后又再次開啟總線更有效率。
1.2.1 I2C總線硬件接口電路示例一
這個(gè)電路是基于LPC2368 ARM7芯片進(jìn)行設(shè)計(jì)的,使用其內(nèi)部的I2C接口作為主設(shè)備,使用ADT75和SC16IS740作為兩個(gè)從設(shè)備的I2C總線應(yīng)用。
ADT75是一個(gè)帶I2C接口的溫度傳感器器件,數(shù)據(jù)手冊(cè)上對(duì)其地址的描述如下:
由此,其地址跟A0、A1、A2引腳的接法有關(guān),我們這里的實(shí)例是將A0、A1、A2全部接到高電平上,因此其地址是:1001111(即0x4F),又因根據(jù)協(xié)議再給地址添加一個(gè)最低位(方向位,默認(rèn)給寫方向),因此最后這個(gè)溫度傳感器作為從設(shè)備的地址是:10011110(即0x9E)。
SC16IS740是一個(gè)具有I2C或者SPI接口的擴(kuò)展UART的器件(通過第8腳來(lái)決定使用I2C還是SPI接口,我們這里要求使用I2C接口,因此將第8腳接到高電平)。根據(jù)數(shù)據(jù)手冊(cè),我們同樣的可以知道地址跟A0、A1的接法有關(guān),我們這里的A0接高電平,A1接低電平。因此這個(gè)器件作為從設(shè)備的地址是:10010010(即0x92)。
1.2.2 I2C總線硬件接口電路示例二
這個(gè)電路是Mini2440開發(fā)板上I2C總線接口的應(yīng)用。我們可以看到,SDA和SCL線上接了一個(gè)10K的上拉排阻。AT24C08是一個(gè)容量為8Kbit的EEPROM存儲(chǔ)器件(注意是8Kbit,也就是1KB) ,根據(jù)數(shù)據(jù)手冊(cè)中器件地址部分的描述,AT24C08的地址是:1010+A2A1A0+方向位,其中1010是EEPROM的類型識(shí)別符;僅僅使用A2來(lái)確定總線訪問本器件的從設(shè)備地址,這里接的低電平,所以為0;A1和A0是器件內(nèi)部頁(yè)地址,在對(duì)器件擦除或者編程時(shí)使用,雖然這里也接的低電平,但器件內(nèi)部并不使用引腳的輸入值,也就是說(shuō)A1和A0的值是由軟件進(jìn)行設(shè)定的。
1.3 脫離操作系統(tǒng)的I2C總線驅(qū)動(dòng)示例(以電路示例一為例)
1.3.1 LPC2368中I2C接口寄存器描述
LPC2368中有三個(gè)I2C總線接口,分別表示為I2C0、I2C1和I2C2,每個(gè)I2C接口都包含7個(gè)寄存器。它們分別是:
I2C控制置位寄存器(I2CONSET): 8位寄存器,各位不同的設(shè)置是對(duì)I2C總線不同的控制。
在前面的I2C總線特征中我們提到過,I2C總線的速率通過可編程時(shí)鐘來(lái)調(diào)整,即必須通過軟件對(duì)I2SCLH和I2SCLL寄存器進(jìn)行設(shè)置來(lái)選擇合適的數(shù)據(jù)頻率和占空比。 頻率由下面的公式得出(fPCLK是PCLK的頻率)。
LPC2368中I2C總線操作
在1.1.4中我們已經(jīng)講過了對(duì)I2C總線的操作,但那只是從協(xié)議和時(shí)序上的描述,那我們?nèi)绾螐能浖先ンw現(xiàn)出來(lái)呢?接下來(lái)我們就討論這個(gè)問題。
對(duì)I2C總線上主從設(shè)備的讀寫可使用兩種方法,一是使用輪詢的方式,二是使用中斷的方式。輪詢方式即是在一個(gè)循環(huán)中判斷I2C狀態(tài)寄存器當(dāng)前的狀態(tài)值來(lái)確定總線當(dāng)前所處的狀態(tài),然后根據(jù)這個(gè)狀態(tài)來(lái)進(jìn)行下一步的操作。中斷方式即是使能I2C中斷,注冊(cè)I2C中斷服務(wù)程序,在服務(wù)程序中讀取I2C狀態(tài)寄存器的當(dāng)前狀態(tài)值,再根據(jù)狀態(tài)值來(lái)確定下一步的操作。
不管使用哪種方法,看來(lái)I2C狀態(tài)寄存器的值是至關(guān)重要的。這些狀態(tài)值代表什么意思呢?下面我們描述一些常用的狀態(tài)值(詳細(xì)的狀態(tài)值含義請(qǐng)參考數(shù)據(jù)手冊(cè))。
0x08: 表明主設(shè)備向總線已發(fā)出了一個(gè)起始條件;
0x10: 表明主設(shè)備向總線已發(fā)出了一個(gè)重復(fù)的起始條件;
0x18: 表明主設(shè)備向總線已發(fā)送了一個(gè)從設(shè)備地址(寫方向)并且接收到從設(shè)備的應(yīng)答;
0x20: 表明主設(shè)備向總線已發(fā)送了一個(gè)從設(shè)備地址(寫方向)并且接收到從設(shè)備的非應(yīng)答;
0x28: 表明主設(shè)備向總線已發(fā)送了一個(gè)數(shù)據(jù)字節(jié)并且接收到從設(shè)備的應(yīng)答;
0x30: 表明主設(shè)備向總線已發(fā)送了一個(gè)數(shù)據(jù)字節(jié)并且接收到從設(shè)備的非應(yīng)答;
0x40: 表明主設(shè)備向總線已發(fā)送了一個(gè)從設(shè)備地址(讀方向)并且接收到從設(shè)備的應(yīng)答;
0x48: 表明主設(shè)備向總線已發(fā)送了一個(gè)從設(shè)備地址(讀方向)并且接收到從設(shè)備的非應(yīng)答;
0x50: 表明主設(shè)備從總線上已接收一個(gè)數(shù)據(jù)字節(jié)并且返回了應(yīng)答;
0x58: 表明主設(shè)備從總線上已接收一個(gè)數(shù)據(jù)字節(jié)并且返回了非應(yīng)答;
四、 總線信號(hào)時(shí)序分析
1. 總線空閑狀態(tài)
SDA和SCL兩條信號(hào)線都處于高電平,即總線上所有的器件都釋放總線,兩條信號(hào)線各自的上拉電阻把電平拉高;
2. 啟動(dòng)信號(hào)START
時(shí)鐘信號(hào)SCL保持高電平,數(shù)據(jù)信號(hào)SDA的電平被拉低(即負(fù)跳變)。啟動(dòng)信號(hào)必須是跳變信號(hào),而且在建立該信號(hào)前必修保證總線處于空閑狀態(tài);
3. 停止信號(hào)STOP
時(shí)鐘信號(hào)SCL保持高電平,數(shù)據(jù)線被釋放,使得SDA返回高電平(即正跳變),停止信號(hào)也必須是跳變信號(hào)。
4. 數(shù)據(jù)傳送
SCL線呈現(xiàn)高電平期間,SDA線上的電平必須保持穩(wěn)定,低電平表示0(此時(shí)的線電壓為地電壓),高電平表示1(此時(shí)的電壓由元器件的VDD決定)。只有在SCL線為低電平期間,SDA上的電平允許變化。
5. 應(yīng)答信號(hào)ACK
I2C總線的數(shù)據(jù)都是以字節(jié)(8位)的方式傳送的,發(fā)送器件每發(fā)送一個(gè)字節(jié)之后,在時(shí)鐘的第9個(gè)脈沖期間釋放數(shù)據(jù)總線,由接收器發(fā)送一個(gè)ACK(把數(shù)據(jù)總線的電平拉低)來(lái)表示數(shù)據(jù)成功接收。
6. 無(wú)應(yīng)答信號(hào)NACK
在時(shí)鐘的第9個(gè)脈沖期間發(fā)送器釋放數(shù)據(jù)總線,接收器不拉低數(shù)據(jù)總線表示一個(gè)NACK,NACK有兩種用途:
a. 一般表示接收器未成功接收數(shù)據(jù)字節(jié);
b. 當(dāng)接收器是主控器時(shí),它收到最后一個(gè)字節(jié)后,應(yīng)發(fā)送一個(gè)NACK信號(hào),以通知被控發(fā)送器結(jié)束數(shù)據(jù)發(fā)送,并釋放總線,以便主控接收器發(fā)送一個(gè)停止信號(hào)STOP。
評(píng)論