2. 寫操作步驟:
2.1 主機(jī)發(fā)起通信,按約定依次寫入command、要寫入的從機(jī)寄存器地址address和要寫入的數(shù)據(jù)data;
2.2 從機(jī)firmware要做的處理:
2.2.1 分別提取command、address和data;
2.2.2 根據(jù)command做出判斷(本例中則判斷是寫入還是讀取);
2.2.3 將data寫入與接收到的address對(duì)應(yīng)的寄存器。(這個(gè)步驟可以使用指針)。

4、主機(jī)發(fā)送數(shù)據(jù)流程
(1)主機(jī)在檢測(cè)到總線為“空閑狀態(tài)”(即 SDA、SCL 線均為高電平)時(shí),發(fā)送一個(gè)啟動(dòng)信號(hào)“S”,開始一次通信的開始
(2)主機(jī)接著發(fā)送一個(gè)命令字節(jié)。該字節(jié)由 7 位的外圍器件地址和 1 位讀寫控制位 R/W組成(此時(shí) R/W=0)
(3)相對(duì)應(yīng)的從機(jī)收到命令字節(jié)后向主機(jī)回饋應(yīng)答信號(hào) ACK(ACK=0)
(4)主機(jī)收到從機(jī)的應(yīng)答信號(hào)后開始發(fā)送第一個(gè)字節(jié)的數(shù)據(jù)
(5)從機(jī)收到數(shù)據(jù)后返回一個(gè)應(yīng)答信號(hào) ACK
(6)主機(jī)收到應(yīng)答信號(hào)后再發(fā)送下一個(gè)數(shù)據(jù)字節(jié)
(7)當(dāng)主機(jī)發(fā)送最后一個(gè)數(shù)據(jù)字節(jié)并收到從機(jī)的 ACK 后,通過(guò)向從機(jī)發(fā)送一個(gè)停止信號(hào)P結(jié)束本次通信并釋放總線。從機(jī)收到P信號(hào)后也退出與主機(jī)之間的通信

注意:①主機(jī)通過(guò)發(fā)送地址碼與對(duì)應(yīng)的從機(jī)建立了通信關(guān)系,而掛接在總線上的其它從機(jī)雖然同時(shí)也收到了地址碼,但因?yàn)榕c其自身的地址不相符合,因此提前退出與主機(jī)的通信;②主機(jī)的一次發(fā)送通信,其發(fā)送的數(shù)據(jù)數(shù)量不受限制。主機(jī)是通過(guò) P 信號(hào)通知發(fā)送的結(jié)束,從機(jī)收到 P 信號(hào)后退出本次通信;③主機(jī)的每一次發(fā)送后都是通過(guò)從機(jī)的 ACK 信號(hào)了解從機(jī)的接收狀況,如果應(yīng)答錯(cuò)誤則重發(fā)。
5、主機(jī)接收數(shù)據(jù)流程
(1)主機(jī)發(fā)送啟動(dòng)信號(hào)后,接著發(fā)送命令字節(jié)(其中 R/W=1)
(2)對(duì)應(yīng)的從機(jī)收到地址字節(jié)后,返回一個(gè)應(yīng)答信號(hào)并向主機(jī)發(fā)送數(shù)據(jù)
(3)主機(jī)收到數(shù)據(jù)后向從機(jī)反饋一個(gè)應(yīng)答信號(hào)
(4)從機(jī)收到應(yīng)答信號(hào)后再向主機(jī)發(fā)送下一個(gè)數(shù)據(jù)
(5)當(dāng)主機(jī)完成接收數(shù)據(jù)后,向從機(jī)發(fā)送一個(gè)“非應(yīng)答信號(hào)(ACK=1)”,從機(jī)收到ASK=1 的非應(yīng)答信號(hào)后便停止發(fā)送
(6)主機(jī)發(fā)送非應(yīng)答信號(hào)后,再發(fā)送一個(gè)停止信號(hào),釋放總線結(jié)束通信

