一、GPIO簡(jiǎn)介
GPIO作為通用輸入輸出端口,其全稱為General Purpose Input Output,能夠通過(guò)軟件自由配置引腳狀態(tài)及工作模式。除通用輸入輸出功能外,部分GPIO端口還可被用作第二功能的配置,即為復(fù)用功能。
每個(gè)通用I/O端口都可以通過(guò)軟件自由配置為4種輸入模式與4種輸出模式。
輸入模式
通過(guò)配置GPIOx_CRL寄存器或GPIOx_CRH寄存器中的MODEx[1:0]為00,即配置為輸入模式,配置寄存器中的CNFx[1:0]選擇工作模式(MM32F0140 的GPIOx中“x”的范圍為A到D)。
圖1. 輸入浮空/上拉輸入/下拉輸入/模擬輸入配置
輸入浮空:
浮空就是輸入引腳即不接高電平也不接低電平,如圖1所示,I/O端口的數(shù)據(jù)在每個(gè)AHB時(shí)鐘被采樣到輸入數(shù)據(jù)寄存器,通過(guò)讀訪問(wèn)輸入數(shù)據(jù)寄存器獲取當(dāng)前I/O狀態(tài),輸入浮空常用于復(fù)用功能。
上拉輸入:
電阻與VDD相連,形成上拉電阻,I/O端口在空閑時(shí)為高電平,能夠用于檢測(cè)由高到低的電平變化,常用于按鍵檢測(cè)。
下拉輸入:
電阻與VSS相連,形成下拉電阻,I/O端口在空閑時(shí)為低電平,能夠用于檢測(cè)由低到高的電平變化。
模擬輸入:
模擬輸入是模擬信號(hào)的輸入,在模擬輸入模式下,上拉電阻、下拉電阻及斯密特觸發(fā)器均被禁止。
輸出模式
通過(guò)配置GPIOx_CRL寄存器或GPIOx_CRH寄存器中的CNFx[1:0]選擇輸出模式,配置GPIOx_CRL中的MODEx[1:0]選擇輸出速度(MODEx[1:0]不為00)。當(dāng)I/O端口使用復(fù)用輸出功能時(shí),端口必須配置為復(fù)用功能輸出模式(推挽或開(kāi)漏),輸出配置如圖2所示。
圖2. 輸出配置
開(kāi)漏輸出:
在開(kāi)漏輸出模式中,輸出控制寄存器配置為0時(shí),數(shù)據(jù)經(jīng)過(guò)輸出控制模塊,MOS管的柵極接收到高電平,MOS管導(dǎo)通,此時(shí)I/O端口接通在GND上,即對(duì)應(yīng)引腳輸出低電平;當(dāng)輸出控制寄存器配置為1,數(shù)據(jù)經(jīng)過(guò)控制模塊,給予MOS管的柵極一個(gè)低電平,此時(shí)MOS管不導(dǎo)通,對(duì)應(yīng)的管腳處于高阻態(tài)。因此,開(kāi)漏輸出通常輸出低電平,若要輸出高電平則需外加上拉電阻。
推挽輸出:
推挽輸出一般指兩個(gè)MOS管分別受兩個(gè)互補(bǔ)信號(hào)的控制,總是在一個(gè)MOS管導(dǎo)通時(shí)另一個(gè)MOS管截止。當(dāng)輸出控制寄存器配置為0時(shí),數(shù)據(jù)經(jīng)過(guò)輸出控制模塊,MOS管的柵極接收到高電平,N-MOS管導(dǎo)通,P-MOS管不導(dǎo)通,此時(shí)I/O端口接通在VSS上,即對(duì)應(yīng)引腳輸出為低電平;當(dāng)輸出控制寄存器配置為1時(shí),數(shù)據(jù)經(jīng)過(guò)輸出控制模塊,MOS管的柵極接收到低電平,P-MOS管導(dǎo)通,N-MOS管不導(dǎo)通,此時(shí)I/O端口接通在VDD上,即對(duì)應(yīng)引腳輸出為高電平。因此,推挽輸出可以輸出高低電平。
圖3. 復(fù)用功能配置
復(fù)用開(kāi)漏輸出:
配置GPIOx_AFRH與GPIOx_AFRL寄存器的AFRLx[3:0]與AFRHx[3:0]選擇復(fù)用功能。當(dāng)GPIO被作為第二功能使用時(shí),模式配置為復(fù)用模式,復(fù)用功能配置如圖3所示。以圖4為例,若要配置PB10引腳作為I2C_SCL,則在配置GPIO模式時(shí)要選擇復(fù)用模式。通過(guò)片上外設(shè)復(fù)用功能,使用MOS管實(shí)現(xiàn)輸出。通常I2C使用GPIO的復(fù)用功能時(shí)會(huì)使用復(fù)用開(kāi)漏輸出模式,由于I2C的一個(gè)主設(shè)備可掛載多個(gè)從設(shè)備,若不使用復(fù)用開(kāi)漏輸出,而使用復(fù)用推挽輸出,數(shù)據(jù)傳輸時(shí),兩個(gè)從設(shè)備一個(gè)拉高,一個(gè)拉低,可能會(huì)造成短路。因此I2C大多使用GPIO的復(fù)用開(kāi)漏輸出模式。
圖4. MM32F0140部分引腳復(fù)用功能
復(fù)用推挽輸出:
當(dāng)GPIO被作為第二功能配置使用時(shí),模式需配置為復(fù)用模式,通過(guò)配置GPIO_AFRH與GPIOx_AFRL寄存器的AFRLx[3:0]與AFRHx[3:0]選擇復(fù)用功能,通過(guò)片上外設(shè)復(fù)用功能,使用兩個(gè)MOS管來(lái)實(shí)現(xiàn)輸出。與推挽輸出不同,復(fù)用推挽輸出模式下端口的I/O操作由對(duì)應(yīng)復(fù)用的功能模塊控制,而推挽輸出模式下控制I/O端口需對(duì)GPIO內(nèi)部的寄存器進(jìn)行操作。
二、配置GPIO
首先,使能對(duì)應(yīng)I/O口的時(shí)鐘,根據(jù)所使用的外設(shè)對(duì)RCC的RCC_AHBENR寄存器進(jìn)行賦值,將對(duì)應(yīng)外設(shè)位置1即可使能時(shí)鐘,詳細(xì)外設(shè)如圖5所示。
圖5. MM32F0140 AHB外設(shè)
其次,配置所需的GPIO引腳、速度及工作模式。端口0到端口7使用GPIOx_CRL寄存器配置工作模式與速度,該寄存器中MODEx[1:0]位表示端口輸入輸出速度,CNFx[1:0]位表示端口工作模式(”MODEx”與”CNFx”的”x”表示指定端口號(hào))。若配置GPIOx_CRL寄存器中的MODEx位等于00則端口為輸入模式,此時(shí)CNFx位有四種配置方式,分別為:00(模擬輸入模式),01(浮空輸入模式),10(上拉/下拉輸入模式);若MODEx位不為00,則對(duì)應(yīng)端口為輸出模式,此時(shí)CNFx具有四種配置方式:00(推挽輸出模式),01(開(kāi)漏輸出模式),10(推挽復(fù)用模式),11(開(kāi)漏復(fù)用模式)。端口8到端口15的配置使用GPIOx_CRH寄存器配置指定端口的工作模式與速度,詳細(xì)配置方式與CPIOx_CRL寄存器相同。
若使用端口復(fù)用功能,需對(duì)GPIOx_AFRL(端口復(fù)用功能低位)寄存器與GPIOx_AFRH(端口復(fù)用功能高位)寄存器進(jìn)行配置。端口號(hào)為0到7則使用GPIOx_AFRL寄存器,端口號(hào)為8到15則使用GPIOx_AFRH寄存器,根據(jù)端口號(hào)與復(fù)用功能表進(jìn)行配置,例如若使用PA0引腳作為I2C1_SCL,則需將GPIOx_AFRL寄存器中AF3的對(duì)應(yīng)位置1(GPIO的工作模式也要配置為復(fù)用模式),PA端口的復(fù)用功能表如圖6所示。
圖6 MM32F0140 PA端口復(fù)用功能表
三、實(shí)驗(yàn)
本實(shí)驗(yàn)通過(guò)使用GPIO獲取按鍵狀態(tài)控制LED亮滅,讀取指定GPIO端口引腳的輸入數(shù)據(jù)(讀GPIOx_IDR寄存器)來(lái)獲取當(dāng)前的按鍵狀態(tài),通過(guò)對(duì)端口設(shè)置/清除寄存器(GPIOx_BSRR寄存器)與端口位清除寄存器(GPIOx_BRR寄存器)的對(duì)應(yīng)端口賦值,使對(duì)應(yīng)的LED亮滅。具體實(shí)驗(yàn)內(nèi)容為配置PB3引腳對(duì)應(yīng)LED2, PB4引腳對(duì)應(yīng)LED3,PB2引腳對(duì)應(yīng)的K2(如圖7所示),若K2按下,則K2對(duì)應(yīng)的端口輸入低電平,設(shè)置實(shí)驗(yàn)現(xiàn)象為L(zhǎng)ED2滅、LED3亮,K2處于非按下時(shí),K2對(duì)應(yīng)的端口輸入高電平,設(shè)置實(shí)驗(yàn)現(xiàn)象為L(zhǎng)ED2亮、LED3滅。
圖7 引腳配置原理圖
外設(shè)時(shí)鐘初始化
GPIO在AHB線上,實(shí)驗(yàn)使用引腳均為GPIOB組的引腳,因此對(duì)RCC_AHBENR寄存器的GPIOB對(duì)應(yīng)位置1。
RCC->AHB1ENR |= (1u << 18u);
按鍵初始化
實(shí)驗(yàn)使用引腳為PB2的K2按鍵,按鍵原理圖如圖8所示,若K2按鍵按下則與GND導(dǎo)通,因此在初始化按鍵時(shí)需配置該端口的工作模式為上拉輸入。
圖8. 按鍵原理圖
GPIOx_CRL寄存器為端口配置低寄存器,用于配置指定端口的速度與工作模式;GPIOx_BSRR寄存器用于設(shè)置/清除對(duì)應(yīng)端口,該寄存器低16位的對(duì)應(yīng)端口位置1會(huì)產(chǎn)生高電平。由圖9所示,K2所使用的端口2為GPIOx_CRL寄存器內(nèi)第8~11位。
圖9.端口配置低寄存器的比特位
//對(duì)應(yīng)端口的配置涉及到4位,后兩位配置端口輸入輸出速度,前兩位配置工作模式;清零端口2的配置位 GPIOB->CRL = ~(0xf << 8u); //速度配置位為0,端口為輸入模式,上拉輸入的工作模式位為10,因此使用0x08. GPIOB->CRL |= (0x08 << 8u); //配置PB2引腳為高電平 GPIOB->BSRR |= (1u << 2u);
LED初始化
實(shí)驗(yàn)使用PB3、PB4,引腳,為觀察LED的高低電平,在配置工作模式時(shí)使用可以輸出高低電平的推挽輸出。因?yàn)镻B3與PB4對(duì)應(yīng)端口在端口0~7中,所以使用GPIOx_CRL寄存器對(duì)LED進(jìn)行初始化配置(若使用端口為8~15則使用GPIOx_CRH寄存器)。
如圖9所示,端口3為GPIOx_CRL寄存器內(nèi)第12~15位,端口4為GPIOx_CRL寄存器內(nèi)第16~19位。由于LED為低電平點(diǎn)亮,設(shè)置GPIOx_BSRR寄存器中LED2與LED3的對(duì)應(yīng)位置1使LED初始狀態(tài)為滅。
//復(fù)位將要使用的端口3與端口4的配置位 GPIOB->CRL = ~( (0xf << 12u) | (0xf << 16u) ); //端口輸入輸出速度配置位不為00時(shí),端口為輸出模式,配置最大速度為50MHz,推挽輸出模式的配置為00. GPIOB->CRL |= ( (0x01 << 12u) | (0x01 << 16u) ); //PB3對(duì)應(yīng)的LED2初始化狀態(tài)為滅 GPIOB->BSRR = (1u << 3u); //PB4對(duì)應(yīng)的LED3初始化狀態(tài)為滅 GPIOB->BSRR = (1u << 4u);
按鍵掃描
讀GPIOx_IDR寄存器獲取對(duì)應(yīng)端口輸入數(shù)據(jù),本實(shí)驗(yàn)中K2配置為上拉輸入,即按鍵未按下時(shí)為高電平,按下按鍵后,K2對(duì)應(yīng)端口輸入為低電平。若GPIOx_BSRR寄存器的低16位的對(duì)應(yīng)端口位置1,則該端口為高電平;若GPIOx_BRR寄存器的對(duì)應(yīng)端口位置1,則該端口為低電平。實(shí)驗(yàn)設(shè)置按鍵未按下時(shí),LED2(PB3)亮、LED3(PB4)滅;按下按鍵時(shí)LED2滅、LED3亮。
while(1) { //K2的引腳為PB2, 1u<<2u = 0100u,將PB2的對(duì)應(yīng)位置1,若讀出GPIOx_IDR的對(duì)應(yīng)端口數(shù)據(jù)為高電平則按鍵未按下 if ( 0u != ( GPIOB->IDR (1u << 2u) ) ) { //PB4引腳對(duì)應(yīng)的LED3滅 GPIOB->BSRR = (1u << 4u); //PB3引腳對(duì)應(yīng)的LED2亮 GPIOB->BRR = (1u << 3u); } else //K2 按鍵按下 { //PB4引腳對(duì)應(yīng)的LED3亮 GPIOB->BRR =(1u << 4u); //PB3引腳對(duì)應(yīng)的LED2滅 GPIOB->BSRR = (1u << 3u); } }
Main()函數(shù)
綜合上述寄存器配置到main函數(shù)中,圖10為實(shí)驗(yàn)效果。
int main(void) { //GPIOB時(shí)鐘初始化 RCC->AHB1ENR |= (1u << 18u); //清零端口2的配置位 GPIOB->CRL = ~(0xfu << 8u); //端口2配置為上拉輸入 GPIOB->CRL |= (0x08u << 8u); //端口2配置為高電平 GPIOB->BSRR |= (1u << 2u); //端口3與端口4配置位清零 GPIOB->CRL = ~( (0xf << 12u) | (0xf << 16u) ); //端口3與端口4配置為推挽輸出,速度最大為50MHz GPIOB->CRL |= ( (0x01 << 12u) | (0x01 << 16u) ); //PB3對(duì)應(yīng)的LED2初始化狀態(tài)為滅 GPIOB->BSRR = (1u << 3u); //PB4對(duì)應(yīng)的LED3初始化狀態(tài)為滅 GPIOB->BSRR = (1u << 4u); while(1) { //K2的引腳為PB2, 1u << 2u = 0100u,將PB2的對(duì)應(yīng)位置1,若讀出GPIOx_IDR的對(duì)應(yīng)端口數(shù)據(jù)為高電平則按鍵未按下 if ( 0u != ( GPIOB->IDR (1u << 2u) ) ) { // PB4引腳對(duì)應(yīng)的LED3滅 GPIOB->BSRR = (1u << 4u); //PB3引腳對(duì)應(yīng)的LED2亮 GPIOB->BRR = (1u << 3u); } else //按下按鍵K2 { // PB4引腳對(duì)應(yīng)的LED3亮 GPIOB->BRR = (1u << 4u); // PB3引腳對(duì)應(yīng)的LED2滅 GPIOB->BSRR = (1u << 3u); } } }
圖9.實(shí)驗(yàn)效果
來(lái)源:靈動(dòng)MM32MCU
-
寄存器
+關(guān)注
關(guān)注
31文章
5434瀏覽量
124513 -
端口
+關(guān)注
關(guān)注
4文章
1046瀏覽量
32949 -
GPIO
+關(guān)注
關(guān)注
16文章
1280瀏覽量
54108
發(fā)布評(píng)論請(qǐng)先 登錄
評(píng)論