示例:GPIO 控制数字输出
本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。
本教程将介绍如何使用乐鑫 ESP-IDF 框架,通过 GPIO 控制数字输出,从而点亮和关闭 LED。
1. GPIO
在 ESP-IDF 中使用 GPIO 控制数字输出,通用步骤如下:
-
包含头文件
首先需要包含 GPIO 驱动的头文件:
#include "driver/gpio.h"
并在
CMakeLists.txt
中添加依赖(如REQUIRES esp_driver_gpio
)。 -
配置 GPIO
配置 GPIO 为输出模式。可以通过
gpio_config_t
结构体进行初始化,例如:gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_NUM_7), // 选择要配置的 GPIO
.mode = GPIO_MODE_OUTPUT, // 设置为输出模式
.pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉
.intr_type = GPIO_INTR_DISABLE // 禁用中断
};
gpio_config(&io_conf); -
设置输出电平
使用
gpio_set_level
控制 GPIO 输出高低电平:gpio_set_level(GPIO_NUM_7, 1); // 输出高电平
gpio_set_level(GPIO_NUM_7, 0); // 输出低电平 -
(可选)重置引脚
可用
gpio_reset_pin(GPIO_NUM_7);
将引脚恢复到默认状态(例如高阻态)。这在需要动态改变引脚功能或进入低功耗模式前非常有用。
2. 示例项目
本示例将演示如何配置一个 GPIO 引脚为数字输出模式,并控制其循环输出高低电平,以实现 LED 灯的周期性闪烁。
2.1 电路
需要使用的器件有:
- LED * 1
- 330Ω 电阻 * 1
- 面包板 * 1
- 导线
- ESP32 开发板 (微雪 ESP32-S3-Zero 迷你开发板)
按照下面接线图连接电路:
ESP32-S3-Zero 引脚图

