stm32的引腳有兩種用途:GPIO(general purpose io)和AFIO(alternate function io)
對于一些引腳(視芯片而定),這兩種用途都沒有,如在64腳產(chǎn)品中,OSC_IN/OSC_OUT與作為GPIO端口的PD0/PD1共用一樣的引腳,而在100、144引腳產(chǎn)品中,這四個功能各有引腳與之對應(yīng),不互相沖突,所以O(shè)SC_IN/OSC_OUT既不作GPIO也不作AFIO,當(dāng)然,這樣的引腳不是討論重點。
1、引腳的配置
不論是作GPIO還是做AFIO,都要對引腳進行配置。在固件庫函數(shù)中,用GPIO_Init()函數(shù)對引腳進行配置,并不是說這個函數(shù)帶了“GPIO”字樣就是要當(dāng)做GPIO來用,而是把它納入GPIO的范疇來討論。
所謂配置,就是引腳上的片上資源連接方式,如上拉電阻、密特觸發(fā)等等。關(guān)于配置的問題,請見http://www.cnblogs.com/king-77024128/articles/1999395.html?1?3。理解了配置,也就能明白配置與模式的區(qū)別。
特別得,在下文中將會專門討論一下輸出配置中的推挽與開漏。
2、復(fù)用功能
復(fù)用功能有兩種:沒有重映像、重映像(包括部分重映像、完全重映像),使用引腳用作AFIO功能,同樣需要對其進行配置。
這三句話來自參考手冊,但我對第一句和注意有疑問,第三節(jié)講。如果把端口配置成復(fù)用輸出功能,則引腳和輸出寄存器斷開,并和片上外設(shè)的輸出信號連接。輸入配置則與GPIO沒有區(qū)別。
為什么輸出模式有專門的復(fù)用模式而輸入則沒有呢。因為輸出是由芯片內(nèi)部電路驅(qū)動的,必須選擇這個驅(qū)動來自哪一個外設(shè),是GPIO還是復(fù)用此管腳的其他外設(shè),也就是選擇該管腳在內(nèi)部是與哪個外設(shè)相連的,不說明這個就會發(fā)生信號的錯亂。而輸入則不同了,輸入信號是由芯片外的信號驅(qū)動的,雖然該信號進入芯片內(nèi)部后可能有不同的去向,但不需要對此進行配置,因為不會發(fā)生信號的沖突,最壞的情況就是多驅(qū)動了個寄存器而已。事實上,當(dāng)將引腳作為GPIO輸入時,相應(yīng)的AFIO外設(shè)是處在關(guān)閉的狀態(tài),并不會耗電;當(dāng)引腳作為AFIO的輸入時,可能GPIO是讀不進來的,這是我猜的,沒有驗證,能不能讀進來無所謂的,不必糾結(jié)于此。
若選擇了復(fù)用,則默認是沒有重映像的,可以直接使用外設(shè),不需要再軟件做設(shè)置。
但若要重映射,則需要簡單設(shè)置一下,
先要配置重映射后對應(yīng)的管腳,可參看參考手冊或數(shù)據(jù)手冊引腳定義章節(jié),開AFIO時鐘,使能重映射。例如重映射USART1,全部代碼如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
/*對寄存器AFIO_EVCR,AFIO_MAPR和AFIO_EXTICRX進行讀寫操作前,即重映射和選擇外部中斷線前,應(yīng)當(dāng)首先打開AFIO的時鐘*/
/* Configure USART1 Tx (PA.09) as alternate function push-pull */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure USART1 Rx (PA.10) as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);
這就完成了IO口的配置和重映射,下邊再配置相關(guān)的外設(shè)(USART1)就可以使用了。
外部中斷線也是可以映射的,并且需要開AFIO時鐘,不用GPIO_PinRemap函數(shù),用GPIO_EXTILineConfig重映射引腳到中斷線。其實與其說是映射,不如說是選擇,選擇引腳連接到外部中斷線。
重映射不是任意的,只能重映射到指定的管腳。
3、關(guān)于第二節(jié)講到那個疑問,為甚么不能配置成模擬輸入?模擬輸入與浮空什么區(qū)別?
答案是可以配置成模擬輸入,官方3.5版固件庫例子和alientek例程都是將ADC輸入引腳配置成GPIO_Mode_AIN
那么配置成浮空行么,還能ADC么?
//例程
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//修改
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOC, &GPIO_InitStructure);
實驗證明,這兩種配置都能實現(xiàn)ADC。那么USART的Tx應(yīng)配置成GPIO_Mode_IN_FLOATING,如果配置成GPIO_Mode_AIN,還能接受數(shù)據(jù)么?金牛板實驗結(jié)果是不能,ST不我欺也??傊?/p>
可以將引腳配置成模擬輸入,使用相應(yīng)的復(fù)用功能;
浮空與模擬這兩種配置是不同的。
關(guān)于第二節(jié)里那個“注意“,我也不知道是什么意思。我猜測是這樣的:打開某外設(shè),這個外設(shè)將某引腳當(dāng)做輸入,我們偏偏把這個引腳配置為GPIO輸出,這樣可以操作GPIO來”欺騙“這個外設(shè),這種用法應(yīng)該是很微妙的。
4、推挽與開漏
不僅僅stm32有這種配置,實際上,這兩種已經(jīng)廣泛應(yīng)用在很多場合。
推挽,又叫做推拉,是個很形象的名字,一般是指兩個三極管(MOS管)分別受兩互補信號(或者一個信號,但是用互補對管)的控制,總是在一個三極管導(dǎo)通的時候另一個截止,這樣的電路被稱為推挽式(互補式):
這種電路在放大中通常被用作輸出級,在STM32中,推挽配置就是這種,如圖:
在相應(yīng)位置1時,P-MOS導(dǎo),通N-MOS截止,輸出電壓為VDD;在相應(yīng)位置0時,N-MOS導(dǎo)通,P-MOS截止,輸出電壓為VSS,這就是所謂的推挽。是比較簡單的。
而所謂的開漏(對三極管而言是開集,一樣的原理),則要巧妙一些。所謂開漏電路概念中提到的“漏”就是指MOS FET的漏極。同理,開集電路中的“集”就是指三極管的集電極。開漏電路就是指以MOS FET的漏極為輸出的電路。一般的用法是會在漏極外部的電路添加上拉電阻。完整的開漏電路應(yīng)該由開漏器件和開漏上拉電阻組成。
對于stm32,開漏就是失能了P-MOS,這樣,當(dāng)相應(yīng)位置1時,引腳實際上是處在了浮空的狀態(tài),而通過外接的上拉電阻,將其拉高。
這么做有如下的好處:
1、可以將多個開漏輸出的引腳,連接到一條線上。形成“與邏輯”關(guān)系。當(dāng)多個引腳任意一個變低后,開漏線上的邏輯就為0了。這也是I2C,SMBus等總線判斷總線占用狀態(tài)的原理。在我的文章“stm32模擬iic——引腳配置、代碼”中,還會提到這個問題。
2、 可以利用改變上拉電源的電壓,改變傳輸電平。這樣我們就可以用低電平邏輯控制輸出高電平邏輯了。想想當(dāng)初認為stm32輸出3.3v電壓帶不動IRF540,就直接斷定要重新選型,是錯誤的想法,只要將推挽輸出變?yōu)殚_漏,再加上上拉到5v的電阻,就能解決這個問題。
順便一提,上拉電阻的阻值決定了邏輯電平轉(zhuǎn)換的沿的速度。阻值越大,速度越低功耗越小。反之亦然。
上海意泓電子科技有限責(zé)任公司 版權(quán)所有 未經(jīng)授權(quán)禁止復(fù)制或鏡像
CopyRight 2020-2025 www.pendragonrpg.com All rights reserved 滬ICP備2021005866號