ESP32-S3 IDF编程第二课:点亮一个LED灯

其实,我们一开始学单片机,都是从点灯开始的,那么esp32也不例外,我们学会了如何去编译项目以后,就可以去初步写一个属于自己的程序。

那么本次教程就是教你如何去初步点亮LED灯

什么是LED灯

LEDLight Emitting Diode(发光二极管)的缩写,是一种能将电能直接转化为光能的半导体器件。

那么如何区分正负极

长的引脚正极,短的负极

简单知道这个,在硬件上你就懂了

esp32哪些引脚是可以使用的

img11

从这张图片可以得知,这款单片机外设十分丰富,iic spi adc 之类有很多,但今天,我们主要是点灯,关注gpio就行了,任选一个gpio接口即可

把正极接入gpio,负极接到gnd就行

下面我们来写程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
* SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "driver/gpio.h"
#define LED_GPIO 21
void app_main(void)
{
gpio_config_t gpio_config1 = {0};
gpio_config1.pin_bit_mask = (1ULL << LED_GPIO);
gpio_config1.mode = GPIO_MODE_OUTPUT;
gpio_config1.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config1.pull_down_en = GPIO_PULLDOWN_DISABLE;
gpio_config(&gpio_config1);
while(1){
gpio_set_level(LED_GPIO, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(LED_GPIO, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}

}

这个就是主要代码了

首先,我们得引用#include “driver/gpio.h” 这个代码是控制gpio的基础

然后我们需要定义个引脚#define LED_GPIO 21 这个就是使用了gpio 21 的引脚,当然,要根据需求进行修改

然后,我们需要定义结构体,这个于stm32大体上有点类似

gpio_config_t gpio_config = {0};这个是初始化结构体

1
2
3
4
gpio_config.pin_bit_mask = (1ULL << LED_GPIO);
gpio_config.mode = GPIO_MODE_OUTPUT;
gpio_config.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config.pull_down_en = GPIO_PULLDOWN_DISABLE;

其中,pin_bit_mask是个位移的gpio位置,你位移多少,gpio在哪里

mode是模式,利用vscode查看定义,我们能知道这些

1
2
3
4
5
6
7
8
typedef enum {
GPIO_MODE_DISABLE = GPIO_MODE_DEF_DISABLE, /*!< GPIO mode : disable input and output */
GPIO_MODE_INPUT = GPIO_MODE_DEF_INPUT, /*!< GPIO mode : input only */
GPIO_MODE_OUTPUT = GPIO_MODE_DEF_OUTPUT, /*!< GPIO mode : output only mode */
GPIO_MODE_OUTPUT_OD = ((GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output only with open-drain mode */
GPIO_MODE_INPUT_OUTPUT_OD = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /*!< GPIO mode : output and input with open-drain mode*/
GPIO_MODE_INPUT_OUTPUT = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT)), /*!< GPIO mode : output and input mode */
} gpio_mode_t;
  1. GPIO_MODE_DISABLE
  • 含义:禁用输入和输出功能
  • 用途:将引脚设置为高阻态,既不驱动也不读取
  • 典型场景:初始化前或不需要使用的引脚,节省功耗
  1. GPIO_MODE_INPUT
  • 含义:仅输入模式
  • 用途:读取外部信号的电平状态(高/低)
  • 典型场景:读取按键状态、传感器信号、检测电平变化
  1. GPIO_MODE_OUTPUT
  • 含义:仅输出模式(推挽输出)
  • 用途:主动驱动引脚为高电平或低电平
  • 典型场景:控制 LED、驱动继电器、输出控制信号
  1. GPIO_MODE_OUTPUT_OD (Open-Drain 开漏输出)
  • 含义:开漏输出模式
  • 工作原理
    • 输出 0 时:引脚被拉低到 GND
    • 输出 1 时:引脚处于高阻态(需要外部上拉电阻)
  • 用途
    • I2C 总线(SDA 和 SCL 引脚)
    • 多设备共享同一总线
    • 电平转换电路
  • 注意:通常需要外接上拉电阻
  1. GPIO_MODE_INPUT_OUTPUT_OD (开漏双向)
  • 含义:既能输入又能输出,输出为开漏模式
  • 用途
    • I2C 总线(需要双向通信)
    • 1-Wire 总线
    • 多主设备通信
  • 特点:可以读取外部信号,也能输出,但输出高时需要外部上拉
  1. GPIO_MODE_INPUT_OUTPUT (标准双向)
  • 含义:标准推挽输入输出模式
  • 用途
    • 需要既能读取又能驱动的普通 GPIO
    • SPI 总线(MOSI、MISO)
    • 控制带反馈的设备
  • 特点:可以主动输出高低电平,也能读取输入状态

然后目前我们使用GPIO_MODE_OUTPUT也就是推挽输出

gpio_config.pull_up_en = GPIO_PULLUP_DISABLE;
gpio_config.pull_down_en = GPIO_PULLDOWN_DISABLE;

这个是设置上下拉的,上拉简单说就是保持高电平,下拉就是保持在低电平,注意低电平没有绝对的0v,只是电压相对较低

循环函数

1
2
3
4
gpio_set_level(LED_GPIO, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(LED_GPIO, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);

这个是控制led闪烁的

gpio_set_level(LED_GPIO, 1);就是高电平,反之低电平

vTaskDelay(1000 / portTICK_PERIOD_MS);就是延迟1秒

然后编译

image-20260406130845087

奇怪,编译报错了,提示没有那个头文件

其实问题很简单,就是没有在main/CmakeLists.txt定义

idf_component_register(SRCS “hello_world_main.c”

​ PRIV_REQUIRES spi_flash

​ INCLUDE_DIRS “”)

只需要这样

idf_component_register(SRCS “hello_world_main.c”

​ PRIV_REQUIRES spi_flash driver

​ INCLUDE_DIRS “”)

就可以了

重新编译就成功了

然后像之前那样,写入到设备就可以了

6F2BF743-1B2B-44E7-961C-0407E233DFDB