GPIO輸入輸出各種模式(推挽、開漏、準雙向端口)詳解(轉)
GPIO輸入輸出各種模式(推挽、開漏、準雙向端口
概述能將處理器的GPIO(General Purpose Input and Output)內部結構和各種模式徹底弄清楚的人並不多,最近在百度上搜索了大量關於這部分的資料,對於其中很多問題的說法並不統一。本文盡可能的將IO涉及到的所有問題羅列出來,對於有明確答案的問題解釋清楚,對於還存在疑問的地方也將問題提出,供大家討論。
概括地說,IO的功能模式大致可以分為輸入、輸出以及輸入輸出雙向三大類。其中作為基本輸入IO,相對比較簡單,主要涉及的知識點就是高阻態;作為輸出IO,相比於輸入復雜一些,工作模式主要有開漏(Open Drain)模式和推挽(Push-Pull)模式,這一部分涉及的知識點比較多;對於輸入輸出IO,容易產生疑惑的地方是準雙向和雙向端口的區別。
下面就按照這樣的順序依次介紹各個模式的詳細情況。
輸入IO
這裏所說的輸入IO,指的是只作為輸入,不具有輸出功能。此時對於input引腳的要求就是高阻(高阻與三態是同一個概念)。基本輸入電路的類型大致可以分為3類:基本輸入IO電路、施密特觸發輸入電路以及弱上拉輸入電路。
先從最基本的基本輸入IO電路說起,其電路如圖 1所示。
圖 1
其中的緩沖器U1是具有控制輸入端,且具有高阻抗特性的三態緩沖器。通俗地說就是這個緩沖器對外來說是高阻的,相當於在控制輸入端不使能的情況下,物理引腳與內部總線之間是完全隔離的,完全不會影響內部電路。而控制輸入端的作用就是可以發出讀Pin狀態的操作指令。其過程如圖 2所示。
圖 2
這種基本電路的一個缺點是在讀取外部信號的跳變沿時會出現抖動,如下圖所示。
圖 3
於是施密特觸發輸入電路就是解決了上述這種抖動的問題,其經過施密特觸發器後的信號如圖 4所示。
圖 4
對於輸入電路還存在另外一個問題,就是當輸入引腳懸空的時候,輸入端檢測到的電平是高還是低?當輸入信號沒有被驅動,即懸空(Floating)時,輸入引腳上任何的噪聲都會改變輸入端檢測到的電平,如圖 5所示。
圖 5
為了解決這個問題,可以在輸入引腳處加一個弱上拉電阻,如圖 6所示。
圖 6
這樣,當輸入引腳懸空時,會被RP上拉到高電平,在內部總線上就有確定的狀態了。
但是這種結構是有一定問題的。首先很明顯的一點是,當輸入引腳懸空時讀到的是1,當輸入引腳被高電平驅動時讀到的也是1,只有當輸入引腳被低電平驅動時讀到的才是0。也就是對於讀1采取的方式是"讀取非零"的方式。
另一個問題是該電路對外呈現的不是高阻,某種意義上說也在向外輸出,當外部驅動電路不同時可能出現錯誤的檢測結果。例如外部驅動電路是如圖 7所示的結構,該電路結構中通過K打到不同端可以輸出高電平或者低電平。
圖 7
如果將如圖 7所示的電路輸出低電平,連接到帶有弱上拉電阻的輸入引腳,其結構如下所示。
圖 8
由歐姆定律知,測試點處的電平是,於是CPU測得的輸入信號為高,而外部驅動電路希望輸出的電平為低。這種錯誤的原因就在於這種結構的輸入電路並不是真正的高阻,或者說這個輸入IO其實也在輸出,而且影響了外部輸入電路。
這種情況的發生也說明了:信號前後兩級傳遞,為什麽需要輸出阻抗小,輸入阻抗大的原因。在這個例子中,外圍驅動電路的輸出阻抗很大,達到了100Kohm;而輸入端的阻抗又不夠大,只有10Kohm,於是就出現了問題。如果輸入端的輸入阻抗真正做到高阻(無窮大),如下所示,就不會出現問題。
圖 9
上面提到的這個帶弱上拉的輸入電路,也就是在後續章節會提到的準雙向端口的情況。
輸出IO
IO輸出電路最主要的兩種模式分別是推挽輸出(Push-Pull Output)和開漏輸出(Open Drain Output)。
推挽輸出(Push-Pull Output)
推挽輸出的結構是由兩個三極管或者MOS管受到互補信號的控制,兩個管子始終保持一個處於截止,另一個處於導通的狀態。如圖 10所示。
圖 10
推挽輸出的最大特點是可以真正能真正的輸出高電平和低電平,在兩種電平下都具有驅動能力。
補充說明:所謂的驅動能力,就是指輸出電流的能力。對於驅動大負載(即負載內阻越小,負載越大)時,例如IO輸出為5V,驅動的負載內阻為10ohm,於是根據歐姆定律可以正常情況下負載上的電流為0.5A(推算出功率為2.5W)。顯然一般的IO不可能有這麽大的驅動能力,也就是沒有辦法輸出這麽大的電流。於是造成的結果就是輸出電壓會被拉下來,達不到標稱的5V。
當然如果只是數字信號的傳遞,下一級的輸入阻抗理論上最好是高阻,也就是只需要傳電壓,基本沒有電流,也就沒有功率,於是就不需要很大的驅動能力。
對於推挽輸出,輸出高、低電平時電流的流向如圖 11所示。所以相比於後面介紹的開漏輸出,輸出高電平時的驅動能力強很多。
圖 11
但推挽輸出的一個缺點是,如果當兩個推挽輸出結構相連在一起,一個輸出高電平,即上面的MOS導通,下面的MOS閉合時;同時另一個輸出低電平,即上面的MOS閉合,下面的MOS導通時。電流會從第一個引腳的VCC通過上端MOS再經過第二個引腳的下端MOS直接流向GND。整個通路上電阻很小,會發生短路,進而可能造成端口的損害。這也是為什麽推挽輸出不能實現" 線與"的原因。
開漏輸出(Open Drain Output)
常說的與推挽輸出相對的就是開漏輸出,對於開漏輸出和推挽輸出的區別最普遍的說法就是開漏輸出無法真正輸出高電平,即高電平時沒有驅動能力,需要借助外部上拉電阻完成對外驅動。下面就從內部結構和原理上說明為什麽開漏輸出輸出高電平時沒有驅動能力,以及進一步比較與推挽輸出的區別。
首先需要介紹一些開漏輸出和開集輸出。這兩種輸出的原理和特性基本是類似的,區別在於一個是使用MOS管,其中的"漏"指的就是MOS管的漏極;另一個使用三極管,其中的"集"指的就是MOS三極管的集電極。這兩者其實都是和推挽輸出相對應的輸出模式,由於使用MOS管的情況較多,很多時候就用"開漏輸出"這個詞代替了開漏輸出和開集輸出。
介紹就先從開集輸出開始,其原理電路結如圖 12所示。
圖 12
圖 12左邊的電路是開集(OC)輸出最基本的電路,當輸入為高電平時,NPN三極管導通,Output被拉到GND,輸出為低電平;當輸入為低電平時,NPN三極管閉合,Output相當於開路(輸出高阻)。高電平時輸出高阻(高阻、三態以及floating說的都是一個意思),此時對外沒有任何的驅動能力。這就是開漏和開集輸出最大的特點,如何利用該特點完成各種功能稍後介紹。這個電路雖然完成了開集輸出的功能,但是會出現input為高,輸出為低;input為低,輸出為高的情況。
圖 12右邊的電路中多使用了一個三極管完成了"反相"。當輸入為高電平時,第一個三極管導通,此時第二個三極管的輸入端會被拉到GND,於是第二個三極管閉合,輸出高阻;當輸入為低電平時,第一個三極管閉合,此時第二個三極管的輸入端會被上拉電阻拉到高電平,於是第二個三極管導通,輸出被拉到GND。這樣,這個電路的輸入與輸出是同相的了。
接下來介紹開漏輸出的電路,如圖 13所示。原理與開集輸出基本相同,只是將三極管換成了MOS而已。
圖 13
接著說說開漏、開集輸出的特點以及應用,由於兩者相似,後文中若無特殊說明,則用開漏表示開漏和開集輸出電路。
- 開漏輸出最主要的特性就是高電平沒有驅動能力,需要借助外部上拉電阻才能真正輸出高電平,其電路如圖 14所示。
圖 14
當MOS管閉合時,開漏輸出電路輸出高電平,且連接著負載時,電流流向是從外部電源,流經上來電阻RPU,流進負載,最後進入GND。
- 開漏輸出的這一特性一個明顯的優勢就是可以很方便的調節輸出的電平,因為輸出電平完全由上拉電阻連接的電源電平決定。所以在需要進行電平轉換的地方,非常適合使用開漏輸出。
- 開漏輸出的這一特性另一個好處在於可以實現"線與"功能,所謂的"線與"指的是多個信號線直接連接在一起,只有當所有信號全部為高電平時,合在一起的總線為高電平;只要有任意一個或者多個信號為低電平,則總線為低電平。而推挽輸出就不行,如果高電平和低電平連在一起,會出現電流倒灌,損壞器件。
推挽與開漏輸出的區別
圖 15
雙向IO
很多處理器的引腳可以設置為雙向端口,雙向端口的要求就是既可以輸出信號,又可以讀回外部信號輸入。要同時做到這兩點從原理上來說有點困難,首先從處理器的開漏輸出IO口的內部結構說起,如圖 16所示。
圖 16
該結構是在圖 13的基礎上,在三極管之前加入了一個FF,目的是用於控制輸出信號的時間。比較常見的一個應用場合是多個IO作為一個總線時,需要總線上的各個引腳同時將數據輸出。
對於開漏輸出結構,會將FF的輸出Q端連接會輸入驅動緩沖器,這樣的話執行讀操作是讀的並不是外部引腳的狀態,而是自己輸出的狀態。
雙向開漏IO
但是對圖 16的結構稍作修改,如圖 17所示時,該結構稱為雙向開漏IO的結構。所做的改動是將輸入驅動緩沖器連接到了PIN上。
圖 17
該結構輸出為"1"時,T1斷開,此時pin對外呈現高阻,作為輸入引腳沒有任何問題。但是如果該結構輸出"0"時,T1導通,此時pin對外短路到地,即無論外部輸入什麽信號,U2讀回的全部是低。所以對於這樣的結構,如果需要作為輸入引腳使用時,必須給U1輸出"1"後才能讀取外部引腳數據。
準雙向開漏IO
很多文獻中還提到了準雙向端口,其實準雙向端口就是圖 17的結構中加了一個上拉電阻,如圖 18所示。
圖 18
這個結構與圖 17相比有以下相同與不同之處:
- 作為輸入引腳使用時,也必須先向U1中寫"1",以達到斷開T1的目的。所以是否需要提前寫"1"並不是雙向IO與準雙向IO的區別。兩者做輸入端口時都需要提前寫"1"。
- 雙向端口作為輸入時是真正的高阻態,而準雙向IO作為輸入端口時,輸入阻抗不為高阻,於是有可能出現如本文圖 8所示的問題。
- 準雙向端口讀取輸入狀態,默認為高。也就是判斷外部輸入信號的方法是"非低則為高"。即該結構只能準確的識別外部的低電平,無法區分懸空和真正的高。於是只要讀到的不是0,都認為外部為1。
推挽輸出作為雙向IO
如果雙向端口中的輸出部分采用的是推挽輸出結構,那麽作為輸入時必須將上下兩個管子全部端口才能成為高阻,作為輸入。
51單片機的P0端口
在雙向端口的討論中,比較復雜的就是51單片機的P0端口了。這裏就詳細討論一下51單片機的P0端口結構和工作原理。
P0端口的內部結構如圖 19所示。
圖 19
內部結構比較復雜,包括以下這些器件:
- U1:與門。一個輸入連著控制線,另一個輸入連接這地址/數據信號。由於與門的特性,當控制線為1時,與門輸出與地址/數據信號的電平保持一致;如果控制線為0,則輸出恒為。於是控制信號線相當於與門的使能信號。
- U2:反相器,輸出信號為地址/數據信號的反相信號。
- U3和U6都是具有控制輸入端且具有高阻抗特性的三態緩沖器,作用是對於外部呈現高阻態。當控制端使能時可以將外部信號的電平讀進數據總線。
- U4:為鎖存器,目的就是控制引腳輸出信號的時間。
- U5:模擬開關,可以控制V2的輸入信號是來自鎖存器U4的Q非輸出還是來自於反相器U2的輸出。
- V1和V2分別是兩個MOS管。
了解了各個獨立器件之後就開始介紹工作在各個模式下的工作原理:
P0用於地址/數據線時:
在P0作為地址/數據線時,是地址、數據復用總線,P0需要輸出地址,同時需要讀回數據信號。
當P0需要輸出地址信息時,U1的控制信號為0,模擬開關U5接到U2反相器的輸出。於是當地址信號線傳來的信號為1,與控制線"1"相與之後輸出到V1的輸入信號為"1",V1截止。地址信號"1"經反相之後,通過模擬開關輸出到V2的輸入端為"0",V2導通,於是情況如圖 20所示,pin輸出"0"。
圖 20
當地址信號線傳來的信號為1,與控制線"1"相與之後輸出到V1的輸入信號為"0",V1導通。地址信號"0"經反相之後,通過模擬開關輸出到V2的輸入端為"1",V2截止,於是情況如圖 21所示,pin輸出"1"。
圖 21
於是在作為地址線輸出時,V1、V2兩個MOS管均使用了,是推挽輸出。
當P0在輸出低8位地址信息後,將變為數據總線,此時CPU的操作是控制端輸出0,模擬開關打到鎖存器的Q非端,且向鎖存器中打入"1"。於是Q非輸出為0,V2截止。同時控制線為0使得與門輸出為0,V1截止。由於V1和V2都截止,所以此時pin對外完全呈現高阻,作為輸入端口,外部數據通過U6進入內部總線,情況如圖 22所示。(相當於將推挽輸出的兩個MOS管全部斷開了)此時由於對外呈現高阻,所以是真正的輸入引腳。這就解釋了為什麽說P0是真正的雙線端口。
圖 22
P0用於普通IO時:
在P0作為普通IO並作為輸出時,控制信號為0,使V1始終處於截止狀態。模擬開關連接到Q非輸出,當作為輸出時,鎖存器的輸入端直接輸入0或者1,Q非將反相信號輸入到V2的輸入端。即當輸出"0"時,V2輸入端為"1",V2導通,pin輸出"0";當輸出"1"時,V2輸入端為"0",V2截止,pin輸出高阻的0。即當P0工作在普通IO模式下,輸出為開漏輸出,且內部沒有上拉電阻。
在P0作為普通IO並作為輸入時,控制信號為0,使V1始終處於截止狀態。模擬開關連接到Q非輸出,且CPU自動向鎖存器輸入端寫1,則V2輸入端為0,V2截止。與之前在作為地址/數據線,作為輸入時一樣,也是兩個MOS管全部斷開,pin直接連接到U6,對外呈現高阻。於是也是真正的輸入引腳。
綜上P0無論工作在哪種模式下都是真正的雙端口IO。
51單片機的P1~P3端口
51單片機的其他三個端口的內部結構如圖 23所示,與P0相比簡單了很多,沒有了頂部的MOS管,也沒有了地址/數據信號的選項。作為輸出時是帶有上拉電阻的的開漏輸出,作為輸入時是有上拉電阻存在的,於是輸入端口對外不是高阻。這就解釋了為什麽P1~P3只能是準雙向端口。
圖 23
- 這種情況的發生也說明了:信號前後兩級傳遞,為什麽需要輸出阻抗小,輸入阻抗大的原因。在這個例子中,外圍驅動電路的輸出阻抗很大,達到了100Kohm;而輸入端的阻抗又不夠大,只有10Kohm,於是就出現了問題。如果輸入端的輸入阻抗真正做到高阻(無窮大),如下所示,就不會出現問題。 哈哈。一開始認為作者這段話錯了。仔細又思考下。作者應該是對的。 信號傳遞確實需要發送信號的設備的輸出阻抗小,接收設備的輸入阻抗大。但在作者的論述中,所謂的"外圍驅動電路"是作為發送信號的設備,而"單片機輸入端"是作為接收信號的設備。所以需要外圍的設備輸出阻抗小(這個例子達到了100k,相比10k屬於大了),單片機的輸入阻抗又不夠大(沒有達到高阻抗,只有10k),於是出現了傳輸錯誤。我犯的錯誤是看到“外圍設備”就認為是接收設備,看到“單片機的輸入端”就認為是發送設備。
GPIO輸入輸出各種模式(推挽、開漏、準雙向端口)詳解(轉)