GPIO(General-purpose input/output)是通用輸入輸出端口的簡稱,CKS32F4xx系列產品通過GPIO引腳與外部設備連接起來,從而實現與外部通訊、控制以及數據采集的功能。最基本的輸出功能是由CKS32F4xx系列產品控制引腳輸出高、低電平,實現開關控制,如把GPIO引腳接入到LED燈,那就可以控制LED燈的亮滅,引腳接入到繼電器或三極管,那就可以通過繼電器或三極管控制外部大功率電路的通斷。最基本的輸入功能是檢測外部輸入電平,如把 GPIO引腳連接到按鍵,通過電平高低區分按鍵是否被按下。
GPIO硬件結構框圖
該圖從最右端看起,最右端標注著“I/O”的就是代表CKS32F4xx系列產品引出的GPIO引腳,其余部件都位于芯片內部。引腳處的兩個保護二級管可以防止引腳外部過高或過低的電壓輸入,當引腳電壓高于VDD_FT時,上方的二極管導通,當引腳電壓低于VSS時,下方的二極管導通,由此可以防止不正常電壓引入芯片導致芯片的燒毀。這里要特別注意VDD_FT 代表IO口兼容3.3V和5V,如果沒有標注“FT”,就代表著不兼容5V。在芯片數據手冊的引腳定義中,會看到有“電平I/O”一列,有FT標注的即為支持5V,如下圖所示:
標號1處是上拉、下拉電阻,從它的結構我們可以看出,通過上、下拉對應的開關配置,我們可以控制引腳默認狀態下的電壓,開啟上拉的時候引腳電壓為高電平,開啟下拉的時候引腳電壓為低電平。同時也可以設置“既不上拉也不下拉模式”,我們也把這種狀態稱為浮空模式。
標號2處是一個由P-MOS和N-MOS管組成的單元電路。這個結構使GPIO具有了“推挽輸出”和“開漏輸出”兩種模式。上方的P-MOS管高電平導通,低電平關閉,下方的N-MOS低電平導通,高電平關閉。
標號3處是輸出數據寄存器,它為標號2處的雙MOS管結構電路提供輸入控制信號,因此通過修改輸出數據寄存器的值就可以修改GPIO引腳的輸出電平。而圖中“置位/復位寄存器 GPIOx_BSRR”可以通過修改輸出數據寄存器的值從而影響電路的輸出。
標號4處是復用功能輸出,“復用”是指CKS32F4xx系列產品的其它片上外設可以對GPIO引腳進行控制,此時GPIO引腳用作該外設功能的一部分,算是第二用途。例如我們使用USART串口通訊時,需要用到某個GPIO引腳作為通訊發送引腳,這個時候就可以把該GPIO引腳配置成USART串口復用功能,由串口外設控制該引腳,發送數據。
標號5處是輸入數據寄存器,它連接到圖中的TTL施密特觸發器,觸發器的基本原理是當輸入電壓高于正向閾值電壓時,輸出為高;當輸入電壓低于負向閾值電壓時,輸出為低;IO口信號經過觸發器后,模擬信號轉化為0和1的數字信號,也就是高低電平,并且是TTL電平協議, 然后存儲在“輸入數據寄存器。因此,通過讀取該寄存器就可以了解GPIO引腳的電平狀態。
標號6處是復用功能輸入,與“復用功能輸出”模式類似,同樣,如果我們使用USART串口通訊時,需要用到某個GPIO引腳作為通訊接收引腳,這個時候就可以把該GPIO引腳配置成USART串口復用功能,使USART可以通過該通訊引腳接收遠端數據。
標號7處是模擬輸入輸出,當 GPIO引腳用于ADC采集電壓的輸入通道時,用作“模擬輸入”功能,此時信號是不經過施密特觸發器的,因為經過施密特觸發器后信號只有0、1 兩種狀態,所以ADC外設要采集到原始的模擬信號,信號源輸入必須在施密特觸發器之前。同樣的,當 GPIO引腳用于DAC作為模擬電壓輸出通道時,此時作為“模擬輸出”功能,DAC 的模擬信號輸出就不經過雙MOS管結構了,在GPIO結構框圖的右下角處,模擬信號直接輸出到引腳。
GPIO的工作模式
- 4種輸入模式 -
1.浮空輸入
浮空輸入狀態下,IO的電平狀態是不確定的,完全由外部輸入決定。如果在該引腳懸空的情況下,讀取該端口的電平是不確定的。
2.上拉輸入
在該模式下,如果IO口外部沒有信號輸入或者引腳懸空,IO口默認為高電平。如果I/O口輸入低電平,那么引腳就為低電平,MCU讀取到的就是低電平。
3.下拉輸入
在該模式下如果IO口外部沒有信號輸入或者引腳懸空,IO口默認為低電平,如果I/O口輸入高電平,那么引腳就為高電平,MCU讀取到的就是高電平。
4.模擬功能
當GPIO用于模擬功能時,引腳的上、下拉電阻是不起作用的,這個時候即使配置了上拉或下拉模式,也不會影響到模擬信號的輸入輸出。除了ADC和DAC要將IO配置為模擬功能模式之外,其他外設功能一律要配置為復用功能模式。
- 4種輸出模式 -
1.開漏輸出(帶上拉或者下拉)
在該模式下,若MCU控制輸出為高電平1時,輸出指令是不會起到作用的。此時I/O端口的電平就不會由輸出的高電平決定,而是由I/O端口外部的上拉或者下拉決定,如果沒有上拉或者下拉,IO口就處于高阻態。雖然通過軟件設置內部上拉,也可以輸出高電平,但是CKS32F4xx系列產品內部上拉是"弱上拉",即通過此上拉輸出的電流是很弱的,驅動能力很弱。但是在該模式下,當MCU控制輸出為低電平0時,即使沒有上拉或者下拉,I/O端口也會輸出低電平。另一方面,在開漏模式下,施密特觸發器是打開的,即輸入可用,可以通過輸入數據寄存器GPIOx_IDR讀取I/O的實際狀態。開漏輸出主要有以下兩點作用:
a. I/O端口設置成開漏輸出模式時,可以用來連接不同電平的器件,用來匹配電平,因為開漏引腳不連接外部的上拉電阻時,只能輸出低電平,如果需要同時具備輸出高電平的功能,則需要接上拉電阻。因此我們通過改變上拉電源的電壓,便可以改變傳輸電平。比如通過加上上拉電阻就可以提供TTL電平-CMOS電平的輸出。
b.當多個設置為開漏輸出的引腳連接到一條總線上時。通過外加一個上拉電阻,在不增加任何器件的情況下,這些引腳形成了“與邏輯”關系,即“線與”。如果有一個引腳輸出為邏輯0,相當于接地,那么與之并聯的回路“相當于被一根導線短路”,所以總線上的邏輯電平便為0。只有都為高電平時,總線上的電平才為1。在IIC通信中,引腳通常設置為開漏輸出模式。
2.復用開漏輸出(帶上拉或者下拉)
此時GPIO復用為其他外設,輸出數據寄存器GPIOx_ODR無效;即輸出的高低電平來源于其它外設,除了輸出信號的來源改變之外,其他的與開漏輸出功能相同。
3.推挽輸出(帶上拉或者下拉)
在該模式下,如果我們控制輸出為0,低電平,則I/O端口的電平就是低電平。若控制輸出為1,高電平,則I/O端口的電平就是高電平。此時,外部上拉和下拉的作用是控制在沒有輸出IO口的默認電平。在該模式下,施密特觸發器也是打開的,即輸入可用,通過輸入數據寄存器GPIOx_IDR可讀取I/O的實際狀態。
4.復用推挽輸出(帶上拉或者下拉)
此時GPIO復用為其他外設,輸出數據寄存器GPIOx_ODR無效;即輸出的高低電平來源于其它外設,除了輸出信號的來源改變之外,其他的與推挽輸出功能相同。
- 4種輸出速度 -
1. 2MHZ(低速)
2. 25MHZ(中速)
3. 50MHZ(快速)
4. 100MHZ(高速)
GPIO的引腳速度又稱輸出驅動電路的響應速度,即一個驅動電路可以不失真地通過信號的最大頻率。比如信號頻率為10MHz,而我們把GPIO速度配置成了2MHz,則10MHz的方波很可能就變成了正弦波,發生了失真。芯片內部在I/O口的輸出部分安排了多個響應速度不同的輸出驅動電路,我們可以根據自己的需要選擇合適的驅動電路,通過選擇速度來選擇不同的輸出驅動模塊,達到最佳的噪聲控制和降低功耗的目的。因為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口的工作模式進行配置。首先,固件庫中定義了一個如下的結構體:
typedefstruct { uint32_tGPIO_Pin; GPIOMode_TypeDefGPIO_Mode; GPIOSpeed_TypeDefGPIO_Speed; GPIOOType_TypeDefGPIO_OType; GPIOPuPd_TypeDefGPIO_PuPd; }GPIO_InitTypeDef;
通過對該結構體成員中各個變量的初始化,就可以完成對2.2小節中所講的GPIO口的工作模式配置。結構體中各個成員變量的介紹及初始化時可被賦的值如下:
1)GPIO_Pin:用來選擇要控制的GPIO引腳,在標準庫函數中可選擇的值及其定義如下:
#defineGPIO_Pin_0((uint16_t)0x0001) #defineGPIO_Pin_1((uint16_t)0x0002) #defineGPIO_Pin_2((uint16_t)0x0004) #defineGPIO_Pin_3((uint16_t)0x0008) #defineGPIO_Pin_4((uint16_t)0x0010) #defineGPIO_Pin_5((uint16_t)0x0020) #defineGPIO_Pin_6((uint16_t)0x0040) #defineGPIO_Pin_7((uint16_t)0x0080) #defineGPIO_Pin_8((uint16_t)0x0100) #defineGPIO_Pin_9((uint16_t)0x0200) #defineGPIO_Pin_10((uint16_t)0x0400) #defineGPIO_Pin_11((uint16_t)0x0800) #defineGPIO_Pin_12((uint16_t)0x1000) #defineGPIO_Pin_13((uint16_t)0x2000) #defineGPIO_Pin_14((uint16_t)0x4000) #defineGPIO_Pin_15((uint16_t)0x8000) #defineGPIO_Pin_All((uint16_t)0xFFFF)
2) GPIO_Mode:用來設置已經選擇的GPIO引腳的模式,在標準庫函數中可選擇的值及其定義如下:
typedefenum { GPIO_Mode_IN=0x00,/*!設置為輸入模式*/ GPIO_Mode_OUT=0x01,/*!設置為輸出模式*/ GPIO_Mode_AF=0x02,/*!設置為復用模式*/ GPIO_Mode_AN=0x03/*!設置為模擬模式*/ }GPIOMode_TypeDef;
3) GPIO_Speed:用來設置已經選擇的GPIO引腳的速度,在標準庫函數中可選擇的值及其定義如下:
#defineGPIO_Speed_2MHzGPIO_Low_Speed #defineGPIO_Speed_25MHzGPIO_Medium_Speed #defineGPIO_Speed_50MHzGPIO_Fast_Speed #defineGPIO_Speed_100MHzGPIO_High_Speed
4) GPIO_OType:用來設置已經選擇的GPIO引腳的輸出模式,只有輸出模式才需要該配置,輸入模式下不需要該配置。在標準庫函數中可選擇的值及其定義如下:
typedefenum { GPIO_OType_PP=0x00,/*!設置為推挽輸出模式*/ GPIO_OType_OD=0x01/*!設置為開漏輸出模式*/ }GPIOOType_TypeDef;
5) GPIO_PuPd:用來設置已經選擇的GPIO引腳的上下拉,在標準庫函數中可選擇的值及其定義如下:
typedefenum { GPIO_PuPd_NOPULL=0x00,/*!設置為既不上拉也不下拉/浮空模式*/ GPIO_PuPd_UP=0x01,/*!設置為上拉模式*/ GPIO_PuPd_DOWN=0x02/*!設置為下拉模式*/ }GPIOPuPd_TypeDef;
根據上面所講解的配置方法,我們講解標準庫下的3個實際配置實例。
1)作為普通的GPIO口輸出,控制LED燈的亮滅,其GPIO口初始化函數如下:
voidLED_GPIO_Init(void) { GPIO_InitTypeDefGPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);//使能GPIOF時鐘 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//LED1對應的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) 復用為CAN外設的輸出。
voidCAN1_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;//復用功能 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復用為CAN1 GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_CAN1);//GPIOA12復用為CAN1
3) 當ADC采集的輸入通道,作為普通模擬輸入。
voidADC_Init(void) { GPIO_InitTypeDefGPIO_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);//初始化 }
來源:中科芯MCU
免責聲明:本文為轉載文章,轉載此文目的在于傳遞更多信息,版權歸原作者所有。本文所用視頻、圖片、文字如涉及作品版權問題,請聯系小編進行處理
審核編輯 黃宇
-
mcu
+關注
關注
146文章
17148瀏覽量
351197 -
GPIO
+關注
關注
16文章
1204瀏覽量
52098
發布評論請先 登錄
相關推薦
評論