在談IIC前,我們先將IIC的通信分為三步,準備、通信、結(jié)束階段
1. 通信準備IIC通信至少要兩條通道,一條時鐘線SCL,一條數(shù)據(jù)線SDA,而這兩條線可以連接很多的設(shè)備。雖然IIC連接著很多的設(shè)備,但是在IIC沒有與各個設(shè)備通信時,IIC均處于休眠狀態(tài),這時候就需要通過主機來喚醒設(shè)備了。 我們首先看時序圖,怎么開始IIC的動作,及怎么結(jié)束II: 然后再看代碼(somenop()為延時函數(shù),延時時間主要是看單片的時鐘周期,我所使用的單片機芯片是IAP15F2K6102) void somenop(void) { uchar t; _nop_(); _nop_(); t = 12; while(--t); }
void IIC_Start(void) { SDA = 1;SCL = 1; somenop(); SDA = 0; somenop(); SCL = 0; }
void IIC_Stop(void) { SDA = 0; SCL = 1; somenop(); SDA = 1; somenop(); }
當我們啟動IIC后,下一步就是尋找設(shè)備了,于是我們發(fā)送一個地址,像PCF8591,喚醒它的地址就是0x90(二進制數(shù)1001 0000),喚醒AT24C02的地址則是0xa0(二進制數(shù)1010 0000)這時候需要設(shè)備給一個響應(yīng)來說明設(shè)備收到消息了,然后由單片機接受即可,所以設(shè)備與單片機達成通信的條件了,然后兩邊建立了通信通道后,單片機就開始選用所需設(shè)備的功能端口地址了。 如:選擇PCF8591的A0、A1、A2、A3通道的話,就可以分別發(fā)送0x00、0x01、0x10、0x11;選擇AT24C02的A0、A1、A2通道的話,就可以分別發(fā)送對應(yīng)地址(因為AT24C02還帶有讀/寫地址,該地址是在最后一位,這里就不詳細談了)。 在IIC開始,選擇設(shè)備地址以及,選擇使用那個通道以及選擇讀數(shù)據(jù)還是寫數(shù)據(jù)后,通信準備階段完成。
2. 開始通信首先我們要知道IIC是半雙工通信,同一時刻只有一個設(shè)備發(fā)送數(shù)據(jù)個另一個設(shè)備,兩個設(shè)備開始通信時,主機一直控制SCL時鐘線并由它來產(chǎn)生出時鐘信號(也就是脈沖信號),然后,兩設(shè)備通過SDA線發(fā)送數(shù)據(jù)來互相通信。 當主機接受從機數(shù)據(jù)時(也就是主機讀取從機數(shù)據(jù)),時鐘信號的電平為低的時間內(nèi),從機通過數(shù)據(jù)線發(fā)出高低電平的信號;當時鐘信號為高電平期時,主機讀取讀取信號,此時數(shù)據(jù)線的電平不能改變。發(fā)送八位數(shù)據(jù)后,主機會收到從機的應(yīng)答,也就是第九個脈沖的時候是應(yīng)答時間,從機將SDA數(shù)據(jù)線置為低電平,此時被主機檢測到。于是一個數(shù)據(jù)就傳輸成功了,主機收到的數(shù)據(jù)是一個二進制,數(shù)據(jù)如果為00101101,轉(zhuǎn)換十六進制是0x2D,然后多做幾個這樣的步驟,數(shù)據(jù)就讀取到了。 同理從機接受主機的數(shù)據(jù)時(主機寫數(shù)據(jù)給從機),時鐘信號還是主機產(chǎn)生的,然后數(shù)據(jù)是由從機發(fā)給主機,發(fā)送8位數(shù)據(jù)后,主機發(fā)給從機應(yīng)答信號,此時一個數(shù)據(jù)也就成功發(fā)送了。
3. 結(jié)束通信主機再數(shù)據(jù)發(fā)送完后(即應(yīng)答時間內(nèi))給從機一個非應(yīng)答信號(主機將SDA電平拉高)后解釋IIC,這時候IIC通信告一段落了,最后也就完成了一次通信,數(shù)據(jù)傳輸進行完畢。
4. 注意點
IIC開始、結(jié)束及SCL的時鐘周期是必須合適的,一般都大于5us就可以了(這個時間也可能和設(shè)備有關(guān))。時間太短會導(dǎo)致數(shù)據(jù)傳輸有問題,或者從機來不急應(yīng)答;時間太長的話……可能數(shù)據(jù)傳輸太慢吧(知識盲區(qū)了)。
以上就是我對IIC的理解了,這也僅僅是我個人的理解,避免不了錯誤之處,也希望諸位指正。(2020年7月30日寫)
|