看了一些書,沒能完全理解。不理解就只能照抄別人的東西,這個沒意思。于是,拋開所有的書,站在設(shè)計者的角度,來自己設(shè)計一下。(個人見解啊) 首先,不是說什么I2C總線,而是先確定是由兩條線來實現(xiàn)兩個器件之間的通訊。 第二,因為兩個器件都要有對數(shù)據(jù)的處理,因此兩個器件都會有微處理器也即你必須將主從器件都當(dāng)作微處理器來對待,所以,在設(shè)計時,必須對兩個器件的端口要一同考慮,對各器件的內(nèi)部也要考慮處理程序,而不是象現(xiàn)在的教科書上對主器件說得多,而對從器件說得太少。 第三,根據(jù)第二條,我們在設(shè)計時必須同時考慮到主從器件四個端口的工作,包括時序圖中也應(yīng)該有四個端口的狀態(tài),而不應(yīng)該在時序圖中只考慮線上狀態(tài)。 第四,就是確定一次傳輸一字節(jié),而且做到雙向傳輸。 以上是在設(shè)計總線時的幾個原則,都很重要。其中第二條,關(guān)系到總線標(biāo)準(zhǔn)或者說是規(guī)格問題,不同的處理方式,就會產(chǎn)生不同的標(biāo)準(zhǔn),進(jìn)而關(guān)系到這個標(biāo)準(zhǔn)之下的所有的器件的設(shè)計及生產(chǎn)標(biāo)準(zhǔn)。 好了,依據(jù)以上,我們現(xiàn)在開始設(shè)計。 一、傳輸方式設(shè)計 設(shè)計的第一步,是先確定采用兩條線的方式,能否實現(xiàn)傳輸,以及傳輸?shù)姆绞揭簿褪菢?biāo)準(zhǔn)。這是這個總線的核心,就象發(fā)動機(jī)的核心機(jī)一樣,確定了這個核心之后,才能在這個基礎(chǔ)上完成其它的要求,比如尋址、區(qū)分?jǐn)?shù)據(jù)與命令。另外,可以實現(xiàn)通訊的傳輸方式可能有多種,你要根據(jù)后續(xù)功能需要來確定最優(yōu)方式。 傳輸設(shè)計的第一步,是對器件的初始值的確定。其它的初始值這里不考慮,只考慮四個端口的工作方式。我們知道有四種方式,我們可以采取窮舉法,這里先設(shè)定四個端口均設(shè)置為準(zhǔn)雙向方式,這個方式下,每條傳輸線上的值就是兩個端口輸出值的“與”,即兩個端口同時輸出高電平,線上才是高電平,這個很重要,我們知道器件要檢測傳輸線的電平狀態(tài)變化的。 我們再確定兩條線的工作分工,這個分工,我們在以下的設(shè)計中確定。 啟動信號 然后器件開始工作,第一步當(dāng)然是主器件要告訴從器件:我準(zhǔn)備要向你傳輸了。那就發(fā)一個信號吧?我們先看看發(fā)一個從低到高的電平,對方能不能感覺到變化:如果對方輸出的是高,那么線上就會從低電平變化為高電平,這個就有變化,能行;如果對方輸出的是低電平,那線上依然是低電平,這個就行不通了。這就確定了一個可行方案:確定兩條線中的一條線來做傳輸啟動信號,初始設(shè)置主器件端為低電平,從器件端為高電平。當(dāng)然,這個不是I2C的標(biāo)準(zhǔn)。我們在后面的設(shè)計中可以理解為什么I2C不采用這個方案。 我們再來看看I2C的方案即第二個方案,確定由一條線做啟動,兩端口初始設(shè)置均為高電平,主器件發(fā)低電平,線上則變?yōu)榈碗娖剑瑥钠骷蜋z測到了變化。 前面說過,主從器件均作為微處理器看待,從器件在設(shè)計中,在待機(jī)時,一是要將此端口設(shè)為高電平,二是要不斷檢測這個端口的狀態(tài),一旦檢測到了變化,則立即轉(zhuǎn)入接收狀態(tài)。 這里有個問題,按說另一條線即數(shù)據(jù)線的狀態(tài)對這個啟動是沒有影響的,它兩端的電平是不需要初始化的,但我看現(xiàn)在的程序中都進(jìn)行了初始化,有必要么?還有現(xiàn)在的程序中開頭就進(jìn)行了時鐘線的兩端拉高然后再拉低,這個已經(jīng)在初始化時拉高過,以及每一次傳輸完成后都進(jìn)行了拉高,有必要再拉高一次么?有興趣的可以實驗驗證一下,如果真是這樣,那程序就可以減減肥了,這也是我們在做程序應(yīng)用時,從設(shè)計角度充分理解其原理的原因。 這里思考一下:從機(jī)檢測到也就是接收到信號并完成接收準(zhǔn)備工作后,要不要對主器件做一個應(yīng)答說我準(zhǔn)備好了?有沒有必要?I2C是沒有的,這個在I2C里面是對的,但如果做其它的總線設(shè)計,則是必須考慮到的。 傳輸字節(jié) 首先確定是一次傳輸一個字節(jié)即八位,這個沒說的。然后是先高位后低還是先低后高的確定,這個理論上都可以,你自己定就是了。I2C選擇的是從高到低。如果你選擇先低后高,那就不是I2C總線標(biāo)準(zhǔn)了,你自己得另外起個名字。 然后確定用哪條線來傳,這個先確定采用另一條線來專門傳送字節(jié),給這條線起個名字“數(shù)據(jù)線”。 先傳送第一位,將其值放在數(shù)據(jù)線上,并告訴從器件可以讀數(shù)據(jù)了,然后從器件讀,放一位就告訴一次并讓對方讀一次,這個“告訴”的工作,就分給那條“啟動”線了,這個時候我們可以給這條線起個名字叫“時鐘線”。怎么讀?什么時候讀?這個就要考慮在發(fā)送數(shù)據(jù)之前的四個端口的電平初始值設(shè)計了。首先數(shù)據(jù)線接收端口必須輸出高電平,這樣發(fā)送端的變化才能直接影響數(shù)據(jù)線電平的高低。 然后就是時鐘線兩端的初始電平設(shè)計。因為從器件要跟著主器件的端口電平變化來區(qū)分位數(shù)變化,故其端口應(yīng)輸出為高。主器件理論上在這一步設(shè)為高或低是都可以的,考慮到后面的其它工作,I2C確定的是低電平。這里從器件還要做的一件事是不斷檢測時鐘線電平。 初始設(shè)置完成了,根據(jù)前面的分析,數(shù)據(jù)第一位在時鐘線低時放在數(shù)據(jù)線上,穩(wěn)定后(這就是延時的來由)主器件拉起時鐘線電平以告訴從器件可以讀第一位數(shù)據(jù)了。從器件在一定時間內(nèi)讀取,主器件認(rèn)為在這個時間內(nèi)已經(jīng)讀取了數(shù)據(jù)線上的電平,然后拉低電平,穩(wěn)定后在數(shù)據(jù)線上放上第二位,再重復(fù)至所有八位傳輸完成。 應(yīng)答 從器件收完八位數(shù),主器件就停下,需要確認(rèn)從器件是否收到了這一字節(jié)數(shù)據(jù),那么從器件就要給個答復(fù)。這個信號必須由從器件發(fā)出。再次強(qiáng)調(diào)在理解這個總線的原理時必須同時考慮從器件。 我們知道在主器件發(fā)送數(shù)據(jù)時,從器件的兩個端口輸出的都是高電平,那么理論上,我們可以讓任一條線上從器件的端口輸出低電平來告訴主器件,這時只需要主器件對應(yīng)端口輸出高電平就行了,然后主器件對此線的電平進(jìn)行檢測,如果是低電平,則判斷收到了從器件的應(yīng)答信號,否則主器件就認(rèn)為從器件沒能完成這段字節(jié)的接收(這個情況主器件就要另外處理了)。 I2C是選擇的哪種方式?自己查。 傳輸結(jié)束 這個是主器件的事,它說傳完了,得告訴從器件,也就是說,這個信號,得主器件來發(fā)出。 既然是主器件發(fā)信號,那從器件的接收端必須設(shè)置為高電平輸出。但這時,從器件也有了一個條件,知道主器件已經(jīng)發(fā)完一段數(shù)據(jù)了,有可能會發(fā)終止信號,也有可能繼續(xù)發(fā)送數(shù)據(jù)(這種總線設(shè)計方案,有沒有繼續(xù)發(fā)送數(shù)據(jù)的可能,需要在后面的設(shè)計中從理論上論證)。在接收終止信號這點上,從器件與啟動時的準(zhǔn)備是有區(qū)別的。這種條件上的區(qū)別,在總線設(shè)計時是必須考慮到的。 做不同的事,就要有不同的信號或者說是對不同狀態(tài)的判斷。前面已經(jīng)用了幾種了,我們得找一種與前不同的狀態(tài)。前面放數(shù)據(jù)位時,是主器件讓時鐘線在低位;應(yīng)答時,數(shù)據(jù)線是從器件讓其在低位。那么,我們在終止時,主從器件讓時鐘線在高位,主器件讓數(shù)據(jù)線在低位(這個時候,從器件端口輸出高與低,有沒有關(guān)系,可以再思考一下),是不是跟其它情況有區(qū)別?當(dāng)然有了,就用它了。 以上,完成了主器件向從器件的數(shù)據(jù)傳輸,包括啟動、字節(jié)傳輸、從器件的應(yīng)答、主器件決定傳輸結(jié)束。到此為止,可以說,核心機(jī)已經(jīng)完成了。
從器件使能; 命令與數(shù)據(jù)的區(qū)分; 從器件數(shù)據(jù)讀出; 從器件的數(shù)據(jù)存放及讀出的數(shù)據(jù)地址; 數(shù)據(jù)連續(xù)傳輸?shù)目赡埽?/font> 多從器件的可能及尋址; 多主器件的可能及競爭; 其它。 以上完成后,就是細(xì)節(jié)的制定,也是標(biāo)準(zhǔn)的內(nèi)容之一了。在論證的過程中,如果有任意一項達(dá)不到,就要考慮從頭設(shè)計了,甚至考慮兩線方式是否合適(注意第7項其它)。當(dāng)然,如果某一功能不能實現(xiàn),也不能說這個總線標(biāo)準(zhǔn)就是廢物,要看你用在哪。 以上所有完成之后,才成為一種總線標(biāo)準(zhǔn)。
其它說明 兩線方式有很多種,I2C的方式,屬非固定波率方式,也就是說節(jié)拍沒有固定時間間隔,甚至節(jié)拍沒說要固定一致,就是說你一會快一會慢也是可以滿足要求的。這點,對我們后面的驗證及實踐很重要。 時序圖中一定要有四端口的時序圖,然后才是四端口的時序“與”之后的線上時序圖,不然理解起來真的困難,反正我是被現(xiàn)在的時序圖弄暈了。 四、驗證方法 對I2C驗證的最好方法,當(dāng)然是用兩片單片機(jī)來實現(xiàn),這種方法,你可以徹底了解這個總線。 第二種簡易方法,不用邏輯分析儀而是很直觀地用LED,就是自己搭建電路,將時鐘線(注意是時鐘線上電平,下數(shù)據(jù)線同)的狀態(tài)送到另外的端口接一個LED,數(shù)據(jù)線的狀態(tài)送到另外八個端口接LED,你可以延時設(shè)定每過2秒送一位數(shù)據(jù),這樣你連從器件的應(yīng)答都可以同步觀測到了,結(jié)束也可以觀測到了,起始狀況、數(shù)據(jù)傳輸各位是否正確等等,可以立即發(fā)現(xiàn)你的程序的問題,比邏輯分析儀還直觀迅速。這種方式,也可以延伸到固定波特率傳輸,當(dāng)然不能照抄。 PS1:實現(xiàn)一種功能,辦法是很多的,“標(biāo)準(zhǔn)”只是辦法之中的一種,它不能在你心中成為對你的約束,否則就是對人類智能的侮辱。 PS2:學(xué)習(xí)別人的方法,才是人才的做法,不然就是機(jī)器。 PS3:實在不想寫了,交差。 PS4:信了你的邪,這就三千多字了?我已經(jīng)在偷懶啊,破底線了!!! PS5:有興趣將后面論證的東西補(bǔ)充一下,就是一篇不錯的論文。
|