yahboom
HomeLearn
Solution
Blog
Online Store
About Us
EN/中文
ESP32 Core Board📖
1. ESP32 Introduction
  • 1. ESP32S3 Overview
  • 2. Environment Setup Introduction
  • 3. Dev Board Introduction
2. ESP-IDF Development Tutorial
1. Before Development
  • 1. Environment Setup (Windows)
  • 2. Environment Setup (Linux)
  • 3. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. DMA
  • 8. ADC
  • 9. PWM Breathing LED
  • 10. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. PSRAM External Memory Experiment
  • 5. Flash Read and Write Experiment
  • 6. USB Emulated Mass Storage Experiment
4. FreeRTOS operating system
  • 1.FreeRTOS Core Concepts Theory
  • 2.Task Creation and Management
  • 3.Queue
  • 4.Binary Semaphore
  • 5.Mutex
  • 6.Event Groups
  • 7.Software Timer
  • 8.Task Scheduler
  • 9.Low Power Mode
  • 10.Deadlock
  • 11.Priority Inversion
5. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. Socket Programming Basics
  • 9. HTTP Client Experiment
  • 10. HTTP Server Experiment
  • 11. MQTT IoT Communication Protocol
  • 12. WIFI OTA Upgrade
  • 13. Bluetooth Fundamentals
  • 14. Bluetooth Slave Mode
  • 15. Bluetooth Master Mode
6. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
7. Xiaozhi AI Voice
  • 1. Burn Xiaozhi Firmware
  • 2. Network and Configuration
  • 3. AI Agent Settings
  • 4. Program Analysis
  • 5. Free Chat
3. Arduino Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. ESP_TIMER
  • 5. GPTIMER
  • 6. Watchdog Timer
  • 7. ADC
  • 8. PWM Breathing LED
  • 9. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication
  • 2. I2C OLED Display
  • 3. SPI Bus Communication
  • 4. Flash Read and Write
  • 5. USB Emulated Mass Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Server Experiment
  • 5. UDP Client Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT IoT Communication Protocol
  • 11. WIFI OTA Upgrade
  • 12. Bluetooth Fundamentals
  • 13. Bluetooth Slave Mode
  • 14. Bluetooth Master Mode
5. Audio Applications
  • 1.I2S Microphone Recording and U-Disk Playback
  • 2.I2S Audio Playback Experiment
  • 3.Repeater Experiment
4. MicroPython Development Course
1. Before Development
  • 1. Environment Setup
  • 2. Build and Flash
  • 3. Thonny IDE
2. Basic Peripherals
  • 1. LED Control
  • 2. Button Detection
  • 3. Peripheral Interrupts
  • 4. TIMER_IT
  • 5. Watchdog Timer
  • 6. ADC
  • 7. PWM Breathing LED
  • 8. RGB LED Effects
3. Serial Communication and Storage System
  • 1. Serial UART Communication Experiment
  • 2. I2C_OLED Display Experiment
  • 3. SPI Bus Communication Experiment
  • 4. Flash Read and Write Experiment
  • 5. Print Storage
4. Network Protocols and Wireless Communication
  • 1. WIFI Network Basics
  • 2. WIFI STA Mode
  • 3. WIFI AP Mode
  • 4. UDP Client Experiment
  • 5. UDP Server Experiment
  • 6. TCP Client Experiment
  • 7. TCP Server Experiment
  • 8. HTTP Client Experiment
  • 9. HTTP Server Experiment
  • 10. MQTT
  • 11. Bluetooth Fundamentals
  • 12. Bluetooth Slave Mode
  • 13. Bluetooth Master Mode
5. Audio Applications
  • 1. I2S Audio Playback Experiment
  • 2. Repeater Experiment
Download
  • Code
  • Hardware_Info
  • 3D_Model_File
  • Software_Tools
  • VMware
  • VM_File
Download ZIP

Welcome to ESP32 Core Board repository

1. LED Control

LED Control


