(注:此為樂(lè)某學(xué)習(xí)記錄,若有出錯(cuò)的地方歡迎各位指出?。?/p>
前言
本人使用的開(kāi)發(fā)板的芯片是STM32H743XIH6,所以外設(shè)也是根據(jù)此芯片來(lái)介紹。
在使用HAL庫(kù)配置的時(shí)候,需要安裝STM32CubeMX。此軟件可在ST官網(wǎng)下載,剩下的安裝步驟比較簡(jiǎn)單,不會(huì)單獨(dú)出篇進(jìn)行講解。
STM32CubeMX下載網(wǎng)址:https://www.st.com/zh/development-tools/stm32cubemx.html
一、什么是GPIO?可以做什么?
GPIO是General?Purpose?Input/Output的簡(jiǎn)寫(xiě),翻譯為通用輸入/輸出。在STM32里是可以對(duì)其進(jìn)行控制或讀取的引腳,通俗點(diǎn)講,可以對(duì)它們輸出高/低電平或者讀取它們的實(shí)時(shí)電平。
GPIO可以實(shí)現(xiàn)跟硬件設(shè)備之間的通信(UART、IIC、SPI等),控制硬件設(shè)備的工作(LED、蜂鳴器等),讀取硬件設(shè)備的狀態(tài)等(中斷讀取,引腳狀態(tài)讀取等)。
我們知道了GPIO可以做這么多事,但是要怎么去實(shí)現(xiàn)呢?這里就提到一個(gè)復(fù)用的說(shuō)法,就是將需要用的引腳用復(fù)用器去連接到其他的外設(shè),這樣的引腳功能就不會(huì)有沖突。有的操作就是,復(fù)用配置后,先執(zhí)行這個(gè)外設(shè)的功能,然后再?gòu)?fù)用到其他的外設(shè)上使用。
我使用的這個(gè)芯片一共有11組IO,分別是GPIOA~K。其中GPIOA~J是16個(gè)IO口,GPIOK是只有8個(gè)IO,大家使用時(shí)請(qǐng)仔細(xì)閱讀數(shù)據(jù)手冊(cè)或參考手冊(cè)。單個(gè)IO的稱呼,例如GPIOA的PIN0,就可以叫做PA0。
二、GPIO的基本結(jié)構(gòu)

我們使用到的IO的內(nèi)部結(jié)構(gòu)基本都是這樣,對(duì)關(guān)鍵器件的解析:
1、保護(hù)二極管
為了防止IO引腳接到了一個(gè)過(guò)高或者過(guò)低的電壓,當(dāng)引腳電壓高于VDD時(shí),上方的二極管導(dǎo)通;當(dāng)引腳電壓低于VSS時(shí),下方的二極管導(dǎo)通,防止不正常電壓引入芯片導(dǎo)致芯片燒毀。 所以,IO是無(wú)法直接接到高功率的器件工作的,需要有額外的電路去處理這部分的問(wèn)題,否則可能會(huì)導(dǎo)致芯片的損壞或者無(wú)法驅(qū)動(dòng)外接器件的工作。
2、P-MOS管和N-MOS管
由P-MOS管和N-MOS管組成的單元電路使得GPIO具有“推挽輸出”和“開(kāi)漏輸出”的模式。推挽即使強(qiáng)高或者強(qiáng)低的輸出,開(kāi)漏只有強(qiáng)低的輸出,無(wú)法進(jìn)行強(qiáng)高的操作。
3、開(kāi)關(guān)
將輸入的信號(hào)轉(zhuǎn)換為0和1的器件。例如,輸入的電平為1.5V,但是我的低電平閾值是0-0.4V,高電平是2.8-VDD。那么這個(gè)電平,就會(huì)被視為浮空狀態(tài)。輸出同理,不會(huì)輸出閾值之外的電平,輸出0的范圍就是0-0.4V,輸出高就是2.8-VDD。如果看到有VDD_FT,就是兼容5V。
三、不同輸入/輸出模式
1、五種輸入:
(1)浮空輸入
此模式下的IO口的電平,由外部的電平信號(hào)決定,是不確定的信號(hào),最終會(huì)直接進(jìn)入輸入數(shù)據(jù)寄存器。此模式容易會(huì)受到干擾來(lái)擾亂電平,通常用于配置USART的RX引腳,如下圖所示:

