電話(huà):
400-0780-677傳真:
025-86644313
做嵌入式系統開(kāi)發(fā),經(jīng)常要接觸硬件。做嵌入式開(kāi)發(fā)對數字電路和模擬電路要有一定的了解。這樣才能深入的研究下去。下面我們簡(jiǎn)單的介紹嵌入式開(kāi)發(fā)中的一些硬件相關(guān)的概念。
總線(xiàn)(Bus)
在嵌入式系統中一定會(huì )有一塊處理器芯片,此外,還有其它的芯片作為外部設備(后面簡(jiǎn)稱(chēng)外設),這些芯片與處理器協(xié)作實(shí)現產(chǎn)品的功能。復雜的產(chǎn)品往往是由大量的芯片組成的。那么不可避免的是我們需要將所有的外設與處理器進(jìn)行相連,為簡(jiǎn)單的是將所有的外設都采用獨立(注意是獨立)的信號線(xiàn)連接至處理器,這樣的好處是容易理解,但問(wèn)題是:不可行。
因為處理器芯片需要引出太多的線(xiàn)了,從芯片的生產(chǎn)和產(chǎn)品的生產(chǎn)角度來(lái)看都不實(shí)際。加之,處理器(在此我們假設處理器是單核的,而不是多核的)處理事務(wù)在微觀(guān)上是串行的,也就是說(shuō)在某一時(shí)刻如果要對外設進(jìn)行讀寫(xiě)操作,那只可能是對大量外設中的一個(gè)進(jìn)行,即多個(gè)外設不可能在微觀(guān)上被處理器同時(shí)訪(fǎng)問(wèn)。
需要注意的是,這里提出了微觀(guān)這一概念,這是為了區別于宏觀(guān)。從宏觀(guān)上來(lái)講,一個(gè)處理器中可以有多個(gè)任務(wù)同時(shí)運行,但這些任務(wù)在微觀(guān)上卻是一個(gè)一個(gè)運行的(后面會(huì )用串行來(lái)描述這里所說(shuō)的“一個(gè)一個(gè)”),多任務(wù)的串行運行實(shí)現是由操作系統扮演著(zhù)重要的角色來(lái)實(shí)現的。
回到我們的話(huà)題,即然將每個(gè)外設采用獨立的信號線(xiàn)連到處理器不可行,且處理器在單一時(shí)間內只會(huì )對一個(gè)外設進(jìn)行訪(fǎng)問(wèn),那我們能不能采用共享的信號線(xiàn)將所有的芯片連在一起呢?這就是總線(xiàn)概念的由來(lái)。通俗的說(shuō),如果我們周?chē)惺畟€(gè)家庭,為了讓這十個(gè)家庭每?jì)蓚€(gè)之間都能往來(lái),我們并不需要為每?jì)蓚€(gè)家庭修一條單獨(注意是單獨)的路(如果這樣,要修45條路),而是可以修一條大路,然后,每個(gè)家都與大路相連。
對于總線(xiàn),我們往往說(shuō)總線(xiàn)是處理器的,而其它的外設是掛在總線(xiàn)上的。那有一個(gè)問(wèn)題,我們每一時(shí)間只能訪(fǎng)問(wèn)掛在總線(xiàn)上的一個(gè)外設,那如何區分這些外設呢?和我們的路一樣,我們需要用地址來(lái)區分每一個(gè)家庭,在總線(xiàn)上,也是采用地址來(lái)進(jìn)行區分的。
這樣,總線(xiàn)就根據其功能分為兩類(lèi)了。一類(lèi)是地址總線(xiàn),這一總線(xiàn)上的數據只會(huì )是從處理器向外設“流”,是單向的。另一類(lèi)則是數據總線(xiàn),用來(lái)將數據從處理器傳送到外設(從處理器的角度來(lái)說(shuō)是寫(xiě)操作)或者是將數據從外設傳送到處理器(從處理器的角度來(lái)說(shuō)是讀操作),顯然,數據總線(xiàn)是雙向的。也就是說(shuō),在我們的嵌入式系統中同時(shí)存在地址總線(xiàn)和數據總線(xiàn)將所有需要與處理器進(jìn)行通訊的芯片連在一起的。
總線(xiàn)是有寬度的,正如我們的路分為“三車(chē)道”或是“四車(chē)道”,我們說(shuō)32位處理器,是指其數據總線(xiàn)寬度是32位,也就是“有32輛車(chē)能同時(shí)跑”,顯然,寬度越是寬我們的處理器速度就越是快,因為我們從外設芯片存取數據的速度會(huì )更快,這就是為什么我們的計算機向64位發(fā)展的原因。同樣的,地址總線(xiàn)也是有寬度的,對于32位處理器其大寬度也就是32位。
總線(xiàn)的概念有了,那接下來(lái)的一個(gè)問(wèn)題是,即使是每一個(gè)外設都有一個(gè)地址,那這一地址記在哪里呢?是放在外設芯片上嗎?如果這樣的話(huà),那就有一個(gè)問(wèn)題,每一類(lèi)外設的地址必須是不能重疊的,而當一個(gè)產(chǎn)品中需要兩塊一樣的芯片的話(huà),兩塊芯片的地址就無(wú)法區分了,看來(lái)這樣操作存在問(wèn)題。還有,如果這樣的話(huà)每一個(gè)外設也得與(比如,32根)數據總線(xiàn)*相連,并監聽(tīng)數據線(xiàn)以了解處理器是不是在“叫”自己,這樣很是復雜。
此外,地址也有可能因為外設種類(lèi)的增多而用光。總的來(lái)說(shuō)地址不能存放在外設芯片,那如何讓外設知道,此時(shí)它是被處理器招換從而需要進(jìn)行讀寫(xiě)訪(fǎng)問(wèn)的呢?答案就是芯片的片選(CS,chip select)信號,或者又號使能(ENable)信號。
片選(CS或EN)
片選信號對于外設芯片來(lái)講,就是一個(gè)(也是一根)通知信號,告訴芯片“嘿,請開(kāi)門(mén),我要放些東西進(jìn)來(lái),或是拿些東西走”,這里的東西只能是數據,不可能是玉米棒什么的。那有個(gè)問(wèn)題,這個(gè)信號源從哪里來(lái)呢?顯然,只能從處理器來(lái)。那是不是也是像總線(xiàn)那樣,每一個(gè)芯片都共用一根線(xiàn)連在一起呢?
如果這樣,可能處理器“一叫開(kāi)門(mén)”所有的芯片都將“門(mén)”打開(kāi)了。如果是處理器寫(xiě)數據,那可能所有的芯片都被寫(xiě)入同樣的數據。而取數據時(shí),每個(gè)外設芯片都向外“扔”數據,這一定會(huì )造成數據總線(xiàn)沖突,因為有的芯片向總線(xiàn)上“扔”1,有的則“扔”0,這種情況下處理器一定會(huì )“發(fā)瘋”的,因為它不知道應當得到1還是0。
即然這樣,那顯然不能將所有的片選信號連在一起了,只能是各芯片的片選信號獨立。前面提到了地址總線(xiàn),我們是采用一根地址線(xiàn)連一個(gè)外設芯片呢?還是采用其它的方法。如果采用一根地址線(xiàn)連一個(gè)外設芯片,那可能多只能掛接32個(gè)芯片了,這顯然不行。
其實(shí),在現實(shí)中,是采用32位的數字來(lái)表示一個(gè)外設芯片的地址的,比如1可以表示芯片A,而6534可以表示另外一個(gè)芯片B,等等。由此看來(lái),理論上我們可以表示2的32次方(4294967296)個(gè)設備,之所以說(shuō)理論上,是因為有的設備要占用大量的地址。即然這樣,那還有一個(gè)問(wèn)題,如果將32位的地址總線(xiàn)轉換成芯片的一根片選信號呢?這需要引入譯碼(器)的概念。
譯碼(器)
譯碼器將一個(gè)數據轉換成一根信號線(xiàn)上的信號,比如3/8譯碼器,可以將一個(gè)位寬是3位的數據轉換成8根(2的3次方)*獨立的信號線(xiàn),當向數據側寫(xiě)入二進(jìn)制的011時(shí),對應的是8根線(xiàn)的第3根,當輸入二進(jìn)制的111時(shí),對應的是8根線(xiàn)中的后一根。有了譯碼器,處理器的地址線(xiàn)就簡(jiǎn)化了,只要32根地址線(xiàn)加上外面的譯碼器,就可以訪(fǎng)問(wèn)大量的外設芯片了。外部設備的選擇問(wèn)題,我們已經(jīng)解決了,現在還得回頭看一看數據總線(xiàn)。
在嵌入式系統中,所有芯片的數據總線(xiàn)可以理解成是直接相連的。之所以用了“可以理解”一詞,是因為為了提高總線(xiàn)的負載能力,其中會(huì )加入總線(xiàn)驅動(dòng)器。為了理解,我們看一看我們生活中的自來(lái)水,比如,在北京理論上可能所有的水管是連在一起的,但中間可能為了提高水壓,存在很多小的水站用來(lái)增加供水壓力,而不可能全北京所有的自來(lái)水自接來(lái)自一個(gè)水廠(chǎng)。
即然所有的數據總線(xiàn)是連在一起的,那就可能會(huì )有問(wèn)題。當向外部設備寫(xiě)數據時(shí),處理器先向地址總線(xiàn)輸送目標外設的地址,地址譯碼器將其轉換成一根信號的片選信號送到了目標外設,目標外設收到這一信號后,將“門(mén)”打開(kāi)。接下來(lái)處理器將要傳送到外設的數據往數據總線(xiàn)上一放,由于只有目標外設芯片打開(kāi)了“門(mén)”,所以數據只會(huì )進(jìn)入到目標外設,而其它的外設什么也不會(huì )收到。很好!處理器向外寫(xiě)數據應當沒(méi)有問(wèn)題,我們接下來(lái)看一看讀。
讀的話(huà),由于數據是從外設輸送到處理器的,盡管我們采用和寫(xiě)一樣的方法打開(kāi)目標外設的“門(mén)”,但此時(shí),其它的外設也在數據總線(xiàn)上,它們有可能處于1也可能處于0,是不是會(huì )影響處理器讀取目標外設的數據呢?結果當然不會(huì ),但我們得引入另一個(gè)概念:高阻態(tài)。
高阻態(tài)
很顯然,當處理器從目標外設讀數據時(shí),我們希望其它沒(méi)有被選上的芯片的數據總線(xiàn)不會(huì )對目標外設所要傳送的數據有影響,那怎么辦呢?實(shí)際上,當芯片沒(méi)有被選中時(shí),其數據總線(xiàn)都處于高阻態(tài)。
所謂的高阻態(tài),我們可以理解成這一管腳在外設芯片內部是斷開(kāi)的,如此一來(lái),顯然不會(huì )對處理器從目標外設讀取數據造成任何的影響了。我們說(shuō)當一個(gè)芯片沒(méi)有被選中或是沒(méi)有被使能時(shí),其數據總線(xiàn)一定是處于高阻態(tài)的。前面用了“門(mén)”的開(kāi)和關(guān)來(lái)打比方,那“門(mén)”是指什么呢?是指外設的數據總線(xiàn),片選信號的作用就是控制將外設的數據總線(xiàn)與處理器的數據總線(xiàn)相連或是斷開(kāi)。
驅動(dòng)
總線(xiàn)上的數據是誰(shuí)放上去的我們就說(shuō)誰(shuí)是那一時(shí)刻的驅動(dòng)者。也就是說(shuō),當處理器向外設寫(xiě)數據時(shí),它是在驅動(dòng)數據總線(xiàn)的,而當處理器從目標外設讀取數據時(shí),目標外設是在驅動(dòng)數據總線(xiàn)的。對于地址總線(xiàn),因為只可能從處理器向目標外設寫(xiě),所以地址總線(xiàn)永遠是由處理器驅動(dòng)的。當一個(gè)芯片沒(méi)有被選中時(shí),我們說(shuō)它并不驅動(dòng)數據總線(xiàn)。
三態(tài)門(mén)
前面我們說(shuō)到外設芯片的數據總線(xiàn)在沒(méi)有被選中時(shí)其處于高阻態(tài),當被選中時(shí),其電平可能是高(1)或是低(0)。如此一來(lái),我們說(shuō)外設的數據總線(xiàn)其芯片管腳是屬于三態(tài)門(mén)的,即存在高電平、低電平和高阻態(tài),三個(gè)狀態(tài)。
電平的有效性
前面我們了解了什么是片選信號,也講到了三態(tài)門(mén),需要指出的是片選信號通常不是三態(tài)門(mén),其只存在兩個(gè)狀態(tài),即高電平或是低電平。前面我們也說(shuō)了,片選信號是用來(lái)“開(kāi)門(mén)”的,而片選信號又有高和低電平,那到底是高電平表示“開(kāi)門(mén)”呢?還是低電平?
對于這一問(wèn)題,我們稱(chēng)如果一個(gè)電平對于一個(gè)片選信號表示“開(kāi)門(mén)”那么它就是這一信號的有效電平。比如,對于一個(gè)片選信號,如果低電平表示“開(kāi)門(mén)”,那么我們說(shuō)這個(gè)片選信號是低電平有效的。雖然,在這里我們用片選信號來(lái)解釋電平的有效性,但是很多信號都存在有效性的問(wèn)題,比如,后面我們將要談的讀信號和寫(xiě)信號都存在有效性問(wèn)題。
時(shí)序
在前面我們說(shuō)到當處理器要向外設芯片寫(xiě)數據時(shí),需要先將所需訪(fǎng)問(wèn)的外設的地址放在地址總線(xiàn)上,然后,由譯碼器將地址總線(xiàn)上的數據轉換成片選信號,片選信號則使能目標外設芯片,接下來(lái)處理器寫(xiě)數據到數據總線(xiàn)上,從而完成一個(gè)寫(xiě)操作。顯然,在處理器將數據寫(xiě)到數據總線(xiàn)之前地址線(xiàn)上的數據必須一直保留一段時(shí)間,否則的話(huà)譯碼器不能長(cháng)時(shí)間的使片選信號有效。
當完成了數據的寫(xiě)操作后,處理器就不需要保證地址總線(xiàn)上的地址有效了。我們可以看出,這一系列的操作都有一定嚴格的時(shí)間順序的,這稱(chēng)之為時(shí)序。時(shí)序描述了處理器與外部設備的交互信號 “規程”,大家只有按照這一“規程”來(lái)操作,才能保證處理器與外部設備之間能正常的通訊。這好比,我們的道路上的紅綠燈,如果我們行人和車(chē)輛不按照其指示來(lái)通行的話(huà),就會(huì )出現事故。通常,采用時(shí)序圖來(lái)描述芯片之間通訊的信號“規程”。
ADDRESS是表示地址總線(xiàn)的,DQ是表示數據總線(xiàn)的,CE是片選信號,且是低電平有效,其寬度要保證在進(jìn)行讀操作時(shí)總是有效的。學(xué)會(huì )看時(shí)序圖對于做嵌入式系統開(kāi)發(fā)非常有幫助,因為我們不可避免的要與芯片打交道。
在時(shí)序圖中,通常會(huì )標識很多的時(shí)間需求信息。在寫(xiě)啟動(dòng)代碼時(shí)需要初始化各地址空間的片選地址寄存器和讀寫(xiě)時(shí)序,時(shí)序的配置依據就是來(lái)自于外設芯片的時(shí)間需求,這是芯片手冊很重要的一部分內容。當一個(gè)地址空間中存在多個(gè)外設芯片時(shí),我們需要考慮到其中慢的外設芯片的時(shí)間需求,否則的話(huà)有的芯片就不能正常工作。
讀信號
當處理器需要從外設芯片讀取信號時(shí),除了需要產(chǎn)生片選信號外,還需要告訴外設芯片這是一個(gè)讀操作,而不是一個(gè)寫(xiě)操作,這是通過(guò)讀信號來(lái)實(shí)現的。
寫(xiě)信號
前面講了讀信號,我想對于寫(xiě)信號也就不難理解了,這個(gè)信號用于告訴外設芯片,這是一個(gè)向外設芯片寫(xiě)數據的操作。
I/O端口
前面提到了外設(芯片),現在是對外設進(jìn)行分類(lèi)的時(shí)候了。大體上外設分為兩類(lèi),一類(lèi)是存儲器外設,而另一類(lèi)是非存儲器外設,后者常被稱(chēng)之為I/O設備,這里的I/O是Input/Output的簡(jiǎn)寫(xiě),即輸入、輸出。可見(jiàn),I/O外設是一個(gè)非常寬泛的概念。對于存儲器外設,其特點(diǎn)是,它所占用的空間是連續的一片。比如,SDRAM內存就是屬于存儲器外設,如果其容量是8M字節,那么其占用的地址空間也會(huì )是8M的。
與存儲器外設所不同的是,I/O外設所點(diǎn)用的地址一般都很少。比如一個(gè)I/O外設可能存在多個(gè)控制寄存器,這些控制寄存器從處理器來(lái)看就是多個(gè)I/O端口(地址),向這個(gè)地址寫(xiě)數據就是向外設所對應的寄存器寫(xiě)數據,反之,也可以是讀。比如,一個(gè)串口芯片可能存在多個(gè)寄存器,一個(gè)用來(lái)查詢(xún)芯片的狀態(tài),一個(gè)用來(lái)設置芯片的功能,另一個(gè)用來(lái)讀取芯片從串口線(xiàn)所收到的數據,后,還有一個(gè)用來(lái)向芯片寫(xiě)數據以向串口線(xiàn)上發(fā)送數據。對于這一串口芯片的寄存器,從處理器的角度來(lái)看,都是獨立的I/O端口。
I/O端口存在讀、寫(xiě)性問(wèn)題,有的端口是只讀的,有的端口是只寫(xiě)的,還有的端口是即可讀也可寫(xiě),其讀寫(xiě)性是由外設芯片的寄存器所決定的,在芯片的數據手冊中能找到。需要指出的是,有些存儲器外設也存在I/O端口,以對其進(jìn)行一定的控制。從I/O端口這一名字來(lái)看,對于處理器來(lái)說(shuō),就是對從外面讀入數據或是向外面輸出數據的一個(gè)接口總稱(chēng)。
中斷
中斷從硬件的角度來(lái)看就是一個(gè)能產(chǎn)生高、低電平的一根信號線(xiàn),但理解它需要從處理器的角度出發(fā)。我們說(shuō)過(guò)了,處理器從微觀(guān)上看,所做的工作是按順序進(jìn)行的,其對程序的處理只能是一條指令一條指令的執行。如果存在需要對外設芯片進(jìn)行訪(fǎng)問(wèn),而有可能從處理器發(fā)出讀、寫(xiě)命令后,由于外設通常比處理器慢很多,所以外設芯片需要一些時(shí)間來(lái)準備好所需的數據。在這種情況下,如果處理器一直等外設芯片的返回數據再執行后續的指令的話(huà),將耗費寶貴的時(shí)間,這些時(shí)間*可以用來(lái)做其它的工作。
別忘了,從宏觀(guān)上看來(lái)處理器常常是多任務(wù)的,任務(wù)是指操作系統所提供的調度單位。當一個(gè)任務(wù)因為等待外設芯片的數據而阻塞時(shí),我們可以切換到另外的任務(wù),從而提高處理效率。這就有一個(gè)問(wèn)題,當處理器去處理另一個(gè)任務(wù)時(shí),如果外設芯片的數據好了的話(huà),如果告訴處理器呢?就是通過(guò)中斷信號。中斷信號的高、低電平可以用來(lái)表示是否有中斷需要處理器注意以處理特定的事件(比如,外設數據準備好了的事件)。
由此看來(lái),中斷的引入能大大的提高處理器的運用效率。為了使用處理器上的中斷,一開(kāi)始我們需要初始化好處理器的中斷控制器,比如安裝好所需的中斷服務(wù)程序或稱(chēng)之為ISR(Interrupt Service Routine),然后,打開(kāi)中斷屏蔽位。中斷服務(wù)程序中需要做如下的操作:
1. 從外設讀入或向外設寫(xiě)數據。讀還是寫(xiě)通常需要讀取外設的中斷狀態(tài)寄存器來(lái)決定。
2. 清除外設的中斷信號。我們知道,中斷信號是由外設芯片驅動(dòng)的,為了告訴外設芯片,處理器已經(jīng)處理完了所需做的工作,那么處理器需要通過(guò)一定的方式通知外設芯片。這種方式就是向外設芯片的寄存器中的某一位寫(xiě)入一個(gè)數據,比如,可能是寫(xiě)入1表示清中斷,也可能是寫(xiě)入0表示清中斷,這通常在外設的數據手冊中能查到。當外設收到了處理器的清中斷請求后,其就會(huì )驅動(dòng)中斷線(xiàn)使其無(wú)效。比如,一個(gè)外設的中斷線(xiàn)是當其為低電平表示有中斷,將其從低電平變?yōu)楦唠娖骄褪球寗?dòng)為無(wú)效。
3. 清除處理器的中斷信號標識。處理器中往往也會(huì )保存外部中斷信號是否發(fā)生過(guò),當我們處理完了外設芯片的中斷時(shí),我們也需要清除處理器上的標識,從而為下一次中斷做準備。需要注意的是,清外設的中斷必須發(fā)生在請處理器中斷標識之前。
中斷還存在一個(gè)觸發(fā)方式問(wèn)題。有兩種觸發(fā)方式 ,一種是電平觸發(fā),另一種是沿觸發(fā)。電平觸發(fā)是指電平的高低表示外設是否有中斷,而沿觸發(fā)則是能過(guò)中斷線(xiàn)上的電平的升或降來(lái)表示的,顯然,存在兩種沿觸發(fā)方式。一種是中斷線(xiàn)從低電平變?yōu)楦唠娖?,我們稱(chēng)之為上升沿觸發(fā),另一處是中斷線(xiàn)從高電平轉換為低電平,我們稱(chēng)之為下降沿觸發(fā)。總的來(lái)說(shuō)中斷的觸發(fā)方式有電平觸發(fā)、上升沿觸發(fā)和下降沿觸發(fā)。電平觸發(fā)方式中處理中中斷設置很重要的一個(gè)步驟。
萬(wàn)用表
萬(wàn)用表通常是用來(lái)查看電平的高低、電阻的大小等的,是常用且*的工具之一。在嵌入式系統開(kāi)發(fā)中,我們常用的是數字萬(wàn)用表。
電平(Level)
在數字電路中,分為高電平和低電平,分別用1和0表示。一個(gè)數字電路的管腳,總是存在一個(gè)電平的,要么高要么低,或者說(shuō)要么1要到0(其實(shí),還有另一種狀態(tài))。
示波器
在嵌入式系統開(kāi)發(fā)中,我們不可避免的要與外設芯片打交道。調試驅動(dòng)程序時(shí),除了需要*看明白芯片的數據手冊,且在軟件高度的過(guò)程中,還需要看我們所期望的信號電平是否發(fā)生在芯片上。比如,我們在寫(xiě)驅動(dòng)程序時(shí),需要通過(guò)寫(xiě)I/O端口來(lái)對外設芯片進(jìn)行操作,當寫(xiě)相應的I/O端口時(shí),我們知道所對應芯片的片選信號應當有效,有時(shí),我們需要驗證是否按預期發(fā)生了,這就需要用到示波器。一般的示波器是能同時(shí)觀(guān)測兩個(gè)信號線(xiàn)的信號狀態(tài)的。
示波器都提供一定的功能,比如設置信號撲捉的方式等等。示波器很重要的一個(gè)參數據是其采集頻率,根據Nyquist采集定理,如果我們想用示波器查看頻率是100M赫茲的信號,那么其采樣頻率必須至少是其兩倍,即200M赫茲。有人可能會(huì )問(wèn):為什么不用萬(wàn)用表來(lái)看呢?因為萬(wàn)用表的采集頻率很底,無(wú)法采集到很快的信號變化。
邏輯分析儀
簡(jiǎn)單的說(shuō)邏輯分析器就是具有很多信號通道的示波器。通過(guò)邏輯分析儀,我們可以看到地址總線(xiàn)和數據總線(xiàn)上的數據。邏輯分析儀都提供一定的編程能力,用于編程什么時(shí)候開(kāi)始對總線(xiàn)上的數據進(jìn)行采集。