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