(2)上拉輸入
此模式下的IO口電平,若無(wú)信號(hào)接入(懸空),默認(rèn)為高電平。若輸入高電平,電平狀態(tài)就會(huì)保持高電平;若輸入低電平,電平狀態(tài)就會(huì)被拉低為低電平,此上拉為弱上拉。最終會(huì)直接進(jìn)入輸入數(shù)據(jù)寄存器。此模式可用作與一些電平狀態(tài)為浮空的器件,例如按鍵。若按鍵是一端接VSS,一端接IO。沒(méi)有按下的情況就是浮空的,當(dāng)按下按鍵后就是低電平。

(3)下拉輸入
此模式下的IO口電平,若無(wú)信號(hào)接入(懸空),默認(rèn)為低電平。若輸入高電平,電平狀態(tài)就會(huì)被拉高為高電平;若輸入低電平,電平狀態(tài)就會(huì)保持低電平,此下拉為弱下拉。最終會(huì)直接進(jìn)入輸入數(shù)據(jù)寄存器。此模式可用作與一些電平狀態(tài)為浮空的器件,例如按鍵。若按鍵是一端接VDD,一端接IO。沒(méi)有按下的情況就是浮空的,當(dāng)按下按鍵后就是高電平。

(4)模擬輸入
此模式下的IO,將不再是讀取電平狀態(tài),獲取的是IO口的電壓值。最終會(huì)輸入到外設(shè)使用。通常使用到ADC外設(shè),用來(lái)讀取模擬電壓的。例如,讀熱敏電阻和固定電阻的分壓來(lái)計(jì)算當(dāng)前溫度。

(5)復(fù)用輸入
此模式下的IO,會(huì)復(fù)用到單片機(jī)的其他外設(shè),最終輸入到外設(shè)使用。例如,USART的串口接收引腳,SPI的MISO引腳等。

2、四種輸出:
(1)推挽輸出
此時(shí)的IO上的P-MOS管和N-MOS管都進(jìn)行工作,當(dāng)我們輸出設(shè)置"0"時(shí),N-MOS管打開(kāi),P-MOS管關(guān)閉,輸出低電平。當(dāng)我們輸出設(shè)置"1"時(shí),P-MOS管打開(kāi),N-MOS管關(guān)閉,輸出高電平。此模式輸出的是強(qiáng)電平,是可以驅(qū)動(dòng)一些器件的,帶負(fù)載能力較強(qiáng),開(kāi)關(guān)速度高。
此時(shí)施密特觸發(fā)器時(shí)開(kāi)啟的,我們也可以讀取輸出數(shù)據(jù)寄存器的值,可以看是否設(shè)置正確,不過(guò)這很少用。同時(shí)我們也可以通過(guò)輸入數(shù)據(jù)寄存器來(lái)讀取電平狀態(tài),注意!我們的IO電平不一定就是我們想要輸出的電平。

(2)開(kāi)漏輸出
此時(shí)的IO上的P-MOS管不工作,只有N-MOS管工作。當(dāng)我們輸出設(shè)置"0"時(shí),N-MOS管打開(kāi),P-MOS管關(guān)閉,輸出低電平。當(dāng)我們輸出設(shè)置"1"時(shí),P-MOS管關(guān)閉,N-MOS管關(guān)閉,此時(shí)的電平狀態(tài)由外部決定。此模式只可輸出強(qiáng)低電平,想輸出高電平只能夠靠外部提供。
此時(shí)施密特觸發(fā)器時(shí)開(kāi)啟的,我們也可以讀取輸出數(shù)據(jù)寄存器的值,可以看是否設(shè)置正確,不過(guò)這很少用。同時(shí)我們也可以通過(guò)輸入數(shù)據(jù)寄存器來(lái)讀取電平狀態(tài),注意!我們的IO電平不一定就是我們想要輸出的電平。

(3)模擬輸出
此模式下的IO,將不再是設(shè)置電平狀態(tài),是設(shè)置IO口的電壓值。最終會(huì)輸出到外部使用。通常使用到DAC外設(shè),用來(lái)設(shè)置模擬電壓的。例如,設(shè)置電壓到電壓控制器件工作。