LED Control1. GPIO Overview2. Core Concepts2.1 Common-Anode LED Connection2.2 Layered Architecture3. ESP32-S3 GPIO Hardware Characteristics4. Project Architecture and Flow5. Hardware Dependencies6. Source Code Analysis6.1 LED Driver Layer — led.h: Macro Encapsulation6.2 LED Driver Layer — led.c: Initialization6.2.1 gpio_config_t Structure6.2.2 mode — Six GPIO Operating Modes6.2.3 pull_up_en / pull_down_en — Internal Pull-up/Pull-down6.3 Application Layer — main.c: Program Entry6.4 Build Files — CMakeLists.txt7. Operation Flow7.1 Build and Flash7.2 Expected Behavior7.3 Verification Methods8. Common Issues


1. GPIO Overview

GPIO (General Purpose Input/Output) is the most fundamental peripheral interface of MCUs. Through software configuration, chip pins can be set to Input mode (reading external signals) or Output mode (driving external circuits).

This experiment controls two onboard LEDs to blink synchronously at 1Hz, demonstrating the basic workflow of GPIO output control. The code uses a component-based layered design, encapsulating hardware operations into semantic macros, so upper-layer applications don't need to worry about pin numbers or polarity.

Typical GPIO application scenarios:

Application TypeExample
Digital OutputLED blinking, relay control, buzzer driving
Digital InputButton detection, switch state reading, sensor digital signals
Bidirectional I/OI2C bus (SDA), single-wire protocols (OneWire / HDQ)
Interrupt InputExternal event triggering (see 3. Peripheral Interrupts)
Analog InputADC sampling (GPIO set to DISABLE, driven by ADC)
Alternate FunctionsUART / SPI / I2C / PWM peripheral signals (configured via IO MUX)

2. Core Concepts

2.1 Common-Anode LED Connection

This board uses Common-Anode LED connection:

xxxxxxxxxx
VDD (3.3V) ──→ LED Anode ──→ LED Cathode ──→ Current-Limiting Resistor ──→ GPIO Pin
GPIO Output LevelLED StatePrinciple
Low (0V)ONCurrent flows from VDD through LED and resistor into GPIO (source→sink), forming a loop
High (3.3V)OFFGPIO and VDD are at same potential, no current flows through LED

Core Understanding: In common-anode connection, GPIO output low = LED ON. This is opposite to the intuition "1=on", so semantic macros are crucial—LED0(0) means "turn on LED0", and the macro internally translates to gpio_set_level(GPIO43, 0).

2.2 Layered Architecture

This project follows the hardware abstraction layering principle:

xxxxxxxxxx
┌────────────────────────────────┐
│  app_main()                    │  ← Application layer: only cares about LED0_TOGGLE() semantics
│  Doesn't care about pin numbers, polarity, or driver details     │
├────────────────────────────────┤
│  components/LED/led.h / led.c  │  ← LED driver layer: semantic macros + initialization
│  LED0(0)=ON, LED0(1)=OFF      │     Encapsulates polarity, pins, and configuration flow
├────────────────────────────────┤
│  driver/gpio.h                 │  ← Driver layer: gpio_set_level / gpio_config
│  gpio_config() / set/get       │     IDF abstracts GPIO hardware operations
├────────────────────────────────┤
│  ESP32-S3 GPIO Hardware        │  ← Physical layer: IO MUX + Matrix + Pad
└────────────────────────────────┘

Benefits of Layering:

  1. Changing pins only requires modifying macros in led.h, zero changes to application code

  2. Semantic macro LED0(0) is more intuitive than gpio_set_level(43, 0), eliminating confusion about "why is 0 ON"

  3. LED driver component is reusable—all example routines needing LED operations can reference components/LED/


3. ESP32-S3 GPIO Hardware Characteristics

CharacteristicParameter
Available GPIO Count~45 (limited by package and internal multiplexing)
Output Drive CurrentMax 40mA (recommended ≤20mA for long-term use)
Input Voltage Range0 ~ 3.3V (Cannot connect 5V! Level shifting required)
Internal Pull-up/Pull-down~45kΩ (weak)
Output Drive Strength4 levels adjustable (~5 / 10 / 20 / 40 mA)
Interrupt SupportEdge triggering + level triggering (see 3.NVIC chapter)
IO MUXEach pin can be mapped to different peripheral signals (UART/SPI/I2C/PWM, etc.)
GPIO Exchange MatrixOn-chip programmable signal routing network, peripheral signals can be mapped to almost any GPIO
Direct Output Pathgpio_set_level bypasses IO MUX and exchange matrix, taking the fastest path
RTC GPIOGPIO0~21 support maintaining level and waking during Deep Sleep
Level Holdgpio_hold_en(pin) can lock level during sleep

