(二)STM32學習之GPIO
1、GPIO簡介
GPIO 是通用輸入輸出端口的簡稱,簡單來說就是STM32 可控制的引腳,STM32 晶片的GPIO 引腳與外部裝置連接配接起來,進而實作與外部通訊、控制以及資料采集的功能。STM32 晶片的GPIO 被分成很多組,每組有16 個引腳,所有的GPIO 引腳都有基本的輸入輸出功能。
2、GPIO框圖剖析

大緻可分為七個子產品,由箭頭走向可知曉GPIO 引腳線路經過兩個保護二極管後,向上流向“輸入模式”結構,向下流向“輸出模式”結構。
(1)保護電路
VDD為3.3V,VSS為公共接地端,當外部輸入電壓大于3.3V時,上面的二極管導通,保護内部晶片。如果輸入為負電壓,則下面的二極管導通,電流往外面流,保護内部晶片。當輸入電壓過大也将會燒毀晶片,切記不可用GPIO直接連接配接電動機,電動機具有較大得反向電動勢,且積分時間短。
(2)普通輸出控制
推挽輸出:
所謂的推挽輸出模式,是根據這兩個MOS 管的工作方式來命名的。在該結構中輸入高電平時,經過反向後,上方的P-MOS 導通,下方的N-MOS 關閉,對外輸出高電平,電流往外流,形似往外推;而在該結構中輸入低電平時,經過反向後,N-MOS管導通,P-MOS關閉,對外輸出低電平,電流往裡面流,則為挽留。當引腳高低電平切換時,兩個管子輪流導通,P管負責灌電流,N管負責拉電流,使其負載能力和開關速度都比普通的方式有很大的提高。推挽輸出的低電平為0 伏,高電平為3.3 伏,具體參考圖 8-2,它是推挽輸出模式時的等效電路。
總結:
1、可以輸出高低電平,用于連接配接數字器件,高電平由VDD決定,低電平由VSS決定。
2、推挽結構指兩個三極管受兩路互補的信号控制,總是在一個導通的時候另外一個截止,優點開關效率效率高,電流大,驅動能力強。
3、輸出高電平時,電流輸出到負載,叫灌電流,可以了解成推,輸出低電平時,負載電流流向晶片,叫拉電流,即挽。
開漏輸出:
在開漏輸出模式時,上方的P-MOS 管完全不工作,則可看作是不經過P-MOS管。如果我們控制輸出為0,經過反向後,則N-MOS 管導通,使輸出接地,若控制輸出為1,經過反向後,N-MOS 管關閉,是以引腳既不輸出高電平,也不輸出低電平,為高阻态。為了能正常輸出高低電平,使用時必須外部接入上拉電阻,即開漏輸出高電平時,電壓為上拉電源電壓,參考圖 8-3 中等效電路。
開漏輸出具有“線與”特性,也就是說,若有很多個開漏模式引腳連接配接到一起時,隻有當所有引腳都輸出高阻态,才由上拉電阻提供高電平,此高電平的電壓為外部上拉電阻所接的電源的電壓。若其中一個引腳為低電平,那線路就相當于短路接地,使得整條線路都為低電平,即0 伏。
推挽輸出模式一般應用在輸出電平為0 和3.3 伏而且需要高速切換開關狀态的場合。在STM32 的應用中,除了必須用開漏模式的場合,我們都習慣使用推挽輸出模式。
開漏輸出一般應用在I2C、SMBUS 通訊等需要“線與”功能的總線電路中。除此之外,還用在電平不比對的場合,如需要輸出5 伏的高電平,就可以在外部接一個上拉電阻,上拉電源為5 伏,并且把GPIO設定為開漏模式,當輸出高阻态時,由上拉電阻和電源向外輸出5 伏的電平。
總結:
1、隻能輸出低電平,不能輸出高電平。
2、如果要輸出高電平,則需要外接上拉。
3、開漏輸出具有“線與”功能,一個為低,全部為低,多用于I2C和SMBUS總線。
(3)輸出資料寄存器(OutputDataRegister -> ODR )
前面的雙MOS管結構電路的輸入信号,是由GPIO“輸出資料寄存器GPIOx_ODR”提供的,是以我們通過修改輸出資料寄存器GPIOx_ODR的值就可以修改GPIO 引腳的輸出電平。而“置位/複位寄存器GPIOx_BSRR”可以通過修改輸出資料寄存器GPIOx_ODR的值進而影響電路的輸出。
(4)複用功能輸出
“複用功能輸出”中的“複用”是指STM32 的其它片上外設對GPIO 引腳進行控制,此時GPIO 引腳用作該外設功能的一部分,算是第二用途。從其它外設引出來的“複用功能輸出信号”與GPIO 本身的資料據寄存器都連接配接到雙MOS 管結構的輸入中,通過圖中的梯形結構作為開關切換選擇。
例如我們使用USART 序列槽通訊時,需要用到某個GPIO 引腳作為通訊發送引腳,這個時候就可以把該GPIO 引腳配置成USART 序列槽複用功能,由序列槽外設控制該引腳,發送資料。
(5)輸入資料寄存器 ( InputDataRegister -> IDR )
看GPIO 結構框圖的上半部分,GPIO 引腳經過内部的上、下拉電阻,可以配置成上/下拉輸入,然後再連接配接到施密特觸發器(即圖中TTL肖特基觸發器),信号經過觸發器後,模拟信号轉化為0、1 的數字信号,然後存儲在“輸入資料寄存器GPIOx_IDR”中,通過讀取該寄存器就可以了解GPIO引腳的電平狀态。
(6)複用功能輸入
與“複用功能輸出”模式類似,在“複用功能輸入模式”時,GPIO 引腳的信号傳輸到
STM32 其它片上外設,由該外設讀取引腳狀态。
同樣,如我們使用USART 序列槽通訊時,需要用到某個GPIO 引腳作為通訊接收引腳,這個時候就可以把該GPIO 引腳配置成USART 序列槽複用功能,使USART 可以通過該通訊引腳的接收遠端資料。
(7)模拟輸入輸出
當GPIO 引腳用于ADC 采集電壓的輸入通道時,用作“模拟輸入”功能,此時信号是
不經過施密特觸發器的,因為經過施密特觸發器後信号隻有0、1 兩種狀态,而ADC 外設要采集到原始的模拟信号,信号源輸入必須在施密特觸發器之前。類似地,當GPIO 引腳用于DAC 作為模拟電壓輸出通道時,此時作為“模拟輸出”功能,DAC 的模拟信号輸出就不經過雙MOS 管結構,模拟信号直接輸出到引腳。
3、GPIO八種工作模式
typedef enum
{
GPIO_Mode_AIN = 0x0, /*模拟輸入 */
GPIO_Mode_IN_FLOATING = 0x04, /*輸入浮空 */
GPIO_Mode_IPD = 0x28, /*輸入下拉 */
GPIO_Mode_IPU = 0x48, /*輸入上拉 */
GPIO_Mode_Out_OD = 0x14, /*開漏輸出 */
GPIO_Mode_Out_PP = 0x10, /*推挽式輸出 */
GPIO_Mode_AF_OD = 0x1C, /*開漏複用 輸出 */
GPIO_Mode_AF_PP = 0x18 /* 推挽式複用 輸出 */
}GPIOMode_TypeDef;
(1). 輸入模式(模拟/浮空/上拉/下拉)
在輸入模式時,施密特觸發器打開,輸出被禁止,可通過輸入資料寄存器GPIOx_IDR讀取I/O 狀态。其中輸入模式,可設定為上拉、下拉、浮空和模拟輸入四種。上拉和下拉輸入很好了解,預設的電平由上拉或者下拉決定。浮空輸入的電平是不确定的,完全由外部的輸入決定,一般接按鍵的時候用的是這個模式。模拟輸入則用于ADC 采集。
(2). 輸出模式(推挽/開漏)
在輸出模式中,推挽模式時雙MOS 管以輪流方式工作,輸出資料寄存器GPIOx_ODR可控制I/O 輸出高低電平。開漏模式時,隻有N-MOS 管工作,輸出資料寄存器可控制I/O輸出高阻态或低電平。輸出速度可配置,有2MHz\10MHz\50MHz 的選項。此處的輸出速度即I/O 支援的高低電平狀态最高切換頻率,支援的頻率越高,功耗越大,如果功耗要求不嚴格,把速度設定成最大即可。在輸出模式時施密特觸發器是打開的,即輸入可用,通過輸入資料寄存器GPIOx_IDR可讀取I/O 的實際狀态。
(3). 複用功能(推挽/開漏)
複用功能模式中,輸出使能,輸出速度可配置,可工作在開漏及推挽模式,但是輸出信号源于其它外設,輸出資料寄存器GPIOx_ODR 無效;輸入可用,通過輸入資料寄存器可擷取I/O 實際狀态,但一般直接用外設的寄存器來擷取該資料信号。通過對GPIO 寄存器寫入不同的參數,就可以改變GPIO 的工作模式,再強調一下,要了解具體寄存器時一定要查閱《STM32F10X-中文參考手冊》中對應外設的寄存器說明。在GPIO 外設中,控制端口高低控制寄存器CRH 和CRL 可以配置每個GPIO 的工作模式和工作的速度,每4 個位控制一個IO,CRH 控制端口的高八位,CRL 控制端口的低8 位,具體的看CRH 和CRL 的寄存器描述。
4、GPIO寄存器
每組IO口含下面7個寄存器。也就是7個寄存器,一共可以控制一組GPIO的16個IO口。
GPIOx->CRL: 端口配置低寄存器
GPIOx->CRH: 端口配置高寄存器
GPIOx->IDR: 端口輸入寄存器
GPIOx->ODR: 端口輸出寄存器
GPIOx->BSRR: 端口位設定/清除寄存器
GPIOx->BRR : 端口位清除寄存器
GPIOx->LCKR: 端口配置鎖存寄存器
5、固件庫操作GPIO代碼示例
//相關宏定義
#define LED_G_GPIO_PIN GPIO_Pin_5//綠燈
#define LED_R_GPIO_PIN GPIO_Pin_6//紅燈
#define LED_B_GPIO_PIN GPIO_Pin_1//藍燈
#define LED_GPIO_PORT GPIOE//選中GPIOB口
#define LED_GPIO_CLK RCC_APB2Periph_GPIOE//打開B口時鐘
/***************具體函數***************/
void LED_GPIO_Config(void) //配置GPIO
{
GPIO_InitTypeDef GPIO_InitStruct;//定義結構體
RCC_APB2PeriphClockCmd(LED_GPIO_CLK, ENABLE);//開時鐘
GPIO_InitStruct.GPIO_Pin = LED_G_GPIO_PIN |LED_R_GPIO_PIN | LED_B_GPIO_PIN;//利用宏定義管理GPIO口
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;//選擇模式
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(LED_GPIO_PORT, &GPIO_InitStruct);
}
void LED_GPIO_Init(void)//GPIO初始化函數
{
GPIO_SetBits(LED_GPIO_PORT, LED_R_GPIO_PIN);//将三個燈全部關閉,燈為負邏輯,低電平亮燈
GPIO_SetBits(LED_GPIO_PORT, LED_G_GPIO_PIN);
GPIO_SetBits(LED_GPIO_PORT, LED_B_GPIO_PIN);
}
此部落格僅用于自身學習,存放,歸納筆記使用 Arelir 要好好學習哦!