GPIO全名爲General Purpose Input Output,即通用輸入輸出。有時候簡稱爲「IO口」。通用,說明它是常見的。輸入輸出,就是說既能當輸入口使用,又能當輸出口使用。端口,就是元器件上的一個引腳。編程
輸入模式和輸出模式是GPIO的基本特性,固然GPIO還有其它模式可選。函數
STM32是一款3.3V電壓的芯片,IO輸出是3.3V,但IO大部分都是能夠容忍5V電壓輸入。通常在芯片手冊的「引腳定義」章節能夠查看到有FT標識表示該IO能夠容忍5V電壓輸入。測試
輸入模式:ui
l 浮空輸入(GPIO_Mode_IN_FLOATING):引腳電平是真實的外部鏈接器件電壓,電平有不肯定性spa
l 上拉輸入 (GPIO_Mode_IPU):默認經過電阻上拉到VCC,不接外部器件時能夠讀出高電平.net
l 下拉輸入 (GPIO_Mode_IPD):默認經過電阻下拉到GND,不接外部器件時能夠讀出低電平3d
l 模擬輸入 (GPIO_Mode_AIN):將外部信號直接傳輸到數模轉換通道上code
輸出模式:orm
l 開漏輸出(GPIO_Mode_Out_OD):只能輸出低電平,高電平由電阻上拉決定blog
l 開漏複用功能(GPIO_Mode_AF_OD):用於外設功能使用
l 推輓式輸出(GPIO_Mode_Out_PP):能夠輸出強高和強低,一般使用該功能控制LED
l 推輓式複用功能(GPIO_Mode_AF_PP):用於外設功能使用
GPIO的基本結構:
TTL肖特基觸發器其實能夠理解爲用肖特基管構成的施密特觸發器,做用簡單說就是將相對緩慢變化的模擬信號變成矩形(方波)信號,便於後面讀取。這裏有一個閾值電壓的概念,好比從低到高達到多少纔會導通,從高到底多少纔會關閉。
浮空就是邏輯器件與引腳即不接高電平,也不接低電平。因爲邏輯器件的內部結構和外部引腳所接的器件決定電平狀態。通常實際運用時,引腳不建議懸空,易受干擾。通俗講就是浮空就是浮在空中,就至關於此端口在默認狀況下什麼都不接,呈高阻態,這種設置在數據傳輸時用的比較多。浮空最大的特色就是電壓的不肯定性,它多是0V,頁多是VCC,還多是介於二者之間的某個值(最有可能) 浮空通常用來作ADC輸入用,這樣能夠減小上下拉電阻對結果的影響。
上拉就是把點位拉高,好比拉到Vcc。上拉就是將不肯定的信號經過一個電阻嵌位在高電平。電阻同時起到限流的做用。弱強只是上拉電阻的阻值不一樣,沒有什麼嚴格區分。
電阻一般爲30-50KΩ
下拉就是把點位拉低,好比拉到GND。下拉就是將不肯定的信號經過一個電阻嵌位在低電平。電阻同時起到限流的做用。弱強只是下拉電阻的阻值不一樣,沒有什麼嚴格區分
模擬輸入是指傳統方式的輸入,數字輸入是輸入PCM數字信號,即0,1的二進制數字信號,經過數模轉換,轉換成模擬信號,經前級放大進入功率放大器,功率放大器仍是模擬的
IO輸出0接GND,IO輸出1,懸空,須要外接上拉電阻,才能實現輸出高電平。當輸出爲1時,IO口的狀態由上拉電阻拉高電平,但因爲是開漏輸出模式,這樣IO口也就能夠由外部電路改變爲低電平或不變。能夠讀IO輸入電平變化,實現C51的IO雙向功能。
只能輸出強低電平。
用於外設使用
IO輸出0-接GND, IO輸出1 -接VCC。這是使用最多的了。控制LED基本都是使用這種模式。
能夠輸出強高低電平,鏈接外部數字器件
用於外設使用
(1). GPIO Pull-up/Pull-down:
IO上下拉配置
l No pull-up and no pull-down,浮空輸入,配置爲不上拉和下拉
l Pull-up,上拉輸入
l Pull-down,下拉輸入
(1). GPIO output level
l Low:IO初始化默認輸出低電平
l High:IO初始化默認輸出高電平
(2). GPIO mode
l Output Open Drain,開漏輸出,能夠輸出低電平
l Output Push Pull,推輓輸出,能夠輸出低電平和高電平
(3). GPIO Pull-up/Pull-down:
IO上下拉配置
l No pull-up and no pull-down,浮空輸入,配置爲不上拉和下拉
l Pull-up,上拉輸入
l Pull-down,下拉輸入
(4). Maximum output speed
l Low,GPIO速度爲低速,一般爲2MHZ
l Medium,GPIO速度爲中速,一般爲10MHZ
l High,GPIO速度爲高速,一般爲50MHZ
測試有GPIOA1和GPIOA2設置爲輸出測試
宏定義
#define DONG_OUT_1_Pin GPIO_PIN_1 #define DONG_OUT_1_GPIO_Port GPIOA #define DONG_OUT_2_Pin GPIO_PIN_2 #define DONG_OUT_2_GPIO_Port GPIOA
初始化函數是自動生成的
void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE();//使能GPIOA時鐘 /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOA, DONG_OUT_1_Pin|DONG_OUT_2_Pin, GPIO_PIN_RESET);//設置上電電平爲低 /*Configure GPIO pins : PAPin PAPin */ GPIO_InitStruct.Pin = DONG_OUT_1_Pin|DONG_OUT_2_Pin;//兩個GPIO_PIN GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推輓輸出模式 GPIO_InitStruct.Pull = GPIO_NOPULL;//浮空,不上拉也不下拉 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;//低速 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); }
設置或清除選定的數據端口位
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
參數:
GPIOx :其中x能夠(A..G取決於所使用的設備)來選擇GPIO外設
GPIO_Pin :指定要寫入的端口位。此參數能夠是GPIO_PIN_x之一,其中x能夠是( 0..15 )。
PinState :指定要寫入選定位的值。此參數能夠是GPIO_PinState枚舉值之一:
l GPIO_PIN_RESET:清除端口Pin,低電平
l GPIO_PIN_SET:設置端口Pin,高電平
例子:
HAL_GPIO_WritePin(GPIOA, DONG_OUT_1_Pin|DONG_OUT_2_Pin, GPIO_PIN_RESET);//兩個設置爲低電平 HAL_Delay(1000);//1s HAL_GPIO_WritePin(GPIOA, DONG_OUT_1_Pin, GPIO_PIN_SET);//單獨設置爲高電平 HAL_GPIO_WritePin(GPIOA,DONG_OUT_2_Pin, GPIO_PIN_SET);//單獨設置爲高電平 HAL_Delay(1000);//1s
切換指定的GPIO pin
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
參數:
GPIOx :其中x能夠(A..G取決於所使用的設備)來選擇GPIO外設
GPIO_Pin :指定要寫入的端口位。此參數能夠是GPIO_PIN_x之一,其中x能夠是(0..15 )。
例子:
HAL_GPIO_TogglePin(GPIOA, DONG_OUT_1_Pin|DONG_OUT_2_Pin);//兩個輸出電平取反 HAL_Delay(1000);//1s HAL_GPIO_TogglePin(GPIOA, DONG_OUT_1_Pin);//單獨輸出電平取反 HAL_GPIO_TogglePin(GPIOA,DONG_OUT_2_Pin);//單獨輸出電平取反 HAL_Delay(1000);//1s
宏定義
#define DONG_IN_1_Pin GPIO_PIN_3 #define DONG_IN_1_GPIO_Port GPIOA
初始化部分
GPIO_InitTypeDef GPIO_InitStruct = {0};//初始化結構體 __HAL_RCC_GPIOA_CLK_ENABLE();//GPIO時鐘開啓 GPIO_InitStruct.Pin = DONG_IN_1_Pin;//引腳 GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//輸入模式 GPIO_InitStruct.Pull = GPIO_PULLUP;//上拉 HAL_GPIO_Init(DONG_IN_1_GPIO_Port, &GPIO_InitStruct);
讀取指定的輸入端口引腳
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
參數:
GPIOx :其中x能夠(A..G取決於所使用的設備)來選擇GPIO外設
GPIO_Pin :指定要寫入的端口位。此參數能夠是GPIO_PIN_x之一,其中x能夠是(0..15 )
返回:
typedef enum { GPIO_PIN_RESET = 0u,//低電平 GPIO_PIN_SET//高電平 } GPIO_PinState;
例子:
GPIO_PinState res=HAL_GPIO_ReadPin(DONG_IN_1_GPIO_Port,DONG_IN_1_Pin);//讀取電平 if(res==GPIO_PIN_RESET){ HAL_GPIO_WritePin(GPIOA, DONG_OUT_1_Pin|DONG_OUT_2_Pin, GPIO_PIN_SET);//兩個設置爲高電平 }else{ HAL_GPIO_WritePin(GPIOA, DONG_OUT_1_Pin|DONG_OUT_2_Pin, GPIO_PIN_RESET);//兩個設置爲低電平 }
GPIO mode:
l 上升沿觸發檢測的外部中斷模式(External Interrupt Mode with Rising edge trigger detection)
l 降低沿觸發檢測的外部中斷模式(External Interrupt Mode with Falling edge trigger detectiort)
l 上升/降低沿觸發檢測的外部中斷模式(External Interrupt Mode with Risinq/Falling edge trigger detection)
l 上升沿觸發檢測的外部事件模式(External Event Mode with Rising edge trigger detection)
l 降低沿觸發檢測的外部事件模式(External Event Mode with Falling edge trigger detection)
l 上升/降低沿觸發檢測的外部事件模式(External Event Mode with Rising/Falling edge trigger detectiont)
中斷和事件的區別:
l 中斷是當IO達到中斷條件後會向CPU產生中斷請求
l 事件是事先設置好的任務,當單片機達到要求將經過硬件的方式處理事先設置好的任務,而不向CPU請求中斷,好比DMA、AD轉換等
宏定義
#define KEY1_Pin GPIO_PIN_3 #define KEY1_GPIO_Port GPIOA #define KEY1_EXTI_IRQn EXTI3_IRQn
初始化部分
__HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_InitStruct = {0}; /*Configure GPIO pin : PtPin */ GPIO_InitStruct.Pin = KEY1_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; GPIO_InitStruct.Pull = GPIO_PULLUP; HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct); /* EXTI interrupt init*/ HAL_NVIC_SetPriority(EXTI3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(EXTI3_IRQn);
中斷回調函數
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin);
參數:
GPIO_Pin :指定鏈接EXTI線的引腳
例子:
//GPIO中斷回調函數 void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){ //判斷進入中斷的GPIOs if(KEY1_Pin==GPIO_Pin){ HAL_GPIO_TogglePin(GPIOA, DONG_OUT_1_Pin);//單獨輸出電平取反 HAL_GPIO_TogglePin(GPIOA,DONG_OUT_2_Pin);//單獨輸出電平取反 } }
關於按鍵防抖的問題:
l 軟件防抖能夠檢測到電平延時一段時間再確認電平,延時時間通常爲10-20ms
l 硬件防抖能夠在按鍵上並聯一個電容,通常爲0.1uf
參考:
https://blog.csdn.net/baidu_37366055/article/details/80060962