Special Pin Reminders:

PinSpecialPrecaution
GPIO0Strapping PinLow during power-on = enters download mode, external circuit should not forcefully pull down
GPIO3JTAG (TMS)Affects JTAG debugging function during power-on
GPIO45/46Strapping PinsAffects startup voltage configuration
GPIO26-32Connected to internal Flash/PSRAMUsually unavailable (depends on chip package)

4. Project Architecture and Flow

xxxxxxxxxx
app_main()
  ├─ nvs_flash_init()      ← Initialize NVS (erase and rebuild if failed)
  │
  ├─ led_init()            ← Initialize GPIO43 / GPIO44 one by one
  │   ├─ gpio_config(GPIO43)  Push-pull bidirectional, no pull-up/down, no interrupt
  │   ├─ gpio_config(GPIO44)  Push-pull bidirectional, no pull-up/down, no interrupt
  │   ├─ LED0(1)               Initial: output high = OFF
  │   └─ LED1(1)               Initial: output high = OFF
  │
  └─ while(1) Main Loop
      ├─ LED0_TOGGLE()     Read level → invert → write
      ├─ LED1_TOGGLE()     Read level → invert → write
      └─ vTaskDelay(500ms) Delay 500ms (release CPU)

Source File Structure:

xxxxxxxxxx
1.LED/
├── CMakeLists.txt               # Top-level build file
├── main/
│   ├── CMakeLists.txt           # main component (depends on esp_driver_gpio / nvs_flash / LED)
│   └── main.c                   # Application entry app_main()
└── components/
    └── LED/
        ├── CMakeLists.txt       # LED component (depends on esp_driver_gpio)
        ├── led.h                # Pin macros + control macros + function declarations
        └── led.c                # GPIO initialization implementation

5. Hardware Dependencies

Hardware Connection:

PinPeripheralDescription
GPIO43LED0Common-anode, low level turns on
GPIO44LED1Common-anode, low level turns on

Dependencies: esp_driver_gpio, nvs_flash, freertos, LED


6. Source Code Analysis

6.1 LED Driver Layer — led.h: Macro Encapsulation

The header file defines pin numbers and semantic control macros, which is the core abstraction of the entire driver:

xxxxxxxxxx
// ============ Pin definitions ============
#define LED0_GPIO_PIN   GPIO_NUM_43
#define LED1_GPIO_PIN   GPIO_NUM_44

// ============ Output control macros (1=OFF, 0=ON) ============
#define LED0(x) do { \
    x ? gpio_set_level(LED0_GPIO_PIN, 1) : \
        gpio_set_level(LED0_GPIO_PIN, 0); \
} while (0)

// ============ Toggle macros ============
#define LED0_TOGGLE() do { \
    gpio_set_level(LED0_GPIO_PIN, !gpio_get_level(LED0_GPIO_PIN)); \
} while (0)

Why wrap macros with do { ... } while(0)? This is the standard safe写法 for multi-statement C macros. Without wrapping, if (cond) LED0(0); else ... would cause compilation errors due to semicolon parsing. do-while(0) ensures the macro is a complete syntactic unit in any control flow context.

LED0_TOGGLE() three-step process:

  1. gpio_get_level() — Read current level (HIGH=1 / LOW=0)

  2. ! — Invert

  3. gpio_set_level() — Write inverted level

6.2 LED Driver Layer — led.c: Initialization

led_init() is the most core function of this experiment—configuring GPIO hardware registers, determining the pin's working mode. Let's break it down line by line and also explain ESP32-S3 GPIO configuration options.

xxxxxxxxxx
void led_init(void)
{
    gpio_config_t gpio_init_struct = {0};

    gpio_init_struct.intr_type    = GPIO_INTR_DISABLE;
    gpio_init_struct.mode         = GPIO_MODE_INPUT_OUTPUT;
    gpio_init_struct.pull_up_en   = GPIO_PULLUP_DISABLE;
    gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE;

    gpio_init_struct.pin_bit_mask = 1ull << LED0_GPIO_PIN;
    ESP_ERROR_CHECK(gpio_config(&gpio_init_struct));

    gpio_init_struct.pin_bit_mask = 1ull << LED1_GPIO_PIN;
    ESP_ERROR_CHECK(gpio_config(&gpio_init_struct));

        LED0(1);   // Initial OFF
        LED1(1);   // Initial OFF
}