注意:主機(jī)所接收數(shù)據(jù)的數(shù)量是由主機(jī)自身決定,當(dāng)發(fā)送“非應(yīng)答信號(hào)/A”時(shí)從機(jī)便結(jié)束傳送并釋放總線(非應(yīng)答信號(hào)的兩個(gè)作用:前一個(gè)數(shù)據(jù)接收成功,停止從機(jī)的再次發(fā)送)。
6、總線死鎖原因分析
I2C總線寫操作過(guò)程中,主機(jī)在產(chǎn)生啟動(dòng)信號(hào)后控制SCL產(chǎn)生8個(gè)時(shí)鐘脈沖,然后拉低SCL信號(hào)為低電平,在這個(gè)時(shí)候,從機(jī)輸出應(yīng)答信號(hào),將SDA信號(hào)拉為低電平。如果這個(gè)時(shí)候主機(jī)異常復(fù)位,SCL就會(huì)被釋放為高電平。此時(shí),如果從機(jī)沒(méi)有復(fù)位,就會(huì)繼續(xù)I2C的應(yīng)答,將SDA一直拉為低電平,直到SCL變?yōu)榈碗娖剑艜?huì)結(jié)束應(yīng)答信號(hào)。而對(duì)于主機(jī)來(lái)說(shuō),復(fù)位后檢測(cè)SCL和SDA信號(hào),如果發(fā)現(xiàn)SDA信號(hào)為低電平,則會(huì)認(rèn)為I2C總線被占用,會(huì)一直等待SCL和SDA信號(hào)變?yōu)楦唠娖健_@樣,主機(jī)等待從機(jī)釋放SDA信號(hào),而同時(shí)從機(jī)又在等待主機(jī)將SCL信號(hào)拉低以釋放應(yīng)答信號(hào),兩者相互等待,I2C總線進(jìn)人一種死鎖狀態(tài)。同樣,當(dāng)I2C進(jìn)行讀操作時(shí),從機(jī)應(yīng)答后輸出數(shù)據(jù),如果在這個(gè)時(shí)刻主機(jī)異常復(fù)位而此時(shí)從機(jī)輸出的數(shù)據(jù)位正好為0,也會(huì)導(dǎo)致I2C總線進(jìn)入死鎖狀態(tài)。
解決方案通常有如下幾種:
(1)將從機(jī)的電源設(shè)計(jì)為可控,當(dāng)發(fā)生總線死鎖的時(shí)將從機(jī)復(fù)位
(2)可以在從機(jī)的程序中加入監(jiān)測(cè)功能,如果總線長(zhǎng)時(shí)間被拉低則釋放對(duì)總線的控制
(3)在主機(jī)中增加I2C總線恢復(fù)程序。每次主機(jī)復(fù)位后,如果檢測(cè)到SDA被拉低,則控制SCL產(chǎn)生《=9個(gè)時(shí)鐘脈沖(針對(duì)8位數(shù)據(jù)的情況),每發(fā)送一個(gè)時(shí)鐘脈沖就檢測(cè)SDA是否被釋放,如果SDA已經(jīng)被釋放就再模擬產(chǎn)生一個(gè)停止信號(hào),這樣從機(jī)就可以完成被掛起的讀寫操作,從死鎖狀態(tài)中恢復(fù)過(guò)來(lái)。這種方法有一定的局限性,因?yàn)榇蟛糠种鳈C(jī)的I2C模塊由內(nèi)置的硬件電路來(lái)實(shí)現(xiàn),軟件并不能夠直接控制SCL信號(hào)模擬產(chǎn)生需要時(shí)鐘脈沖。
掛在I2C總線上的EEPROM設(shè)備
EEPROM稱為電擦除式只讀存儲(chǔ)器,一般容量很小、用于保存產(chǎn)品的固化參數(shù),此次跟我狹路相逢的是一款來(lái)自ATMEL公司的AT24C512B,總?cè)萘繛?4K,支持以頁(yè)的方式寫入數(shù)據(jù),頁(yè)大小128字節(jié),以下是這款設(shè)備的相關(guān)信息和操作方法(其他型號(hào)類同):
硬件連接。在AT24C512B硬件連接中,跟軟件編程相關(guān)的引腳有三個(gè),除了連接在I2C總線上的時(shí)鐘線(SCL)、數(shù)據(jù)線(SDA)引腳之外,還有一個(gè)寫保護(hù)引腳(WP)連接在GPIO上。
尋址方式。EEPROM可以讓你精確地訪問(wèn)到每一字節(jié),AT24C512B采用16位的尋址方式共計(jì)可以訪問(wèn)65536字節(jié)的地址空間。
讀寫時(shí)序。AT24C512B支持的寫操作有單字節(jié)寫入、按頁(yè)寫入,支持的讀操作有隨機(jī)單字節(jié)或連接讀取、當(dāng)前位置單字節(jié)或連續(xù)讀取,EEPROM一般在電路中做從設(shè)備,我此次面對(duì)的也是,以下是主設(shè)備對(duì)EEPROM進(jìn)行各種操作的操作方法:
單字節(jié)寫入:START -》 發(fā)送從設(shè)備地址(寫控制碼) -》 處理Ack -》 發(fā)送字節(jié)地址 -》 處理Ack [-》 發(fā)送1字節(jié)數(shù)據(jù) -》 處理Ack] -》 STOP。
按頁(yè)寫入:將單字節(jié)寫入的[ ]中的操作重復(fù)進(jìn)行128次即可實(shí)現(xiàn)。
隨機(jī)單字節(jié)讀取:START -》 發(fā)送從設(shè)備地址(寫控制碼) -》 處理Ack -》 發(fā)送字節(jié)地址 -》 處理Ack -》 START -》 發(fā)送器件地址(讀控制碼) -》 處理Ack -》 接收1字節(jié)數(shù)據(jù) -》 STOP。
隨機(jī)連續(xù)讀取:在隨機(jī)單字節(jié)讀取操作的STOP信號(hào)發(fā)送之前,加入若干個(gè) [-》 發(fā)送Ack -》 接收1字節(jié)數(shù)據(jù)] 即可實(shí)現(xiàn)。
當(dāng)前位置單字節(jié)讀取:START -》 發(fā)送從設(shè)備地址(讀控制碼) -》 處理Ack -》 發(fā)送字節(jié)地址 -》 處理Ack -》 接收1字節(jié)數(shù)據(jù) -》 STOP。當(dāng)前指的是之前進(jìn)行過(guò)讀取操作但是沒(méi)有發(fā)送STOP信號(hào),EEPROM芯片內(nèi)部指針?biāo)诘奈恢眉礊楫?dāng)前位置。
當(dāng)前位置連續(xù)讀取:在當(dāng)前位置單節(jié)讀取操作的STOP信號(hào)發(fā)送之前,加入若干個(gè) [-》 發(fā)送Ack -》 接收1字節(jié)數(shù)據(jù)] 即可實(shí)現(xiàn)。
關(guān)于EEPROM的按頁(yè)寫入。為提高數(shù)據(jù)寫入效率,有的EEPROM設(shè)備用一個(gè)內(nèi)部的RAM來(lái)提供按頁(yè)寫入的功能,進(jìn)行寫操作的時(shí)候,先記錄下要寫入的首地址,然后將接收到的數(shù)據(jù)都緩存在RAM中,在接收到STOP信號(hào)時(shí)再把緩存數(shù)據(jù)一次性保存到先前記錄的地址處。
有兩個(gè)需要注意的問(wèn)題:(a)、如果寫入的數(shù)據(jù)超過(guò)一頁(yè)的長(zhǎng)度,將發(fā)生回卷,即從RAM的0地址處進(jìn)行數(shù)據(jù)覆蓋。(b)、如果頁(yè)大小為128字節(jié),即0-127字節(jié)為第一頁(yè)、128-255為第二頁(yè),即頁(yè)的邊界位置是絕對(duì)的,而不是從寫入數(shù)據(jù)的起始位置開始計(jì)算。
在進(jìn)行數(shù)據(jù)讀取操作沒(méi)有頁(yè)的問(wèn)題,可以從任意位置開始讀取任意大小的數(shù)據(jù),超過(guò)EEPROM總?cè)萘繒r(shí)發(fā)生回卷。
電子發(fā)燒友App





































評(píng)論