2.2 创建项目
-
创建一个项目。如果不清楚如何操作,请参考 从模板创建项目。
-
查看 GPIO API 参考。根据文档中的指引完成以下步骤。
首先在 main.c 中包含头文件:
#include "driver/gpio.h"
然后在 main/CMakeLists.txt 中声明
esp_driver_gpio
组件:idf_component_register(SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES esp_driver_gpio)
2.3 示例代码
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
static const char *TAG = "example";
static const gpio_num_t GPIO_OUTPUT_LED = GPIO_NUM_7;
void app_main(void)
{
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_OUTPUT_LED), // 选择要配置的 GPIO
.mode = GPIO_MODE_OUTPUT, // 设置为输出模式
.pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉
.intr_type = GPIO_INTR_DISABLE // 禁用中断
};
gpio_config(&io_conf);
while (1) {
// 设置 GPIO 高电平
ESP_LOGI(TAG, "Turn the LED on");
gpio_set_level(GPIO_OUTPUT_LED, 1);
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒
// 设置 GPIO 低电平
ESP_LOGI(TAG, "Turn the LED off");
gpio_set_level(GPIO_OUTPUT_LED, 0);
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒
}
}
2.4 构建并烧录
-
配置烧录选项
首先,在构建和烧录之前,请务必检查并设置正确的目标设备、串口和烧录方式。参考 第2节 运行示例 - 1.3 配置项目 。
-
点击
一键自动依次执行构建、烧录和监视这三个步骤。
-
烧录完成后,可以看到开发板上的 LED 开始闪烁。同时,串口监视器会启动并输出如下日志信息:
I (256) main_task: Started on CPU0
I (266) main_task: Calling app_main()
I (266) example: Turn the LED on
I (1266) example: Turn the LED off
I (2266) example: Turn the LED on
I (3266) example: Turn the LED off
I (4266) example: Turn the LED on
I (5266) example: Turn the LED off
...
2.5 代码解析
本示例代码的核心是配置一个 GPIO 引脚为输出模式,并在一个无限循环中交替设置其电平为高和低,从而实现 LED 的闪烁效果。
-
包含头文件
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"driver/gpio.h
:ESP-IDF GPIO 驱动的头文件,提供了配置和操作 GPIO 所需的所有函数和类型定义,如gpio_config()
和gpio_set_level()
。freertos/FreeRTOS.h
和freertos/task.h
:FreeRTOS 的核心头文件。这里主要用于调用vTaskDelay()
函数,以实现精确且高效的延时,这在实时操作系统中是标准做法。esp_log.h
:ESP-IDF 的日志库,用于在串口监视器中打印信息,方便调试和观察程序运行状态。
-
定义 GPIO 引脚
static const gpio_num_t GPIO_OUTPUT_LED = GPIO_NUM_7;
- 这行代码定义了一个常量
GPIO_OUTPUT_LED
来表示 LED 所连接的 GPIO 引脚号。 gpio_num_t
是 ESP-IDF 中用于表示 GPIO 编号的枚举类型。GPIO_NUM_7
是该枚举中的一个取值,表示编号为 7 的通用 IO 引脚(GPIO7)。从可读性角度,建议使用GPIO_NUM_7
而不是直接写字面值7
。
备注不同芯片对 GPIO7 的可用性与限制不同,请检查你所用的开发板的引脚定义。
- 这行代码定义了一个常量
-
配置 GPIO
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_OUTPUT_LED), // 选择要配置的 GPIO
.mode = GPIO_MODE_OUTPUT, // 设置为输出模式
.pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉
.pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉
.intr_type = GPIO_INTR_DISABLE // 禁用中断
};
gpio_config(&io_conf);- 我们首先创建并初始化一个
gpio_config_t
结构体io_conf
,它像一个“配置包”,包含了所有需要的设置。 .pin_bit_mask
:这是一个位掩码,用于指定要配置哪些 GPIO 引脚。每一位 (bit) 对应一个 GPIO 编号。1ULL
:表示一个 64 位无符号长整型(unsigned long long)的数字 1。在二进制中,它是0x00...0001
。<<
:是 C 语言中的左移运算符。1ULL << N
的意思就是将这个数字 1 的二进制表示向左移动 N 位。- 在本例中,
GPIO_OUTPUT_LED
的值是7
,所以1ULL << 7
会将0x00...0001
左移 7 位,得到0x00...10000000
(即第 7 位为 1,其余为 0)。 这个结果就是“掩码”。gpio_config()
函数会检查这个掩码的每一位,如果某一位是 1,就将该配置应用到对应的 GPIO 引脚上。
.mode = GPIO_MODE_OUTPUT
:将引脚模式设置为数字输出。.pull_up_en
和.pull_down_en
:禁用内部上拉和下拉电阻。对于驱动 LED 这种简单的推挽输出场景,通常不需要它们。.intr_type = GPIO_INTR_DISABLE
:禁用中断功能,因为我们只进行输出操作,不需要响应外部信号。- 最后,调用
gpio_config(&io_conf)
函数,将这个配置应用到指定的 GPIO 引脚上。
提示配置 GPIO 有两种主要方式:
-
使用
gpio_config_t
结构体(推荐): 这是最常用、最高效的方法。您可以将引脚掩码、I/O 模式、上下拉等所有参数打包到一个gpio_config_t
结构体中,然后只需调用一次gpio_config()
函数,就能同时为一个或多个 GPIO 完成配置。 -
使用独立函数: ESP-IDF 也提供了一系列独立的 API 函数,如
gpio_set_direction()
、gpio_set_pull_mode()
等,用于单独设置某个引脚的特定属性。这种方式更灵活,适合在运行时动态修改或进行简单的单项设置。对于本教程的示例,如果采用独立函数进行配置,代码如下:
gpio_reset_pin(GPIO_OUTPUT_LED); // 重置引脚
gpio_set_direction(GPIO_OUTPUT_LED, GPIO_MODE_OUTPUT); // 设置引脚为输出模式
- 我们首先创建并初始化一个
-
主循环:控制 LED 闪烁
while (1) {
// 设置 GPIO 高电平
ESP_LOGI(TAG, "Turn the LED on");
gpio_set_level(GPIO_OUTPUT_LED, 1);
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒
// 设置 GPIO 低电平
ESP_LOGI(TAG, "Turn the LED off");
gpio_set_level(GPIO_OUTPUT_LED, 0);
vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒
}while (1)
创建了一个无限循环,确保app_main
函数不会退出,并使其中的代码持续运行。gpio_set_level(GPIO_OUTPUT_LED, 1)
:调用此函数将 GPIO 7 的电平设置为高电平(通常是 3.3V)。根据电路连接,这会点亮 LED。gpio_set_level(GPIO_OUTPUT_LED, 0)
:将 GPIO 7 的电平设置为低电平(0V),从而熄灭 LED。vTaskDelay(pdMS_TO_TICKS(1000))
:这是 FreeRTOS 提供的延时函数。它会使当前任务(主任务)暂停指定的时长。与简单的忙等待(如for
循环)不同,vTaskDelay
会让出 CPU 使用权,允许其他任务运行,是一种非常高效的延时方式。pdMS_TO_TICKS(1000)
是一个宏,用于将 1000 毫秒(1 秒)转换为 FreeRTOS 调度器所使用的“系统节拍数 (ticks)”。