模擬I2C總線(xiàn)多主通信研究與軟件設計
摘要 介紹模擬I2C總線(xiàn)的多主節點(diǎn)通信原理,并提出一種新的實(shí)現方法。這種采用延時(shí)接收比較來(lái)實(shí)現仲裁的方法,可使不具有I2C接口的普通微控制器(MCU)能夠實(shí)現模擬I2C總線(xiàn)的多主通信,同時(shí)對I2C總線(xiàn)的推廣起到了積極作用。
關(guān)鍵詞 模擬I2C總線(xiàn) 仲裁 多主通信
I2C總線(xiàn)(Inter IC BUS)是Philips公司推出的雙向兩線(xiàn)串行通信標準。由于它具有接口少、通信效率高等優(yōu)點(diǎn),現已得到廣泛的應用[1~3]。它除了可以進(jìn)行簡(jiǎn)單的單主節點(diǎn)通信外,還可以應用在多主節點(diǎn)的通信系統中。在多主節點(diǎn)通信系統中,如果兩個(gè)或者更多的主節點(diǎn)同時(shí)啟動(dòng)數據傳輸,總線(xiàn)具有沖突檢測和仲裁功能,保證通信正常進(jìn)行并防止數據破壞?,F在許多微控制器(MCU)都具有I2C總線(xiàn)接口,能方便地進(jìn)行I2C總線(xiàn)設計。對于沒(méi)有I2C總線(xiàn)接口的MCU,可以采用兩條I/O接口線(xiàn)進(jìn)行模擬[2,3]。目前,一些介紹模擬I2C的資料主要講的是在單主節點(diǎn)系統中進(jìn)行的通信,這使得模擬I2C總線(xiàn)的應用具有一定的局限性。本文根據總線(xiàn)仲裁的思想,提出一種多主節點(diǎn)通信的思想及實(shí)現流程。
1 I2C總線(xiàn)系統簡(jiǎn)介[1~3]
I2C總線(xiàn)系統是由SCL(串行時(shí)鐘)和SDA(串行數據)兩根總線(xiàn)構成的。該總線(xiàn)有嚴格的時(shí)序要求,總線(xiàn)工作時(shí),由串行時(shí)鐘線(xiàn)SCL傳送時(shí)鐘脈沖,由串行數據線(xiàn)SDA傳送數據??偩€(xiàn)協(xié)議規定,各主節點(diǎn)進(jìn)行通信時(shí)都要有起始、結束、發(fā)送數據和應答信號。這些信號都是通信過(guò)程中的基本單元??偩€(xiàn)傳送的每1幀數據均是1個(gè)字節,每當發(fā)送完1個(gè)字節后,接收節點(diǎn)就相應給一應答信號。協(xié)議規定,在啟動(dòng)總線(xiàn)后的第1個(gè)字節的高7位是對從節點(diǎn)的尋址地址,第8位為方向位(“0”表示主節點(diǎn)對從節點(diǎn)的寫(xiě)操作;“1”表示主節點(diǎn)對從節點(diǎn)的讀操作),其余的字節為操作數據。圖1列出I2C總線(xiàn)上幾個(gè)基本信號的時(shí)序。
圖1中包括起始信號、停止信號、應答信號、非應答信號以及傳輸數據“0”和數據“1”的時(shí)序。起始信號就是在SCL線(xiàn)為高時(shí)SDA線(xiàn)從高變化到低;停止信號就是在SCL線(xiàn)為高時(shí)SDA線(xiàn)從低變化到高;應答信號是在SCL為高時(shí)SDA為低;非應答信號相反,是在SCL為高時(shí)SDA為高。傳輸數據“0”和數據“1”與發(fā)送應答位和非應答位時(shí)序圖是相同的。
圖1 I2C總線(xiàn)上基本信號的時(shí)序
圖2表示了一個(gè)完整的數據傳送過(guò)程。在I2C總線(xiàn)發(fā)送起始信號后,發(fā)送從機的7位尋址地址和1位表示這次操作性質(zhì)的讀寫(xiě)位,在有應答信號后開(kāi)始傳送數據,直到發(fā)送停止信號。數據是以字節為單位的。發(fā)送節點(diǎn)每發(fā)送1個(gè)字節就要檢測SDA線(xiàn)上有沒(méi)有收到應答信號,有則繼續發(fā)送,否則將停止發(fā)送數據。
圖2 一次完整的數據傳送過(guò)程
2 I2C總線(xiàn)的仲裁
在多主的通信系統中??偩€(xiàn)上有多個(gè)節點(diǎn),它們都有自己的尋址地址,可以作為從節點(diǎn)被別的節點(diǎn)訪(fǎng)問(wèn),同時(shí)它們都可以作為主節點(diǎn)向其他的節點(diǎn)發(fā)送控制字節和傳送數據。但是如果有兩個(gè)或兩個(gè)以上的節點(diǎn)都向總線(xiàn)上發(fā)送啟動(dòng)信號并開(kāi)始傳送數據,這樣就形成了沖突。要解決這種沖突,就要進(jìn)行仲裁的判決,這就是I2C總線(xiàn)上的仲裁。
I2C總線(xiàn)上的仲裁分兩部分:SCL線(xiàn)的同步和SDA線(xiàn)的仲裁。SCL同步是由于總線(xiàn)具有線(xiàn)“與”的邏輯功能,即只要有一個(gè)節點(diǎn)發(fā)送低電平時(shí),總線(xiàn)上就表現為低電平。當所有的節點(diǎn)都發(fā)送高電平時(shí),總線(xiàn)才能表現為高電平。正是由于線(xiàn)“與”邏輯功能的原理,當多個(gè)節點(diǎn)同時(shí)發(fā)送時(shí)鐘信號時(shí),在總線(xiàn)上表現的是統一的時(shí)鐘信號。這就是SCL的同步原理。
SDA線(xiàn)的仲裁也是建立在總線(xiàn)具有線(xiàn)“與”邏輯功能的原理上的。節點(diǎn)在發(fā)送1位數據后,比較總線(xiàn)上所呈現的數據與自己發(fā)送的是否一致。是,繼續發(fā)送;否則,退出競爭。圖3中給出了兩個(gè)節點(diǎn)在總線(xiàn)上的仲裁過(guò)程。SDA線(xiàn)的仲裁可以保證I2C總線(xiàn)系統在多個(gè)主節點(diǎn)同時(shí)企圖控制總線(xiàn)時(shí)通信正常進(jìn)行并且數據不丟失??偩€(xiàn)系統通過(guò)仲裁只允許一個(gè)主節點(diǎn)可以繼續占據總線(xiàn)[1]。
圖3是以?xún)蓚€(gè)節點(diǎn)為例的仲裁過(guò)程。DATA1和DATA2分別是主節點(diǎn)向總線(xiàn)所發(fā)送的數據信號,SDA為總線(xiàn)上所呈現的數據信號,SCL是總線(xiàn)上所呈現的時(shí)鐘信號。當主節點(diǎn)1、2同時(shí)發(fā)送起始信號時(shí),兩個(gè)主節點(diǎn)都發(fā)送了高電平信號。這時(shí)總線(xiàn)上呈現的信號為高電平,兩個(gè)主節點(diǎn)都檢測到總線(xiàn)上的信號與自己發(fā)送的信號相同,繼續發(fā)送數據。第2個(gè)時(shí)鐘周期,2個(gè)主節點(diǎn)都發(fā)送低電平信號,在總線(xiàn)上呈現的信號為低電平,仍繼續發(fā)送數據。在第3個(gè)時(shí)鐘周期,主節點(diǎn)1發(fā)送高電平信號,而主節點(diǎn)2發(fā)送低電平信號。根據總線(xiàn)的線(xiàn)“與”的邏輯功能,總線(xiàn)上的信號為低電平,這時(shí)主節點(diǎn)1檢測到總線(xiàn)上的數據和自己所發(fā)送的數據不一樣,就斷開(kāi)數據的輸出級,轉為從機接收狀態(tài)。這樣主節點(diǎn)2就贏(yíng)得了總線(xiàn),而且數據沒(méi)有丟失,即總線(xiàn)的數據與主節點(diǎn)2所發(fā)送的數據一樣,而主節點(diǎn)1在轉為從節點(diǎn)后繼續接收數據,同樣也沒(méi)有丟掉SDA線(xiàn)上的數據。因此在仲裁過(guò)程中數據沒(méi)有丟失。
圖3 兩個(gè)主節點(diǎn)的仲裁過(guò)程
3 多主通信的原理及其實(shí)現流程
多主通信就是在總線(xiàn)上有多個(gè)節點(diǎn)。這些節點(diǎn)既可以作為主節點(diǎn)訪(fǎng)問(wèn)其他的節點(diǎn),也可以作為從節點(diǎn)被其他節點(diǎn)訪(fǎng)問(wèn)。當有多個(gè)節點(diǎn)同時(shí)企圖占用總線(xiàn)時(shí),就需要總線(xiàn)的仲裁。對于模擬I2C總線(xiàn)系統,怎樣實(shí)現總線(xiàn)的仲裁是現在研究模擬I2C總線(xiàn)系統的難點(diǎn)。文獻[4]提出在系統中增加1根BUSY線(xiàn),在占用總線(xiàn)之前先檢測BUSY線(xiàn),看總線(xiàn)是否被占用。若總線(xiàn)空閑,則設置BUSY線(xiàn)并向總線(xiàn)上傳送數據;否則,接收數據,直到總線(xiàn)空閑時(shí)才占有總線(xiàn)。這種實(shí)現多主通信的方法有兩個(gè)缺點(diǎn):① 因為I2C最大的優(yōu)點(diǎn)就是接口少、效率高,這樣做不僅增加了使用資源而且減少了I2C總線(xiàn)的優(yōu)勢;② 當主節點(diǎn)數比較多時(shí),等待時(shí)間比較長(cháng),效率不高。本設計根據總線(xiàn)的仲裁原理,提出一種基于延時(shí)比較的仲裁方法。當主節點(diǎn)想要占用總線(xiàn)時(shí),先檢測總線(xiàn)上是否空閑,如果總線(xiàn)是空閑的就發(fā)送數據。在發(fā)送數據的同時(shí),將總線(xiàn)上的數據接收并與發(fā)送的數據進(jìn)行比較。如果不同,說(shuō)明總線(xiàn)上同時(shí)還存在其他節點(diǎn),于是就退出;否則,一直到發(fā)送完數據。這種方法既體現了I2C總線(xiàn)的高效性,同時(shí)還具有良好的擴展性。
圖4 多主通信流程
圖4給出了基于延時(shí)比較的多主通信流程,其中MCU作為從節點(diǎn)部分的流程在圖5中給出。在節點(diǎn)發(fā)送起始信號之前先要檢測一下總線(xiàn)上是否為空閑狀態(tài)(BUSY是否為0)。這里使用的檢測方法是,持續檢測一段時(shí)間看總線(xiàn)上的電平是否一直為高,若是說(shuō)明總線(xiàn)上為閑狀態(tài),否則說(shuō)明有其他的節點(diǎn)正在使用總線(xiàn),要等一段時(shí)間再發(fā)送。當總線(xiàn)空閑時(shí),發(fā)送起始信號,接著(zhù)發(fā)送要訪(fǎng)問(wèn)的從節點(diǎn)的地址字節。每發(fā)送1位數據就接收比較1次,看發(fā)送和接收的是否一致,若是則繼續,否則跳出到從節點(diǎn)的接收狀態(tài)。如果沒(méi)有產(chǎn)生沖突,MCU作為主節點(diǎn)繼續發(fā)送數據,直到任務(wù)結束,然后發(fā)送停止信號并返回。如果數據不一樣,MCU將跳轉到從節點(diǎn)狀態(tài)。由于在跳轉到從節點(diǎn)接收狀態(tài)的過(guò)程中累加器(ACC)和工作寄存器(Ri)的數據沒(méi)有發(fā)生變化,所以數據沒(méi)有丟失,作為從節點(diǎn)可以繼續接收總線(xiàn)上的數據。這樣整個(gè)通信的過(guò)程沒(méi)有中斷,數據也沒(méi)有丟失。
圖5 從節點(diǎn)部分的流程
圖5給出了從節點(diǎn)的流程。進(jìn)入從節點(diǎn)時(shí),要將BUSY置為高,說(shuō)明MCU現在正在工作,不能完成其他的任務(wù)。在MCU作為從節點(diǎn)完成接收任務(wù)后,要將BUSY置為低。MCU在接收到尋址字節后與自己的地址字節進(jìn)行比較。如果是訪(fǎng)問(wèn)自己的就進(jìn)入到下面的接收程序,否則跳出。在訪(fǎng)問(wèn)自己的時(shí)候,還要判斷主節點(diǎn)是讀取數據還是寫(xiě)數據,以便進(jìn)入相應的程序。在寫(xiě)字節的子程序中,從節點(diǎn)每發(fā)送1個(gè)字節的數據后都要察看是否有應答信號(ACK),有則說(shuō)明數據接收到了;否則要跳出等待,重新發(fā)送。在讀字節的子程序中,每接收1個(gè)字節的數據就要發(fā)送1個(gè)應答信號(ACK),以示接收正常,否則主節點(diǎn)將停止繼續發(fā)送。在現有的資料中,關(guān)于從節點(diǎn)的原理和源代碼比較少,這里給出作為從節點(diǎn)時(shí)寫(xiě)字節子程序的源代碼。由于篇幅有限其他的子程序沒(méi)有列出。
4 部分源代碼
本節是在MCU多主通信中的部分源代碼。多主通信的實(shí)現中有幾個(gè)難點(diǎn)和重點(diǎn)。一是在作為主節點(diǎn)時(shí)的寫(xiě)字節子程序,里面要包括發(fā)送的每位數據和總線(xiàn)的數據進(jìn)行比較并做出判斷。如果數據不同,要跳出并進(jìn)入從節點(diǎn)的狀態(tài)。由于子程序返回主程序時(shí)改變的只是PC的值而累加器(ACC)和工作寄存器(Ri)里面的值是不變的,因此MCU進(jìn)入從機狀態(tài)后繼續接收總線(xiàn)剩下的數據,這樣總線(xiàn)的數據并沒(méi)有丟失。二是作為從節點(diǎn)時(shí)的寫(xiě)字節的子程序。由于時(shí)鐘線(xiàn)是由主節點(diǎn)的MCU控制的,所以怎樣根據SCL線(xiàn)來(lái)讀取SDA線(xiàn)的數據是其中的一個(gè)難點(diǎn)。三是在具有子地址的從節點(diǎn)關(guān)于是寫(xiě)字節還是讀字節時(shí)的判斷。如果是寫(xiě)字節時(shí)主節點(diǎn)會(huì )給出新的起始信號,并再次發(fā)送從節點(diǎn)的地址數據。這時(shí)從節點(diǎn)需要做出判斷是讀取數據還是寫(xiě)數據,并進(jìn)入相應的子程序。這里給出以上三個(gè)重點(diǎn)和難點(diǎn)的子程序的源代碼,以供讀者參考。這些源代碼經(jīng)實(shí)踐證明都是正確的。
主節點(diǎn)的寫(xiě)字節子程序:
;其中的NOP可根據時(shí)鐘的快慢自己加減
WRBYTE:MOV R0,#08H
CLR BUSY;將BUSY值清零
WLP: RLC A;取數據位
JC WR1
SJMP WR0;判斷數據位
WLP1: DJNZ R0,WLP
NOP
OUT1: RET
WR1: SETB SDA;發(fā)送1
NOP
SETB SCL
MOV C,SDA;判斷是否與發(fā)送的數據相同
JC GOON
SETB BUSY
AJMP OUT1
GOON: NOP
NOP
NOP
CLR SCL
SJMP WLP1
WR0: CLR SDA;發(fā)送0
NOP
SCL
NOP
NOP
NOP
NOP
NOP
CLR
SCL
SJMP WLP1
從節點(diǎn)的寫(xiě)字節子程序(返回為ACK):
SWRBYTE:MOV R0,#08H
WAGAIN: RRC A
MOV B,#37H
WWAIT1: JB SCL,WWAIT1;等待SCL為低
JC WR1;判斷是發(fā)送“1”還是發(fā)送“0”
SETB SDA;發(fā)送“1”
AJMP COM
WR1: CLR SDA;發(fā)送“0”
COM: DJNZ R0,WWAIT2;判斷是否發(fā)送完畢
WWAIT3: JNB SCL,WWAIT3;發(fā)送完畢等待應答信號
WWAIT4: JB SCL,WWAIT4
WWAIT5: JNB SCL,WWAIT5
CLR ACK
JB SDA,ST0
SETB ACK
ST0: RET;返回
WWAIT2: JNB SCL,WWAIT2;等待SCL為高
SJMP WAGAIN
從節點(diǎn)的讀字節同時(shí)判斷是否有起始信號的子程序。如果有起始信號,則轉為寫(xiě)字節子程序:
SRDBYTE:MOV R0,#08H
SETB 20H;設置標志位判斷是讀還是寫(xiě)
SETB SDA;釋放總線(xiàn)
RWAITJ: JNB SCL,RWAITJ;等待SCL為高
MOV C,SDA;從總線(xiàn)上讀取數據
RRC A;存入累計器
DEC R0
MOV C,ACC.7;判斷是否為起始信號
JNC RWAITJ1;為低繼續讀取數據
REWAIT: JNB SCL,RWAITJ1;開(kāi)始判斷是否為起始信號
JB SDA,REWAIT
CLR 20H;是,則清標志位并返回
AJMP SjRDOUT
RWAITJ1:JB SCL,RWAITJ1;等待SCL為低
RWAITJ3:JNB SCL,RWAITJ3;等待SCL為高
MOV C,SDA
RRC A
DJNZ R0,RWAITJ2
SjRDOUT:RET
RWAITJ2:JB SCL,RWAITJ2;等待SCL為低繼續讀數據
SJMP RWAITJ3
5 總結
根據總線(xiàn)協(xié)議中的仲裁原理,提出的基于延時(shí)比較的模擬I2C多主通信的方法,不僅能夠體現了I2C總線(xiàn)的高效性,而且還具有良好的擴展性。它使普通不具有I2C接口的MCU可以應用在多主通信的系統中,既增加了普通MCU的使用范圍,又突破了模擬I2C總線(xiàn)的應用局限性,為I2C總線(xiàn)的推廣起到了積極的作用。
參考文獻
1 The I2CBus Specification, Version 2.1. January, 2000. http://www.philips.com/
2 張昆,邱揚,劉浩. 基于CPLD的系統中I2C總線(xiàn)的設計. 電子技術(shù)應用,2003(11)
3 何立民. I2C總線(xiàn)應用系統設計. 北京:北京航空航天大學(xué)出版社,1995
4 張冬梅,藩仕彬,何為民. 模擬I2C總線(xiàn)多主通信的通用軟件包. 單片機與嵌入式系統應用, 2003(12)
評論