關(guān)于STM32 GPIO配置模式
其實(shí)關(guān)于GPIO模式,手冊(cè)有非常詳細(xì)的說明,可見好好查看Datasheet有多么重要??!
首先關(guān)于stm32的GPIO口有輸入輸出之分,這點(diǎn)與51單片機(jī)使用的雙向IO口有區(qū)別,這就需要根據(jù)我們具體是輸入還是輸出配置為相應(yīng)的輸入輸出模式。輸入就是輸入模式,輸出就是輸出模式,兩者不能混用。
下面這段話是手冊(cè)這么描述GPIO口的:
通用I/O(GPIO)
復(fù)位期間和剛復(fù)位后,復(fù)用功能未開啟,I/O端口被配置成浮空輸入模式(CNFx[1:0]=01b,
MODEx[1:0]=00b)。
復(fù)位后,JTAG引腳被置于輸入上拉或下拉模式:
─PA15:JTDI置于上拉模式
─PA14:JTCK置于下拉模式
─PA13:JTMS置于上拉模式
─PB4:JNTRST置于上拉模式
當(dāng)作為輸出配置時(shí),寫到輸出數(shù)據(jù)寄存器上的值(GPIOx_ODR)輸出到相應(yīng)的I/O引腳。可以以推
挽模式或開漏模式(當(dāng)輸出0時(shí),只有N-MOS被打開)使用輸出驅(qū)動(dòng)器。
輸入數(shù)據(jù)寄存器(GPIOx_IDR)在每個(gè)APB2時(shí)鐘周期捕捉I/O引腳上的數(shù)據(jù)。
所有GPIO引腳有一個(gè)內(nèi)部弱上拉和弱下拉,當(dāng)配置為輸入時(shí),它們可以被激活也可以被斷開
從上面的描述我們知道,單片機(jī)復(fù)位后默認(rèn)是浮空輸入模式,但是JTAG的引腳會(huì)被設(shè)置為輸入上拉或者下拉模式。輸出模式下是輸出寄存器ODR的輸出到對(duì)應(yīng)IO口實(shí)現(xiàn)高低電平。
輸入配置
當(dāng)I/O端口配置為輸入時(shí):
● 輸出緩沖器被禁止
● 施密特觸發(fā)輸入被激活
● 根據(jù)輸入配置(上拉,下拉或浮動(dòng))的不同,弱上拉和下拉電阻被連接
● 出現(xiàn)在I/O腳上的數(shù)據(jù)在每個(gè)APB2時(shí)鐘被采樣到輸入數(shù)據(jù)寄存器
● 對(duì)輸入數(shù)據(jù)寄存器的讀訪問可得到I/O狀態(tài)
參見手冊(cè)關(guān)于輸入配置這幾點(diǎn)很重要。
1)當(dāng)作為輸入時(shí),輸出數(shù)據(jù)寄存器與IO口之間是斷開的,這也就意味著我們?cè)谳斎霠顟B(tài)下即使操作輸出數(shù)據(jù)寄存器對(duì)IO口也沒有影響。比如我們用庫(kù)函數(shù)各種直接或間接改變輸出數(shù)據(jù)寄存器的操作都是無(wú)效的。比如我們?cè)O(shè)置在初始化某IO為上拉輸入后,又將該IO口輸出為0,將這輸出為0的操作是完全無(wú)效不起作用的!比如你設(shè)置為輸入去用萬(wàn)用表測(cè)IO口就很可笑的操作?。?/p>
2)IO口的數(shù)據(jù)在每個(gè)APB2時(shí)鐘被采樣到輸入數(shù)據(jù)寄存器,這就意味著我們比如當(dāng)前模式為輸入模式,那么在72M系統(tǒng)時(shí)鐘下,約每13ns會(huì)更新一次輸入數(shù)據(jù)。比如我們?cè)趯懩承┩ㄐ沤涌跁r(shí)序,在設(shè)置為輸入模式下就要留個(gè)心看看是否數(shù)據(jù)能否在讀命令下是否13ns該通信方式是否有效數(shù)據(jù)已經(jīng)到達(dá)保證讀取 的是準(zhǔn)確值,是否需加延時(shí)(針對(duì)通信數(shù)據(jù)更新慢的情況)。
3)注意我們?cè)O(shè)置為浮空、上拉還是下拉輸入,在沒有接外設(shè)的情況下,這些狀態(tài)才是確定的。比如我們說浮空模式下,輸入值不確定可能為0可能為1,上拉輸入時(shí)輸入數(shù)據(jù)寄存器為1,下拉輸入時(shí)輸入數(shù)據(jù)寄存器值為0均是針對(duì)前提是在未接任何外設(shè)情況下來(lái)說的!我們測(cè)開發(fā)板一定要先確定引腳是否有外設(shè)影響!
4)STM32為弱上拉和弱下拉,也就是上拉電阻阻值很大,未接外設(shè)時(shí)輸入數(shù)據(jù)寄存器為1,這樣有利于檢測(cè)低電平輸入;同理,下拉輸入未接外設(shè)輸入數(shù)據(jù)寄存器為0,有利于我們檢測(cè)高電平輸入。而對(duì)于外設(shè)電平可高可低的輸入,我們?cè)O(shè)置為浮空輸入即可。
5)輸入數(shù)據(jù)寄存器為只讀,在硬件仿真時(shí)值是屏蔽表示不可修改,但是值是準(zhǔn)確的!需要注意的是,硬件仿真輸入模式下去查看輸入寄存器IDR沒意義,輸出模式下去查看輸出數(shù)據(jù)寄存器ODR也沒意義。
輸出配置
當(dāng)I/O端口被配置為輸出時(shí):
● 輸出緩沖器被激活
─開漏模式:輸出寄存器上的’0’激活N-MOS,而輸出寄存器上的’1’將端口置于高阻狀態(tài)(PMOS從不被激活)。
─推挽模式:輸出寄存器上的’0’激活N-MOS,而輸出寄存器上的’1’將激活P-MOS。
● 施密特觸發(fā)輸入被激活
● 弱上拉和下拉電阻被禁止
● 出現(xiàn)在I/O腳上的數(shù)據(jù)在每個(gè)APB2時(shí)鐘被采樣到輸入數(shù)據(jù)寄存器
● 在開漏模式時(shí),對(duì)輸入數(shù)據(jù)寄存器的讀訪問可得到I/O狀態(tài)
● 在推挽式模式時(shí),對(duì)輸出數(shù)據(jù)寄存器的讀訪問得到最后一次寫的值。
參見手冊(cè)關(guān)于輸出配置這段話我們需要注意這幾點(diǎn):
1)在輸出模式下,輸入寄存器與IO口之間并未屏蔽,并且在開漏輸出模式下,我們讀輸入數(shù)據(jù)寄存器的操作可以真實(shí)的讀取我們輸入口的狀態(tài)(盡管不建議輸出模式和輸入混用,但是具有這樣的性質(zhì)是要注意的)
2)開漏輸出的特點(diǎn)如果要控制外設(shè),則必須外接上拉電阻,因?yàn)槠渥陨聿痪邆漭敵龈唠娖降哪芰?,只能輸出低電平,?dāng)然這種需外接上拉電阻的模式也實(shí)現(xiàn)我們可輸出我們想要的任意“高電平”,比如5V外接5V上拉即可;而推挽輸出則可輸出可高可低電平。(欲了解見下文)
單片機(jī)I/O口推挽與開漏輸出詳解:
推挽輸出:可以輸出高,低電平,連接數(shù)字器件;推挽結(jié)構(gòu)一般是指兩個(gè)三極管分別受兩互補(bǔ)信號(hào)的控制,總是在一個(gè)三極管導(dǎo)通的時(shí)候另一個(gè)截止.
開漏輸出:輸出端相當(dāng)于三極管的集電極. 要得到高電平狀態(tài)需要上拉電阻才行. 適合于做電流型的驅(qū)動(dòng),其吸收電流的能力相對(duì)強(qiáng)(一般20ma以內(nèi)).
我們先來(lái)說說集電極開路輸出的結(jié)構(gòu)。集電極開路輸出的結(jié)構(gòu)如圖1所示,右邊的那個(gè)三極管集電極什么都不接,所以叫做集電極開路(左邊的三極管為反相之用,使輸入為“0”時(shí),輸出也為“0”)。對(duì)于圖1,當(dāng)左端的輸入為“0”時(shí),前面的三極管截止(即集電極C跟發(fā)射極E之間相當(dāng)于斷開),所以5V電源通過1K電阻加到右邊的三極管上,右邊的三極管導(dǎo)通(即相當(dāng)于一個(gè)開關(guān)閉合);當(dāng)左端的輸入為“1”時(shí),前面的三極管導(dǎo)通,而后面的三極管截止(相當(dāng)于開關(guān)斷開)。
我們將圖1簡(jiǎn)化成圖2的樣子。圖2中的開關(guān)受軟件控制,“1”時(shí)斷開,“0”時(shí)閉合。很明顯可以看出,當(dāng)開關(guān)閉合時(shí),輸出直接接地,所以輸出電平為0。而當(dāng)開關(guān)斷開時(shí),則輸出端懸空了,即高阻態(tài)。這時(shí)電平狀態(tài)未知,如果后面一個(gè)電阻負(fù)載(即使很輕的負(fù)載)到地,那么輸出端的電平就被這個(gè)負(fù)載拉到低電平了,所以這個(gè)電路是不能輸出高電平的。
再看圖三。圖三中那個(gè)1K的電阻即是上拉電阻。如果開關(guān)閉合,則有電流從1K電阻及開關(guān)上流過,但由于開關(guān)閉其它三個(gè)口帶內(nèi)部上拉),當(dāng)我們要使用輸入功能時(shí),只要將輸出口設(shè)置為1即可,這樣就相當(dāng)于那個(gè)開關(guān)斷開,而對(duì)于P0口來(lái)說,就是高阻態(tài)了。
對(duì)于漏極開路(OD)輸出,跟集電極開路輸出是十分類似的。將上面的三極管換成場(chǎng)效應(yīng)管即可。這樣集電極就變成了漏極,OC就變成了OD,原理分析是一樣的。
另一種輸出結(jié)構(gòu)是推挽輸出。推挽輸出的結(jié)構(gòu)就是把上面的上拉電阻也換成一個(gè)開關(guān),當(dāng)要輸出高電平時(shí),上面的開關(guān)通,下面的開關(guān)斷;而要輸出低電平時(shí),則剛好相反。比起OC或者OD來(lái)說,這樣的推挽結(jié)構(gòu)高、低電平驅(qū)動(dòng)能力都很強(qiáng)。如果兩個(gè)輸出不同電平的輸出口接在一起的話,就會(huì)產(chǎn)生很大的電流,有可能將輸出口燒壞。而上面說的OC或OD輸出則不會(huì)有這樣的情況,因?yàn)樯侠娮杼峁┑碾娏鞅容^小。如果是推挽輸出的要設(shè)置為高阻態(tài)時(shí),則兩個(gè)開關(guān)必須同時(shí)斷開(或者在輸出口上使用一個(gè)傳輸門),這樣可作為輸入狀態(tài),AVR單片機(jī)的一些IO口就是這種結(jié)構(gòu)。
開漏電路特點(diǎn)及應(yīng)用
在電路設(shè)計(jì)時(shí)我們常常遇到開漏(open drain)和開集(open collector)的概念。
所謂開漏電路概念中提到的“漏”就是指MOSFET的漏極。同理,開集電路中的“集”就是指三極管的集電極。開漏電路就是指以MOSFET的漏極為輸出的電路。一般的用法是會(huì)在漏極外部的電路添加上拉電阻。完整的開漏電路應(yīng)該由開漏器件和開漏上拉電阻組成。如圖1所示:
組成開漏形式的電路有以下幾個(gè)特點(diǎn):
1. 利用外部電路的驅(qū)動(dòng)能力,減少IC內(nèi)部的驅(qū)動(dòng)(或驅(qū)動(dòng)比芯片電源電壓高的負(fù)載)。當(dāng)IC內(nèi)部MOSFET導(dǎo)通時(shí),驅(qū)動(dòng)電流是從外部的VCC流經(jīng)R pull-up ,MOSFET到GND。IC內(nèi)部?jī)H需很下的柵極驅(qū)動(dòng)電流。如圖1。
2. 可以將多個(gè)開漏輸出的Pin,連接到一條線上。形成 “與邏輯” 關(guān)系。如圖1,當(dāng)PIN_A、PIN_B、PIN_C任意一個(gè)變低后,開漏線上的邏輯就為0了。這也是I2C,SMBus等總線判斷總線占用狀態(tài)的原理。如果作為輸出必須接上拉電阻。接容性負(fù)載時(shí),下降延是芯片內(nèi)的晶體管,是有源驅(qū)動(dòng),速度較快;上升延是無(wú)源的外接電阻,速度慢。如果要求速度高電阻選擇要小,功耗會(huì)大。所以負(fù)載電阻的選擇要兼顧功耗和速度。
3. 可以利用改變上拉電源的電壓,改變傳輸電平。如圖2, IC的邏輯電平由電源Vcc1決定,而輸出高電平則由Vcc2(上拉電阻的電源電壓)決定。這樣我們就可以用低電平邏輯控制輸出高電平邏輯了(這樣你就可以進(jìn)行任意電平的轉(zhuǎn)換)。(例如加上上拉電阻就可以提供TTL/CMOS電平輸出等。)
4. 開漏Pin不連接外部的上拉電阻,則只能輸出低電平(因此對(duì)于經(jīng)典的51單片機(jī)的P0口而言,要想做輸入輸出功能必須加外部上拉