(4)復(fù)用輸出
此模式下的IO,會(huì)復(fù)用到單片機(jī)的其他外設(shè),輸出數(shù)據(jù)寄存器無(wú)法使用。輸出的電平狀態(tài)將會(huì)由外設(shè)控制。復(fù)用推挽輸出和復(fù)用開(kāi)漏輸出在此方面功能相同。
同時(shí)我們也可以通過(guò)輸入數(shù)據(jù)寄存器來(lái)讀取電平狀態(tài),注意!我們的IO電平不一定就是我們想要輸出的電平。

四、GPIO的寄存器介紹
這里會(huì)拿配置IO的基本輸入輸出來(lái)介紹寄存器。我的開(kāi)發(fā)板上的LED燈連接到PB0,按鍵連接到了PA0。前面介紹了不同的輸入輸出模式的區(qū)別,所以PB0需要配置成輸出,PA0需要配置成輸入。
1、端口模式寄存器

在每個(gè)位的介紹里,并沒(méi)有看到具體的輸入輸出介紹,所以PB0配置為通用輸出模式(01),PA0配置成輸入模式(00)。
//PB0的模式配置
GPIOB->MODER?&= ~(0x03 << 0);? ? //先對(duì)需要配置的為作清零
GPIOB->MODER?|= (0x01 << 0);
//按鍵1的模式配置
GPIOA->MODER?&= ~(0x03 << 0);? ? //先對(duì)需要配置的為作清零
GPIOA->MODER?|= (0x00 << 0);
2、端口輸出類型寄存器

只有PB0是配置為輸出,所以PA0不需要配置此寄存器。因?yàn)槭球?qū)動(dòng)LED燈亮,所以需要配置為推挽輸出(0),使用開(kāi)漏輸出只有強(qiáng)低。
//PB0的輸出類型配置
GPIOB->OTYPER?&= ~(0x01 << 0);? ? //先對(duì)需要配置的為作清零
GPIOB->OTYPER?|= (0x00 << 0);
3、端口輸出速度寄存器

只有PB0是配置為輸出,所以PA0不需要配置此寄存器。速度多少都行,這里沒(méi)有什么講究,我設(shè)置為超高速。
//PB0的輸出速度配置
GPIOB->OSPEEDR?&= ~(0x03 << 0);? ? //先對(duì)需要配置的為作清零
GPIOB->OSPEEDR?|= (0x03 << 0);
4、端口上拉/下拉寄存器

PB0是做強(qiáng)高或強(qiáng)低輸出的,沒(méi)有必要做上拉下拉處理。PA0的外接了下拉電阻,所以這里也沒(méi)必要做上下拉處理。
//PB0的上下拉配置
GPIOB->PUPDR?&= ~(0x03 << 0);? ? //先對(duì)需要配置的為作清零
GPIOB->PUPDR?|= (0x00 << 0);
//PA0的上下拉配置
GPIOA->PUPDR?&= ~(0x03 << 0);? ? //先對(duì)需要配置的為作清零
GPIOA->PUPDR?|= (0x00 << 0);
5、端口輸入數(shù)據(jù)寄存器

這里會(huì)在獲取按鍵引腳狀態(tài)的時(shí)候使用到,我使用了宏定義來(lái)代替這操作。
#define KEY1_STATE?GPIOA->IDR & (0x01?<<?0)
6、端口輸出數(shù)據(jù)寄存器

此寄存器在控制LED的輸出操作時(shí)使用,統(tǒng)一寫(xiě)成宏定義的寫(xiě)法。我的開(kāi)發(fā)板LED是低電平點(diǎn)亮,所以將第0位置1熄滅LED,置0點(diǎn)亮LED
#define?LED_ON??GPIOB->ODR?&=?~(0x01?<<?0);
#define?LED_OFF?GPIOB->ODR?|=?(0x01?<<?0);
7、端口復(fù)位/置位寄存器

這個(gè)寄存器的功能和輸出寄存器的差不多,就是操作有點(diǎn)差別。在0-15位置1,就會(huì)把輸出寄存器的對(duì)應(yīng)位置1。在16-31位置一,就會(huì)把輸出寄存器的對(duì)應(yīng)位置0,就是16位對(duì)應(yīng)0位,31位對(duì)應(yīng)15位。
#define?LED_ON??GPIOB->BSRR?|=?(0x01?<<?16);
#define?LED_OFF?GPIOB->BSRR?|=?(0x01?<<?0);
8、端口配置鎖定寄存器

