飞书文档
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

















![[Vue]路由基础使用和路径传参](https://i-blog.csdnimg.cn/direct/afe6ca0f8a054d7a87905ab6ffc410c0.png)


