CKS32F4xx系列產(chǎn)品GPIO口配置
GPIO(General-purpose input/output)是通用輸入輸出端口的簡(jiǎn)稱(chēng),CKS32F4xx系列產(chǎn)品通過(guò)GPIO引腳與外部設(shè)備連接起來(lái),從而實(shí)現(xiàn)與外部通訊、控制以及數(shù)據(jù)采集的功能。最基本的輸出功能是由CKS32F4xx系列產(chǎn)品控制引腳輸出高、低電平,實(shí)現(xiàn)開(kāi)關(guān)控制,如把GPIO引腳接入到LED燈,那就可以控制LED燈的亮滅,引腳接入到繼電器或三極管,那就可以通過(guò)繼電器或三極管控制外部大功率電路的通斷。最基本的輸入功能是檢測(cè)外部輸入電平,如把 GPIO引腳連接到按鍵,通過(guò)電平高低區(qū)分按鍵是否被按下。
GPIO硬件結(jié)構(gòu)框圖
該圖從最右端看起,最右端標(biāo)注著“I/O”的就是代表CKS32F4xx系列產(chǎn)品引出的GPIO引腳,其余部件都位于芯片內(nèi)部。引腳處的兩個(gè)保護(hù)二級(jí)管可以防止引腳外部過(guò)高或過(guò)低的電壓輸入,當(dāng)引腳電壓高于VDD_FT時(shí),上方的二極管導(dǎo)通,當(dāng)引腳電壓低于VSS時(shí),下方的二極管導(dǎo)通,由此可以防止不正常電壓引入芯片導(dǎo)致芯片的燒毀。這里要特別注意VDD_FT 代表IO口兼容3.3V和5V,如果沒(méi)有標(biāo)注“FT”,就代表著不兼容5V。在芯片數(shù)據(jù)手冊(cè)的引腳定義中,會(huì)看到有“電平I/O”一列,有FT標(biāo)注的即為支持5V,如下圖所示:
標(biāo)號(hào)1處是上拉、下拉電阻,從它的結(jié)構(gòu)我們可以看出,通過(guò)上、下拉對(duì)應(yīng)的開(kāi)關(guān)配置,我們可以控制引腳默認(rèn)狀態(tài)下的電壓,開(kāi)啟上拉的時(shí)候引腳電壓為高電平,開(kāi)啟下拉的時(shí)候引腳電壓為低電平。同時(shí)也可以設(shè)置“既不上拉也不下拉模式”,我們也把這種狀態(tài)稱(chēng)為浮空模式。
標(biāo)號(hào)2處是一個(gè)由P-MOS和N-MOS管組成的單元電路。這個(gè)結(jié)構(gòu)使GPIO具有了“推挽輸出”和“開(kāi)漏輸出”兩種模式。上方的P-MOS管高電平導(dǎo)通,低電平關(guān)閉,下方的N-MOS低電平導(dǎo)通,高電平關(guān)閉。
標(biāo)號(hào)3處是輸出數(shù)據(jù)寄存器,它為標(biāo)號(hào)2處的雙MOS管結(jié)構(gòu)電路提供輸入控制信號(hào),因此通過(guò)修改輸出數(shù)據(jù)寄存器的值就可以修改GPIO引腳的輸出電平。而圖中“置位/復(fù)位寄存器 GPIOx_BSRR”可以通過(guò)修改輸出數(shù)據(jù)寄存器的值從而影響電路的輸出。
標(biāo)號(hào)4處是復(fù)用功能輸出,“復(fù)用”是指CKS32F4xx系列產(chǎn)品的其它片上外設(shè)可以對(duì)GPIO引腳進(jìn)行控制,此時(shí)GPIO引腳用作該外設(shè)功能的一部分,算是第二用途。例如我們使用USART串口通訊時(shí),需要用到某個(gè)GPIO引腳作為通訊發(fā)送引腳,這個(gè)時(shí)候就可以把該GPIO引腳配置成USART串口復(fù)用功能,由串口外設(shè)控制該引腳,發(fā)送數(shù)據(jù)。
標(biāo)號(hào)5處是輸入數(shù)據(jù)寄存器,它連接到圖中的TTL施密特觸發(fā)器,觸發(fā)器的基本原理是當(dāng)輸入電壓高于正向閾值電壓時(shí),輸出為高;當(dāng)輸入電壓低于負(fù)向閾值電壓時(shí),輸出為低;IO口信號(hào)經(jīng)過(guò)觸發(fā)器后,模擬信號(hào)轉(zhuǎn)化為0和1的數(shù)字信號(hào),也就是高低電平,并且是TTL電平協(xié)議, 然后存儲(chǔ)在“輸入數(shù)據(jù)寄存器。因此,通過(guò)讀取該寄存器就可以了解GPIO引腳的電平狀態(tài)。
標(biāo)號(hào)6處是復(fù)用功能輸入,與“復(fù)用功能輸出”模式類(lèi)似,同樣,如果我們使用USART串口通訊時(shí),需要用到某個(gè)GPIO引腳作為通訊接收引腳,這個(gè)時(shí)候就可以把該GPIO引腳配置成USART串口復(fù)用功能,使USART可以通過(guò)該通訊引腳接收遠(yuǎn)端數(shù)據(jù)。
標(biāo)號(hào)7處是模擬輸入輸出,當(dāng) GPIO引腳用于ADC采集電壓的輸入通道時(shí),用作“模擬輸入”功能,此時(shí)信號(hào)是不經(jīng)過(guò)施密特觸發(fā)器的,因?yàn)榻?jīng)過(guò)施密特觸發(fā)器后信號(hào)只有0、1 兩種狀態(tài),所以ADC外設(shè)要采集到原始的模擬信號(hào),信號(hào)源輸入必須在施密特觸發(fā)器之前。同樣的,當(dāng) GPIO引腳用于DAC作為模擬電壓輸出通道時(shí),此時(shí)作為“模擬輸出”功能,DAC 的模擬信號(hào)輸出就不經(jīng)過(guò)雙MOS管結(jié)構(gòu)了,在GPIO結(jié)構(gòu)框圖的右下角處,模擬信號(hào)直接輸出到引腳。
?
?
GPIO的工作模式
- 4種輸入模式 -
1.浮空輸入
浮空輸入狀態(tài)下,IO的電平狀態(tài)是不確定的,完全由外部輸入決定。如果在該引腳懸空的情況下,讀取該端口的電平是不確定的。
2.上拉輸入
在該模式下,如果IO口外部沒(méi)有信號(hào)輸入或者引腳懸空,IO口默認(rèn)為高電平。如果I/O口輸入低電平,那么引腳就為低電平,MCU讀取到的就是低電平。
3.下拉輸入
在該模式下如果IO口外部沒(méi)有信號(hào)輸入或者引腳懸空,IO口默認(rèn)為低電平,如果I/O口輸入高電平,那么引腳就為高電平,MCU讀取到的就是高電平。
4.模擬功能
當(dāng)GPIO用于模擬功能時(shí),引腳的上、下拉電阻是不起作用的,這個(gè)時(shí)候即使配置了上拉或下拉模式,也不會(huì)影響到模擬信號(hào)的輸入輸出。除了ADC和DAC要將IO配置為模擬功能模式之外,其他外設(shè)功能一律要配置為復(fù)用功能模式。
- 4種輸出模式 -
1.開(kāi)漏輸出(帶上拉或者下拉)
在該模式下,若MCU控制輸出為高電平1時(shí),輸出指令是不會(huì)起到作用的。此時(shí)I/O端口的電平就不會(huì)由輸出的高電平?jīng)Q定,而是由I/O端口外部的上拉或者下拉決定,如果沒(méi)有上拉或者下拉,IO口就處于高阻態(tài)。雖然通過(guò)軟件設(shè)置內(nèi)部上拉,也可以輸出高電平,但是CKS32F4xx系列產(chǎn)品內(nèi)部上拉是"弱上拉",即通過(guò)此上拉輸出的電流是很弱的,驅(qū)動(dòng)能力很弱。但是在該模式下,當(dāng)MCU控制輸出為低電平0時(shí),即使沒(méi)有上拉或者下拉,I/O端口也會(huì)輸出低電平。另一方面,在開(kāi)漏模式下,施密特觸發(fā)器是打開(kāi)的,即輸入可用,可以通過(guò)輸入數(shù)據(jù)寄存器GPIOx_IDR讀取I/O的實(shí)際狀態(tài)。開(kāi)漏輸出主要有以下兩點(diǎn)作用:
a. I/O端口設(shè)置成開(kāi)漏輸出模式時(shí),可以用來(lái)連接不同電平的器件,用來(lái)匹配電平,因?yàn)殚_(kāi)漏引腳不連接外部的上拉電阻時(shí),只能輸出低電平,如果需要同時(shí)具備輸出高電平的功能,則需要接上拉電阻。因此我們通過(guò)改變上拉電源的電壓,便可以改變傳輸電平。比如通過(guò)加上上拉電阻就可以提供TTL電平-CMOS電平的輸出。
b.當(dāng)多個(gè)設(shè)置為開(kāi)漏輸出的引腳連接到一條總線上時(shí)。通過(guò)外加一個(gè)上拉電阻,在不增加任何器件的情況下,這些引腳形成了“與邏輯”關(guān)系,即“線與”。如果有一個(gè)引腳輸出為邏輯0,相當(dāng)于接地,那么與之并聯(lián)的回路“相當(dāng)于被一根導(dǎo)線短路”,所以總線上的邏輯電平便為0。只有都為高電平時(shí),總線上的電平才為1。在IIC通信中,引腳通常設(shè)置為開(kāi)漏輸出模式。
2.復(fù)用開(kāi)漏輸出(帶上拉或者下拉)
此時(shí)GPIO復(fù)用為其他外設(shè),輸出數(shù)據(jù)寄存器GPIOx_ODR無(wú)效;即輸出的高低電平來(lái)源于其它外設(shè),除了輸出信號(hào)的來(lái)源改變之外,其他的與開(kāi)漏輸出功能相同。 3.推挽輸出(帶上拉或者下拉)
在該模式下,如果我們控制輸出為0,低電平,則I/O端口的電平就是低電平。若控制輸出為1,高電平,則I/O端口的電平就是高電平。此時(shí),外部上拉和下拉的作用是控制在沒(méi)有輸出IO口的默認(rèn)電平。在該模式下,施密特觸發(fā)器也是打開(kāi)的,即輸入可用,通過(guò)輸入數(shù)據(jù)寄存器GPIOx_IDR可讀取I/O的實(shí)際狀態(tài)。
4.復(fù)用推挽輸出(帶上拉或者下拉)
此時(shí)GPIO復(fù)用為其他外設(shè),輸出數(shù)據(jù)寄存器GPIOx_ODR無(wú)效;即輸出的高低電平來(lái)源于其它外設(shè),除了輸出信號(hào)的來(lái)源改變之外,其他的與推挽輸出功能相同。
- 4種輸出速度 -
1. 2MHZ(低速)
2. 25MHZ(中速)
3. 50MHZ(快速)
4. 100MHZ(高速)
GPIO的引腳速度又稱(chēng)輸出驅(qū)動(dòng)電路的響應(yīng)速度,即一個(gè)驅(qū)動(dòng)電路可以不失真地通過(guò)信號(hào)的最大頻率。比如信號(hào)頻率為10MHz,而我們把GPIO速度配置成了2MHz,則10MHz的方波很可能就變成了正弦波,發(fā)生了失真。芯片內(nèi)部在I/O口的輸出部分安排了多個(gè)響應(yīng)速度不同的輸出驅(qū)動(dòng)電路,我們可以根據(jù)自己的需要選擇合適的驅(qū)動(dòng)電路,通過(guò)選擇速度來(lái)選擇不同的輸出驅(qū)動(dòng)模塊,達(dá)到最佳的噪聲控制和降低功耗的目的。因?yàn)镚PIO口的速度配置越高,噪聲越大,功耗也越大。比如在USART串口通信中,若最大波特率只需115.2k,那用2M的速度就夠了,既省電,噪聲也小;而在SPI接口中,若使用18M或9M的波特率,則需要選用50M的GPIO的引腳速度。 注意:CKS32F407用于配置PA13輸出速度的GPIOA_OSPEEDR寄存器的端口 13配置位(GPIOA_OSPEEDR_OSPEEDR13[1:0])初始值為00,即PA13的I/O輸出速度默認(rèn)為低速。因此客戶在實(shí)際使用CKS32F407時(shí),要按照參考手冊(cè)中的介紹來(lái)配置GPIOA_OSPEED寄存器中 OSPEEDR13[1:0]位,從而來(lái)選擇PA13的I/O輸出指定的速度。
?
GPIO的配置
?
接下來(lái)我們講解如何利用CKS32F4xx系列固件庫(kù)對(duì)GPIO口的工作模式進(jìn)行配置。首先,固件庫(kù)中定義了一個(gè)如下的結(jié)構(gòu)體:
typedef struct { uint32_t GPIO_Pin; GPIOMode_TypeDef GPIO_Mode; GPIOSpeed_TypeDef GPIO_Speed; GPIOOType_TypeDef GPIO_OType; GPIOPuPd_TypeDef GPIO_PuPd; }GPIO_InitTypeDef;
通過(guò)對(duì)該結(jié)構(gòu)體成員中各個(gè)變量的初始化,就可以完成對(duì)2.2小節(jié)中所講的GPIO口的工作模式配置。結(jié)構(gòu)體中各個(gè)成員變量的介紹及初始化時(shí)可被賦的值如下:
1)GPIO_Pin:用來(lái)選擇要控制的GPIO引腳,在標(biāo)準(zhǔn)庫(kù)函數(shù)中可選擇的值及其定義如下:
#define GPIO_Pin_0 ((uint16_t)0x0001) #define GPIO_Pin_1 ((uint16_t)0x0002) #define GPIO_Pin_2 ((uint16_t)0x0004) #define GPIO_Pin_3 ((uint16_t)0x0008) #define GPIO_Pin_4 ((uint16_t)0x0010) #define GPIO_Pin_5 ((uint16_t)0x0020) #define GPIO_Pin_6 ((uint16_t)0x0040) #define GPIO_Pin_7 ((uint16_t)0x0080) #define GPIO_Pin_8 ((uint16_t)0x0100) #define GPIO_Pin_9 ((uint16_t)0x0200) #define GPIO_Pin_10 ((uint16_t)0x0400) #define GPIO_Pin_11 ((uint16_t)0x0800) #define GPIO_Pin_12 ((uint16_t)0x1000) #define GPIO_Pin_13 ((uint16_t)0x2000) #define GPIO_Pin_14 ((uint16_t)0x4000) #define GPIO_Pin_15 ((uint16_t)0x8000) #define GPIO_Pin_All ((uint16_t)0xFFFF)
2) GPIO_Mode:用來(lái)設(shè)置已經(jīng)選擇的GPIO引腳的模式,在標(biāo)準(zhǔn)庫(kù)函數(shù)中可選擇的值及其定義如下:
typedef enum { GPIO_Mode_IN = 0x00, /*!設(shè)置為輸入模式 */ GPIO_Mode_OUT = 0x01, /*!設(shè)置為輸出模式*/ GPIO_Mode_AF = 0x02, /*!設(shè)置為復(fù)用模式 */ GPIO_Mode_AN = 0x03 /*!設(shè)置為模擬模式*/ }GPIOMode_TypeDef;
3) GPIO_Speed:用來(lái)設(shè)置已經(jīng)選擇的GPIO引腳的速度,在標(biāo)準(zhǔn)庫(kù)函數(shù)中可選擇的值及其定義如下:
#define GPIO_Speed_2MHz GPIO_Low_Speed #define GPIO_Speed_25MHz GPIO_Medium_Speed #define GPIO_Speed_50MHz GPIO_Fast_Speed #define GPIO_Speed_100MHz GPIO_High_Speed
4) GPIO_OType:用來(lái)設(shè)置已經(jīng)選擇的GPIO引腳的輸出模式,只有輸出模式才需要該配置,輸入模式下不需要該配置。在標(biāo)準(zhǔn)庫(kù)函數(shù)中可選擇的值及其定義如下:
typedef enum { GPIO_OType_PP = 0x00, /*!設(shè)置為推挽輸出模式 */ GPIO_OType_OD = 0x01 /*!設(shè)置為開(kāi)漏輸出模式 */ }GPIOOType_TypeDef;
5) GPIO_PuPd:用來(lái)設(shè)置已經(jīng)選擇的GPIO引腳的上下拉,在標(biāo)準(zhǔn)庫(kù)函數(shù)中可選擇的值及其定義如下:
typedef enum { GPIO_PuPd_NOPULL = 0x00, /*!設(shè)置為既不上拉也不下拉/浮空模式 */ GPIO_PuPd_UP = 0x01, /*!設(shè)置為上拉模式*/ GPIO_PuPd_DOWN = 0x02 /*!設(shè)置為下拉模式*/ }GPIOPuPd_TypeDef;
根據(jù)上面所講解的配置方法,我們講解標(biāo)準(zhǔn)庫(kù)下的3個(gè)實(shí)際配置實(shí)例。
1)?作為普通的GPIO口輸出,控制LED燈的亮滅,其GPIO口初始化函數(shù)如下:
void LED_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//使能GPIOF時(shí)鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//LED1對(duì)應(yīng)的IO口 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//輸出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽模式 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//速度100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIO }
2) 復(fù)用為CAN外設(shè)的輸出。
void CAN1_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能PORTA時(shí)鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11| GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //復(fù)用功能 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化PA11,PA12 GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_CAN1); //GPIOA11復(fù)用為CAN1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1); //GPIOA12復(fù)用為CAN1
3) 當(dāng)ADC采集的輸入通道,作為普通模擬輸入。
void ADC_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA時(shí)鐘 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//PA5 通道5 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模擬輸入 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;//不帶上下拉 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化 }
編輯:黃飛
評(píng)論
查看更多