一、什么是 GPIO?
GPIO(General Purpose Input Output)意为“通用输入输出端口”,是一种可以通过软件灵活配置为输入或输出的引脚。它在嵌入式开发中的典型应用包括:
控制 LED 灯、继电器、蜂鸣器等输出设备
检测按键、拨码开关等输入设备
与传感器或其他模块进行高低电平交互
还有模拟I2C SPI I2S等通讯协议
二、ESP32 GPIO 特性
ESP32 芯片提供了丰富的 GPIO 引脚,具体特性如下:
最多支持 39 个 GPIO,编号为 GPIO0 ~ GPIO39(部分为输入专用)
每个 GPIO 均可配置为输入、输出、上拉、下拉、中断等模式
支持 中断触发(上升沿/下降沿/电平触发)
部分 GPIO 还支持特定的外设功能(如 PWM、ADC、I2C、SPI)
注意:部分 GPIO 有特殊功能限制,例如 GPIO6~GPIO11 为 Flash 通信专用引脚,不建议作为通用 GPIO 使用。
三、GPIO 配置结构体与常用函数
在 ESP-IDF 框架中(ESP32 官方开发框架),GPIO 的使用主要通过以下结构体与 API 实现。
3.1 GPIO 配置结构体
ESP32 使用 gpio_config_t
结构体来配置 GPIO 属性:
typedef struct {
uint64_t pin_bit_mask; // 要配置的 GPIO 位掩码,例如 (1ULL<<GPIO_NUM_2)
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;
3.2 常用 GPIO 控制函数
以下是 ESP-IDF 中使用 GPIO 的常用函数:
函数 |
说明 |
---|---|
gpio_config() |
初始化并配置 GPIO 参数 |
gpio_set_level() |
设置 GPIO 输出高/低电平(0 或 1) |
gpio_get_level() |
读取 GPIO 当前输入电平 |
gpio_set_direction() |
设置 GPIO 的输入/输出方向 |
gpio_install_isr_service() |
安装 GPIO 中断服务 |
gpio_isr_handler_add() |
添加中断处理函数 |
gpio_intr_enable() / |
启用或关闭某 GPIO 中断功能 |
四、GPIO 控制 LED 示例
以下代码展示如何使用 GPIO 控制一个连接在 GPIO2 上的 LED。
4.1 示例代码
#include"driver/gpio.h"
#include"freertos/FreeRTOS.h"
#include"freertos/task.h"
#define LED_GPIO GPIO_NUM_2
void app_main(void) {
gpio_reset_pin(LED_GPIO); // 重置 GPIO 状态
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT); // 设置为输出模式
while (1) {
gpio_set_level(LED_GPIO, 1); // 点亮 LED
vTaskDelay(pdMS_TO_TICKS(500));
gpio_set_level(LED_GPIO, 0); // 熄灭 LED
vTaskDelay(pdMS_TO_TICKS(500));
}
}
4.2 说明
gpio_reset_pin()
:清除之前可能的配置gpio_set_direction()
:设置方向为输出gpio_set_level()
:设置电平状态
这是一个标准的“LED 闪烁”示例,每隔 500ms 切换一次电平状态。
五、GPIO 监听按键输入案例
接下来展示如何监听按键输入。假设一个按键连接到 GPIO4,当按下按键(电平变低)时,控制 LED 灯亮起。
5.1 示例代码
#define LED_GPIO GPIO_NUM_2
#define KEY_GPIO GPIO_NUM_4
void app_main(void) {
// 配置 LED 引脚
gpio_reset_pin(LED_GPIO);
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);// 配置按键引脚
gpio_reset_pin(KEY_GPIO);
gpio_set_direction(KEY_GPIO, GPIO_MODE_INPUT);
gpio_pullup_en(KEY_GPIO); // 开启上拉,避免悬空
while (1) {
int key_level = gpio_get_level(KEY_GPIO);
if (key_level == 0) { // 按下为低电平
gpio_set_level(LED_GPIO, 1); // 点亮 LED }
else
{
gpio_set_level(LED_GPIO, 0); // 熄灭 LED }
vTaskDelay(pdMS_TO_TICKS(50)); // 简单防抖延迟
}
}
5.2 说明
按键使用输入模式,使用内部上拉电阻。
检测按键是否被按下,通过
gpio_get_level()
读取电平状态。使用一个简单延迟代替硬件防抖。
六、中断方式监听按键(高级)
如果不想频繁轮询,可以使用 GPIO 中断方式检测按键。
6.1 配置中断处理器示例
static void IRAM_ATTR gpio_isr_handler(void* arg) {
gpio_set_level(LED_GPIO, !gpio_get_level(LED_GPIO)); // LED 取反
}
void app_main(void) {
// 配置 LED
gpio_reset_pin(LED_GPIO);
gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);// 配置按键为下降沿中断输入
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << KEY_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_NEGEDGE,
};
gpio_config(&io_conf);
gpio_install_isr_service(0); // 安装 ISR 服务
gpio_isr_handler_add(KEY_GPIO, gpio_isr_handler, NULL); // 添加 ISR 处理函数
}
6.2 说明
使用
gpio_config()
配置中断模式使用
gpio_install_isr_service()
和gpio_isr_handler_add()
注册中断服务中断服务函数必须使用
IRAM_ATTR
修饰以放置到 IRAM 中
七、总结
本文介绍了 ESP32 GPIO 的使用基础,涵盖:
GPIO 的功能与结构体配置
常用控制函数
控制 LED 的输出示例
读取按键的输入检测示例
使用中断方式监听按键的进阶示例
GPIO 是嵌入式开发的“第一步”,掌握好 GPIO 控制逻辑,对于后续的串口通信、PWM 控制、传感器读取等都有重要帮助。
在后续文章中,我们还将进一步探讨 ESP32 的 PWM、ADC、UART、I2C、SPI 等外设控制技术,敬请期待。