此寄存器較為少用,?簡(jiǎn)要來(lái)說(shuō),就是用來(lái)鎖定GPIO的配置的,需要按照上面的解鎖方式對(duì)第16位操作,將GPIO進(jìn)行解鎖。然后給16位置0,再給你想要鎖定的端口置1即可。有興趣可以去研究研究。
9、復(fù)用功能寄存器

這個(gè)寄存器的作用,是引腳用于外設(shè)時(shí)使用的。可以將引腳復(fù)用到其他的外設(shè),其中的AFx就是想要復(fù)用的外設(shè),一個(gè)引腳可能有好幾種外設(shè)可以復(fù)用。后面寫(xiě)到其他外設(shè)的時(shí)候會(huì)使用這個(gè)寄存器,所以這里不多表述。
五、GPIO的配置方法
1、寄存器配置
//GPIOA和GPIOB的時(shí)鐘開(kāi)啟
RCC->AHB4ENR?|= (0x03 << 0);
//PB0的模式配置
GPIOB->MODER?&= ~(0x03 << 0);
GPIOB->MODER?|= (0x01 << 0);
//PB0的輸出模式配置
GPIOB->OTYPER?&= ~(0x01 << 0);
GPIOB->OTYPER?|= (0x00 << 0);
//PB0的輸出速度配置
GPIOB->OSPEEDR?&= ~(0x03 << 0);
GPIOB->OSPEEDR?|= (0x03 << 0);
//PB0的上下拉配置
GPIOB->PUPDR?&= ~(0x03 << 0);
GPIOB->PUPDR?|= (0x00 << 0);
//PA0的模式配置
GPIOA->MODER?&= ~(0x03 << 0);
GPIOA->MODER?|= (0x00 << 0);
//PA0的上下拉配置
GPIOA->PUPDR?&= ~(0x03 << 0);
GPIOA->PUPDR?|= (0x00 << 0);
2、HAL庫(kù)配置
1、打開(kāi)STM32CubeMX,點(diǎn)擊這里

2、搜索到自己的芯片信號(hào)后,雙擊點(diǎn)進(jìn)去

3、這就是默認(rèn)的界面

4、選擇使用的引腳和需要配置的類型

5、選擇好之后,點(diǎn)擊右邊的這部分,進(jìn)行引腳的具體配置。

6、配置系統(tǒng)時(shí)鐘,這里我使用的內(nèi)部高速時(shí)鐘,直接在這里輸入64,然后一直點(diǎn)擊確定,然后就會(huì)自動(dòng)幫忙配置好。

7、按下面的步驟,選擇好項(xiàng)目名稱和地址。

8、這里會(huì)創(chuàng)建一個(gè)文件夾,是專門(mén)做外設(shè)的初始化的,我比較建議勾上。

9、點(diǎn)擊生成代碼,然后就配置好了。

10、這里就是我們使用STM32CubeMX配置的GPIO方式,在MX_GPIO_Init函數(shù)里面,就是具體的配置操作,這里的操作和標(biāo)準(zhǔn)庫(kù)的很相似。

六、總結(jié)
此篇對(duì)STM的GPIO外設(shè)進(jìn)行了講解,介紹了GPIO的基本結(jié)構(gòu),不同的輸入輸出模式,以及寄存器的介紹。學(xué)到這里,應(yīng)該就能做出,通過(guò)按鍵控制LED燈的亮滅這種操作了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-757715.html
HAL庫(kù)的操作介紹比較簡(jiǎn)單,基本上只要學(xué)習(xí)了標(biāo)準(zhǔn)庫(kù)就會(huì)HAL庫(kù)了,而學(xué)了寄存器后,就能大致看懂庫(kù)函數(shù)里面都做了什么,因?yàn)閹?kù)函數(shù)的本質(zhì)也就是操作寄存器。庫(kù)函數(shù)的操作呢,多玩玩基本上就熟悉了,大部分的功能都有函數(shù)實(shí)現(xiàn),除非想要做出想要的邏輯操作,所以就不再過(guò)多的介紹庫(kù)函數(shù)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-757715.html
到了這里,關(guān)于STM32的GPIO操作(寄存器&HAL)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!