6.2.1 gpio_config_t Structure

ESP32-S3 GPIO configuration uses independent struct fields: mode, pull-up/down, interrupt, and pin are four independent dimensions. Fill in → call gpio_config() to write to hardware registers at once. This is more flexible than STM32's traditional approach of encoding 8 modes + pull-up/down into enum combinations.

xxxxxxxxxx
typedef struct {
    uint64_t      pin_bit_mask;   // Pin bitmask, bit N=1 means GPIO_N is selected
    gpio_mode_t   mode;           // GPIO mode, 6 choices
    gpio_pullup_t pull_up_en;     // Internal pull-up (0=OFF, 1=ON)
    gpio_pulldown_t pull_down_en; // Internal pull-down (0=OFF, 1=ON)
    gpio_int_type_t intr_type;    // Interrupt type
} gpio_config_t;

6.2.2 mode — Six GPIO Operating Modes

ESP-IDF defines 6 modes. For LED blinking, we only need two, the rest are for reference:

ModeInputOutputOutput TypeTypical Use
GPIO_MODE_DISABLEDisabledDisabled—Analog input (ADC/DAC), unused pins for power saving
GPIO_MODE_INPUTEnabledDisabled—Button reading, digital sensors
GPIO_MODE_OUTPUTDisabledEnabledPush-pullLED driving (output only, no readback needed)
GPIO_MODE_OUTPUT_ODDisabledEnabledOpen-drainI2C SCL, level shifting
GPIO_MODE_INPUT_OUTPUT_ODEnabledEnabledOpen-drainI2C SDA, single-wire (OneWire)
GPIO_MODE_INPUT_OUTPUTEnabledEnabledPush-pullLED toggling (needs gpio_get_level readback)

Push-Pull Output — Internally uses PMOS + NMOS complementary pair, high and low levels are actively driven by the chip, fast transition and strong drive capability:

xxxxxxxxxx
        VDD
         │      Output 1 → PMOS conducts, NMOS turns off → pin pulled to VDD
       PMOS     Output 0 → PMOS turns off, NMOS conducts → pin pulled to GND
         ├── PAD
       NMOS     Not suitable for multiple output pins in parallel (one pulls high + one pulls low = short circuit)
         │
        GND

Open-Drain Output — Only NMOS, high level relies on external pull-up resistor, multiple devices can share bus (wire-AND):

xxxxxxxxxx
   External pull-up resistor ── VDD
         │        Output 0 → NMOS conducts → pull low
       PAD        Output 1 → NMOS turns off → external resistor pulls high
         │
       NMOS       Suitable for I2C, single-wire multi-device sharing scenarios
         │
        GND

This project selects GPIO_MODE_INPUT_OUTPUT (push-pull bidirectional): Compared to GPIO_MODE_OUTPUT, it adds input enable, ensuring LED0_TOGGLE() calling gpio_get_level() reliably reads back the current level.

6.2.3 pull_up_en / pull_down_en — Internal Pull-up/Pull-down

ESP32-S3 has built-in ~ 45kΩ weak pull-up/pull-down resistors:

ValueEffect
GPIO_PULLUP_DISABLE (0)Pull-up disabled
GPIO_PULLUP_ENABLE (1)Internal ~45kΩ pull-up to VDD
GPIO_PULLDOWN_DISABLE (0)Pull-down disabled
GPIO_PULLDOWN_ENABLE (1)Internal ~45kΩ pull-down to GND

Typical combinations:

PUPDEquivalentUse Case
00FloatingOutput pins—driven by GPIO, no pull-up/down needed
10Pull-up inputButton connected to GND, reads high when not pressed
01Pull-down inputButton connected to VDD, reads low when not pressed

This project sets PU=0, PD=0: LEDs are actively driven by GPIO push-pull output, level is always defined, pull-up/down only adds unnecessary static power consumption.

