SOC-ESP32S3部分:9-GPIO输入按键状态读取
飞书文档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