飛書文檔https://x509p6c8to.feishu.cn/wiki/L6IGwHKV6ikQ08kqwAwcAvhznBc
前面我們學習了GPIO的輸出,GPIO輸入部分其實也是一樣的,這里我們使用按鍵作為GPIO輸入例程講解,分三步走。
- 查看板卡原理圖,確定使用的是哪個GPIO
- 查看GPIO官方例程,了解GPIO輸入如何配置
- 查看GPIO官方API文檔,了解API參數和如何使用
1.1、查看板卡原理圖,確定使用的是哪個GPIO
這里我們使用按鍵作為GPIO輸入例程講解,先查看原理圖,找到按鍵連接的GPIO,如下圖所示,板卡的GPIO42連接到按鍵。
1.2、查看GPIO官方例程,了解GPIO如何配置
這部分和GPIO輸出的配置比較類似,GPIO的輸入配置和輸出配置,用的都是一個函數gpio_config,我們只需要把參數中的mode設置為輸入模式即可。
??? gpio_config_t io_conf = {};io_conf.intr_type = GPIO_INTR_DISABLE;io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;io_conf.mode = GPIO_MODE_INPUT;io_conf.pull_up_en = GPIO_PULLUP_ENABLE;gpio_config(&io_conf);
1.3、查看GPIO官方API文檔,了解API參數和如何使用
GPIO輸入主要用到兩個函數,gpio_config和gpio_get_level,我們參考官方API手冊了解下這兩個函數的說明
頭文件
#include "driver/gpio.h"esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
功能: gpio_config 函數用于配置一個或多個 GPIO 引腳。通過傳遞一個 gpio_config_t 結構體,可以設置引腳的模式、上拉/下拉電阻、中斷類型等屬性。pGPIOConfig參數說明
typedef struct {uint64_t pin_bit_mask;? // 要配置的 GPIO 引腳的位掩碼gpio_mode_t mode;?????? // GPIO 引腳的工作模式gpio_pullup_t pull_up_en; // 是否啟用上拉電阻gpio_pulldown_t pull_down_en; // 是否啟用下拉電阻gpio_int_type_t intr_type; // 中斷觸發類型
} gpio_config_t;pin_bit_mask:
一個64位的掩碼,用于指定要配置的引腳。每個位對應一個 GPIO 引腳,例如,若要配置 GPIO 2 和 GPIO 3,則可以設置為 (1ULL << 2) | (1ULL << 3)。mode: 引腳的工作模式,可以是以下值之一:
GPIO_MODE_DISABLE: 禁用引腳。
GPIO_MODE_INPUT: 輸入模式。
GPIO_MODE_OUTPUT: 輸出模式。
GPIO_MODE_OUTPUT_OD: 開漏輸出模式。
GPIO_MODE_INPUT_OUTPUT_OD: 開漏輸入輸出模式。
GPIO_MODE_INPUT_OUTPUT: 輸入輸出模式。pull_up_en: 上拉電阻使能,可以是以下值之一:
GPIO_PULLUP_DISABLE: 禁用上拉電阻。
GPIO_PULLUP_ENABLE: 啟用上拉電阻。pull_down_en: 下拉電阻使能,可以是以下值之一:
GPIO_PULLDOWN_DISABLE: 禁用下拉電阻。
GPIO_PULLDOWN_ENABLE: 啟用下拉電阻。intr_type: 中斷類型,可以是以下值之一:
GPIO_INTR_DISABLE: 禁用中斷。
GPIO_INTR_POSEDGE: 上升沿觸發中斷。
GPIO_INTR_NEGEDGE: 下降沿觸發中斷。
GPIO_INTR_ANYEDGE: 任意邊沿觸發中斷。
GPIO_INTR_LOW_LEVEL: 低電平觸發中斷。
GPIO_INTR_HIGH_LEVEL: 高電平觸發中斷。int gpio_get_level(gpio_num_t gpio_num);
功能: gpio_get_level 函數用于獲取指定 GPIO 引腳的電平狀態。該函數適用于配置為輸入模式的 GPIO 引腳。
參數:
gpio_num: 要讀取電平的 GPIO 引腳編號。
返回值:
0: 引腳處于低電平。
1: 引腳處于高電平。
-1: 參數無效(例如,GPIO 引腳編號無效或引腳未配置為輸入模式)。
于是我們就可以得到最終的程序:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"static const char* TAG = "MyModule";
// 定義一個宏 GPIO_INPUT_IO,其值為 42,表示要使用的輸入 GPIO 引腳編號為 42
#define GPIO_INPUT_IO 42
// 定義一個宏 GPIO_INPUT_PIN_SEL,通過位運算(將無符號長整型 1 左移 GPIO_INPUT_IO 位)生成一個用于選擇特定 GPIO 引腳的掩碼
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO)void app_main(void)
{// 定義一個 gpio_config_t 類型的結構體變量 io_conf,并初始化為空結構體gpio_config_t io_conf = {};// 設置 GPIO 引腳的中斷觸發類型為上升沿觸發io_conf.intr_type = GPIO_INTR_DISABLE;// 使用之前定義的掩碼 GPIO_INPUT_PIN_SEL 來指定要配置的 GPIO 引腳io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;// 將 GPIO 引腳的工作模式設置為輸入模式io_conf.mode = GPIO_MODE_INPUT;// 啟用 GPIO 引腳的上拉電阻io_conf.pull_up_en = GPIO_PULLUP_ENABLE;// 調用 gpio_config 函數,將上述配置應用到指定的 GPIO 引腳gpio_config(&io_conf);while (1){int level = gpio_get_level(GPIO_INPUT_IO);ESP_LOGI(TAG, "level: %d", level);vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
代碼優化
上面代碼中,GPIO初始化部分代碼還是太零散了,有沒有辦法更整潔點,也是有的,我們可以使用另一種結構體初始化的方式,定義+賦值放到一起。
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"static const char* TAG = "MyModule";#define GPIO_INPUT_IO 42
#define GPIO_INPUT_PIN_SEL (1ULL << GPIO_INPUT_IO)void app_main(void)
{gpio_config_t io_conf = {.pin_bit_mask = GPIO_INPUT_PIN_SEL,.mode = GPIO_MODE_INPUT,.pull_up_en = GPIO_PULLUP_ENABLE,};gpio_config(&io_conf);while (1){int level = gpio_get_level(GPIO_INPUT_IO);ESP_LOGI(TAG, "level: %d", level);vTaskDelay(1000 / portTICK_PERIOD_MS);}
}
然后我們需要把板卡接到底板上,因為按鍵是在底板上的。
然后按下按鍵,可以看到打印level:0,松開按鍵打印level:1