6.3 Application Layer — main.c: Program Entry

xxxxxxxxxx
void app_main(void)
{
    // ===== NVS Initialization =====
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ESP_ERROR_CHECK(nvs_flash_init());
    }

    // ===== LED Initialization =====
    led_init();

    // ===== Main Loop =====
    while (1) {
        LED0_TOGGLE();
        LED1_TOGGLE();
        vTaskDelay(pdMS_TO_TICKS(500));
    }
}

NVS Initialization: nvs_flash_init() initializes ESP-IDF's key-value storage system. Wi-Fi configuration, PHY calibration data, etc. are stored in NVS partition. Even if not using Wi-Fi, initialization is recommended (many IDF subsystems depend on it).

Error CodeMeaningHandling
ESP_OKSuccessNo action needed
ESP_ERR_NVS_NO_FREE_PAGESNo free pages in partition (common on first flash)Erase and retry
ESP_ERR_NVS_NEW_VERSION_FOUNDPartition table version changedErase and retry

Why use vTaskDelay() instead of bare-metal delay()? vTaskDelay() suspends the current task to Blocked state for 500ms, during which the CPU can execute other tasks. Bare-metal delay is busy-waiting, which should always be avoided under RTOS. pdMS_TO_TICKS(500) converts 500ms to FreeRTOS tick count.

6.4 Build Files — CMakeLists.txt

LED Component (components/LED/CMakeLists.txt):

xxxxxxxxxx
idf_component_register(
    SRCS "led.c"
    INCLUDE_DIRS "."
    REQUIRES esp_driver_gpio)
  • SRCS — Component source files

  • INCLUDE_DIRS — Header file search path (. = current directory)

  • REQUIRES — Depends on esp_driver_gpio

main Component (main/CMakeLists.txt):

xxxxxxxxxx
idf_component_register(
    SRCS "main.c"
    INCLUDE_DIRS "."
    REQUIRES esp_driver_gpio nvs_flash LED)

After declaring dependency on LED, CMake automatically finds components/LED/ and links it.


7. Operation Flow

7.1 Build and Flash

For detailed flashing process, see: 1. Before Development → 3. Build and Flash

7.2 Expected Behavior

  • Both LEDs blink synchronously at 1Hz

  • ON 500ms → OFF 500ms → repeat

  • No serial log output (this experiment has no printf / ESP_LOGI calls)

    LED灯闪烁例程(亮)

    LED灯闪烁例程(灭)

7.3 Verification Methods

Test ItemMethodExpected Result
LED0 normalObserve GPIO43 LEDStable blinking, period ~1s
LED1 normalObserve GPIO44 LEDBlinks synchronously with LED0
Frequency checkTime 10 blinks with phone stopwatch~5 seconds (10 half-cycles)

8. Common Issues

PhenomenonCauseSolution
LED doesn't light upGPIO configuration error / pin multiplexing conflictCheck if pin_bit_mask matches hardware
LED brightness very lowGPIO drive strength insufficientCall gpio_set_drive_cap(pin, GPIO_DRIVE_CAP_1)
LED stays on constantlyCommon-anode/common-cathode reversedConfirm hardware connection, adjust macro logic (0↔1)
Doesn't work after flashingNVS initialization failure causing abortFirst flash automatically erases and rebuilds, this is normal
Blinking frequency inaccuratevTaskDelay has ±1 tick jitterNo effect on LED blinking; use esp_timer for precise timing
No response after program startsNo while(1) loopUnder RTOS, system restarts after app_main exits
GPIO configuration failedpin_bit_mask didn't use 1ull1 << 43 overflows, must write 1ull << 43
Build and Flash
Button Detection

COMPANY

  • About us
  • Team Style
  • Blog

LEARNING & EXPLORATION

  • Tutorials
  • Edge AI hardware
  • Educational robots
  • Embedded intelligent hardware

WHERE TO BUY

  • Yahboom Online Store
  • Amazon
  • Alibaba
  • AliExpress
  • Mercado

TECHNOLOGY SUPPORT

  • Email: support@yahboom.com

BE A DISTRIBUTOR

  • Email: sales@yahboom.com
QR Code
QR Code

Copyright © 2017-2026 Yahboom. All Rights Reserved.

EN/中文