ESP-IDF 开发
本章节包含以下内容,请按需阅读:
ESP-IDF 入门教程
初次接触 ESP32 ESP-IDF 开发,想要快速上手?我们为您准备了一套通用的 入门教程。
- 第0节 认识 ESP32
- 第1节 搭建环境
- 第2节 运行实例
- 第3节 创建项目
- 第4节 使用组件
- 第5节 调试程序
- 第6节 FreeRTOS
- 第7节 驱动外设
- 第8节 Wi-Fi 编程
- 第9节 BLE 编程
请注意:该教程使用 ESP32-S3-Zero 作为教学示例,所有硬件代码均基于其引脚布局。在动手实践前,建议您对照手中的开发板引脚图,确认引脚配置无误。
配置 ESP-IDF 开发环境
ESP32-C5-Touch-LCD-1.69 示例工程需要 ESP-IDF v5.3 或更新版本。
以下内容以 Windows 系统为例,使用 VS Code + ESP-IDF 扩展 的方式进行开发。Mac/Linux 用户请参考 官方说明。
此部分图示以安装 ESP-IDF V5.5.2 为例示范,安装时请选用与您开发板示例匹配的 ESP-IDF 版本。
安装 ESP-IDF 开发环境
-
前往 ESP-IDF Installation Manager 下载 ESP-IDF 安装管理器。这是乐鑫最新推出的跨平台安装工具,下文将演示如何使用其离线安装功能。
在页面中点击 Offline Installer 标签,然后在筛选栏中选择 Windows 操作系统和你需要的 ESP-IDF 版本(图示仅为参考,请以实际为准)。

确认选择无误后,点击下载按钮。浏览器将自动同时下载两个文件:一个是 ESP-IDF 离线整合包(.zst),另一个是 ESP-IDF 安装器(.exe)。

请耐心等待两个文件下载完成。
-
下载完成后,双击运行 ESP-IDF 安装器(eim-gui-windows-x64.exe)。
启动后,可在右上角将界面语言切换为中文。

安装工具会自动检测同一目录下是否存在离线整合包。点击 从存档安装。

接下来,选择安装路径。建议使用默认路径;若需自定义,请确保路径中不包含中文或空格。确认无误后,点击 开始安装。

-
当看到如下界面时,表示 ESP-IDF 已安装成功。

-
建议同时安装驱动程序。点击 完成安装,然后点击 安装驱动程序。

安装 Visual Studio Code 与 ESP-IDF 扩展
-
下载并安装 Visual Studio Code。
-
安装时建议勾选 通过 Code 打开操作添加到 Windows 资源管理器文件上下文菜单,以便快速打开项目文件夹。
-
在 VS Code 中,点击侧边活动栏中的
扩展图标(或使用快捷键 Ctrl + Shift + X)打开 扩展 视图。
-
在搜索框中输入 ESP-IDF,找到 ESP-IDF 扩展并点击安装。

-
当 ESP-IDF 扩展版本 ≥ 2.0 时,扩展会自动检测并识别上述步骤中安装的 ESP-IDF 环境,无需手动配置。
若安装失败或需重装,可尝试删除 C:\Users\%Username%\esp 与 C:\Users\%Username%\.espressif 后重试。
编译和烧录
进入 ESP-IDF 示例工程目录后执行:
cd example/esp-idf
idf.py build flash monitor
如果需要指定串口,请将 COMx 替换为实际串口号,例如 COM5:
idf.py -p COMx build flash monitor
示例程序
ESP-IDF 示例位于工程的 example/esp-idf/main/examples 目录,工程入口为 example/esp-idf/main/main.c。同一时间只保留一个示例或应用宏为 1,其他宏保持为 0。
#define EXAMPLE_RGB_TEST 1
#define EXAMPLE_MIC_SPEAKER_TEST 0
#define EXAMPLE_IMU_TEST 0
#define EXAMPLE_BAT_TEST 0
#define EXAMPLE_RTC_TEST 0
#define EXAMPLE_LVGL_DEMO_TEST 0
#define EXAMPLE_Brookesia_TEST 0
#define APPS_WIFI_Connect 0
#define APPS_Clock 0
#define APPS_Honeycomb_Demo 0
默认配置运行 RGB 刷色测试。如需运行其他示例,将目标示例对应宏改为 1,并将其他宏改为 0。
| 示例程序 | 基础例程说明 |
|---|---|
| 01_RGB_Test | 屏幕刷色测试 |
| 02_Mic_Speaker_Test | 麦克风与扬声器测试 |
| 03_IMU_Test | IMU 测试 |
| 04_Bat_Test | 电池检测测试 |
| 05_RTC_Test | RTC 测试 |
| 06_LVGL_Demo_Test | LVGL 示例测试 |
| 07_Brookesia_Test | Brookesia 示例测试 |
| 08_WIFI_Connect | Wi-Fi 配网应用 |
| 09_Clock_Display | 时钟显示应用 |
| 10_Honeycomb_Demo | 蜂窝图标交互演示 |
01_RGB_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
RGB 刷色测试代码
void rgb_test_run(void)
{
static const uint16_t colors[] = { RGB565_RED, RGB565_GREEN, RGB565_BLUE };
static const char *color_names[] = { "red", "green", "blue" };
bsp_display_cfg_t display_cfg = {0};
esp_lcd_panel_handle_t panel = NULL;
uint16_t *draw_buffer = NULL;
size_t color_index = 0;
ESP_ERROR_CHECK(bsp_display_new(&display_cfg, &panel, NULL));
ESP_ERROR_CHECK(bsp_display_brightness_init());
ESP_ERROR_CHECK(bsp_display_brightness_set(100));
draw_buffer = heap_caps_malloc(BSP_LCD_H_RES * RGB_TEST_BLOCK_LINES * sizeof(uint16_t), MALLOC_CAP_DMA);
while (true) {
ESP_LOGI(TAG, "show color: %s", color_names[color_index]);
rgb_test_draw_color(panel, draw_buffer, colors[color_index]);
vTaskDelay(pdMS_TO_TICKS(RGB_TEST_DELAY_MS));
color_index++;
if (color_index >= (sizeof(colors) / sizeof(colors[0]))) {
color_index = 0;
}
}
}
代码解释
bsp_display_new(&display_cfg, &panel, NULL):初始化 LCD 面板,返回 panel 句柄。bsp_display_brightness_init()/bsp_display_brightness_set(100):初始化并设置背光亮度为 100%。heap_caps_malloc(..., MALLOC_CAP_DMA):分配 DMA 兼容的绘制缓冲区,用于批量像素传输。rgb_test_draw_color(panel, draw_buffer, colors[color_index]):将指定颜色按 20 行分块写入 LCD,逐块刷新整屏。vTaskDelay(pdMS_TO_TICKS(RGB_TEST_DELAY_MS)):每种颜色停留 1 秒。
运行效果
- 屏幕依次显示红、绿、蓝三种颜色,每种停留 1 秒后切换。
- 串口每秒输出一次当前颜色名称。
02_Mic_Speaker_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
麦克风回环播放代码
void mic_speaker_test_run(void)
{
uint8_t audio_buffer[MIC_SPEAKER_TEST_FRAME_BYTES];
esp_codec_dev_handle_t speaker = NULL;
esp_codec_dev_handle_t microphone = NULL;
esp_codec_dev_sample_info_t codec_fs = {
.sample_rate = BSP_AUDIO_OUTPUT_SAMPLE_RATE_HZ,
.bits_per_sample = 16,
.channel = 1,
};
ESP_ERROR_CHECK(bsp_audio_init(NULL));
speaker = bsp_audio_codec_speaker_init();
microphone = bsp_audio_codec_microphone_init();
ESP_ERROR_CHECK(esp_codec_dev_open(speaker, &codec_fs));
ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(speaker, MIC_SPEAKER_TEST_VOLUME));
ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(microphone, MIC_SPEAKER_TEST_GAIN));
ESP_LOGI(TAG, "microphone loopback to speaker");
while (true) {
ESP_ERROR_CHECK(esp_codec_dev_read(microphone, audio_buffer, sizeof(audio_buffer)));
ESP_ERROR_CHECK(esp_codec_dev_write(speaker, audio_buffer, sizeof(audio_buffer)));
}
}
代码解释
bsp_audio_init(NULL):初始化 I2S 总线和 ES8311 编解码器。bsp_audio_codec_speaker_init()/bsp_audio_codec_microphone_init():分别初始化扬声器和麦克风编解码设备。esp_codec_dev_open(speaker, &codec_fs):以 16bit 单声道格式打开扬声器设备。esp_codec_dev_set_out_vol(speaker, 70):设置扬声器音量为 70。esp_codec_dev_set_in_gain(microphone, 18):设置麦克风增益为 18dB。esp_codec_dev_read(...)/esp_codec_dev_write(...):从麦克风读取 1024 字节数据并写入扬声器,实现实时回环。
运行效果
- 串口输出
microphone loopback to speaker。 - 对着麦克风说话,可从扬声器实时听到回放声音。
03_IMU_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
QMI8658 数据读取代码
void imu_test_run(void)
{
qmi8658_data_t data = {0};
ESP_ERROR_CHECK(bsp_i2c_init());
ESP_ERROR_CHECK(bsp_qmi8658_init());
while (true) {
ESP_ERROR_CHECK(bsp_qmi8658_get_data(&data));
ESP_LOGI(TAG, "accel: %.2f %.2f %.2f m/s2", data.accelX, data.accelY, data.accelZ);
ESP_LOGI(TAG, "gyro: %.2f %.2f %.2f rad/s", data.gyroX, data.gyroY, data.gyroZ);
ESP_LOGI(TAG, "temp: %.2f C", data.temperature);
vTaskDelay(pdMS_TO_TICKS(IMU_TEST_DELAY_MS));
}
}
代码解释
bsp_i2c_init():初始化 I2C 总线(SDA=GPIO8,SCL=GPIO9,400kHz)。bsp_qmi8658_init():初始化 QMI8658 六轴传感器,I2C 地址 0x6B。bsp_qmi8658_get_data(&data):读取加速度、陀螺仪和温度数据到qmi8658_data_t结构体。ESP_LOGI(TAG, ...):通过串口输出加速度(m/s²)、陀螺仪(rad/s)和温度(℃)数据。vTaskDelay(pdMS_TO_TICKS(IMU_TEST_DELAY_MS)):按宏设定的间隔读取一次数据。
运行效果
- 串口每 500ms 输出一行加速度、陀螺仪和温度数据。
- 轻微倾斜或转动开发板时,数据会随姿态变化。

04_Bat_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
- 连接锂电池到开发板。
代码分析
电池信息读取与显示代码
void bat_test_run(uint16_t battery_capacity_mah)
{
bsp_bat_info_t bat_info = {0};
lv_display_t *display = NULL;
lv_obj_t *label = NULL;
display = bsp_display_start();
ESP_ERROR_CHECK(bsp_display_brightness_set(100));
ESP_ERROR_CHECK(bsp_bat_init(battery_capacity_mah));
ESP_ERROR_CHECK(bsp_display_lock(0));
label = lv_label_create(lv_screen_active());
lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10);
bsp_display_unlock();
while (true) {
ret = bsp_get_bat_info(&bat_info);
if (ret != ESP_OK) {
ESP_LOGW(TAG, "battery info update failed: %s", esp_err_to_name(ret));
continue;
}
battery_state = (bat_info.ma > 0) ? "Charging" : ((bat_info.ma < 0) ? "Discharging" : "Idle");
ESP_ERROR_CHECK(bsp_display_lock(0));
lv_label_set_text_fmt(label,
"Battery Test\n"
"State: %s\n"
"Voltage: %u mV\n"
"Current: %d mA\n"
"SOC: %u %%\n"
"Temp: %u C\n"
"Capacity: %u mAh\n"
"%s",
battery_state,
bat_info.mv,
bat_info.ma,
bat_info.soc,
bat_info.tc,
battery_capacity_mah,
battery_note);
bsp_display_unlock();
vTaskDelay(pdMS_TO_TICKS(BAT_TEST_DELAY_MS));
}
}
代码解释
bsp_display_start():启动 LVGL 显示。bsp_bat_init(battery_capacity_mah):初始化 BQ27220 电量计,设置电池容量(入口参数传入,默认 1000mAh)。bsp_get_bat_info(&bat_info):读取电池信息(电压/电流/SOC/温度/容量等)。bsp_display_lock(0)/bsp_display_unlock():获取/释放 LVGL 互斥锁,确保 UI 操作线程安全。lv_label_set_text_fmt(label, ...):格式化并更新电池信息标签,包含状态、电压、电流、SOC、温度和容量。
运行效果
- 屏幕显示电池状态信息:状态(Charging/Discharging/Idle)、电压(mV)、电流(mA)、SOC(%)、温度(℃)、容量(mAh)。
- 串口同步输出电池数据。
- 接入电池后,电流不为 0 时状态为 Charging 或 Discharging;未接电池或充满时状态为 Idle。

05_RTC_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
RTC 初始化与时间读取代码
void rtc_test_run(void)
{
char datetime_str[32];
pcf85063a_datetime_t time = {
.year = 2026,
.month = 1,
.day = 1,
.dotw = 4,
.hour = 12,
.min = 0,
.sec = 0,
};
ESP_ERROR_CHECK(bsp_rtc_init());
ESP_ERROR_CHECK(bsp_set_rtc_time_date(time));
while (true) {
ESP_ERROR_CHECK(bsp_get_rtc_time_date(&time));
ESP_ERROR_CHECK(bsp_datetime_to_str(datetime_str, sizeof(datetime_str), time));
ESP_LOGI(TAG, "rtc time: %s", datetime_str);
vTaskDelay(pdMS_TO_TICKS(RTC_TEST_DELAY_MS));
}
}
代码解释
bsp_rtc_init():初始化 PCF85063A RTC 芯片。bsp_set_rtc_time_date(time):设置 RTC 初始时间(示例中设为 2026-01-01 12:00:00)。bsp_get_rtc_time_date(&time):从 RTC 读取当前时间到pcf85063a_datetime_t结构体。bsp_datetime_to_str(datetime_str, ...):将时间结构体转换为字符串,便于输出显示。vTaskDelay(pdMS_TO_TICKS(RTC_TEST_DELAY_MS)):按宏设定的间隔读取一次时间。
运行效果
- 串口每秒输出一次
rtc time: YYYY-MM-DD HH:MM:SS格式的时间。

06_LVGL_Demo_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
LVGL Widgets Demo 代码
void lvgl_test_run(void)
{
lv_display_t *display = NULL;
display = bsp_display_start();
ESP_ERROR_CHECK(display ? ESP_OK : ESP_FAIL);
ESP_ERROR_CHECK(bsp_display_brightness_set(100));
ESP_ERROR_CHECK(bsp_display_lock(0));
/* Running Widgets Demo */
lv_demo_widgets();
bsp_display_unlock();
ESP_LOGI(TAG, "LVGL demo started");
while (true) {
vTaskDelay(pdMS_TO_TICKS(LVGL_TEST_DELAY_MS));
}
}
代码解释
bsp_display_start():启动 LVGL 显示,初始化 LCD 面板和 LVGL 核心。bsp_display_brightness_set(100):设置背光亮度为 100%。bsp_display_lock(0)/bsp_display_unlock():获取/释放 LVGL 互斥锁,确保 UI 操作线程安全。lv_demo_widgets():启动 LVGL Widgets 演示,展示按钮、滑块、开关、图表等常用控件。
运行效果
- 屏幕显示 LVGL Widgets 演示界面,包含按钮、滑块、开关、图表等控件。
- 可通过触摸屏与界面控件进行交互。

07_Brookesia_Test
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
Brookesia Phone 初始化代码
bool init_phone_system(void)
{
ESP_Brookesia_PhoneStylesheet_t *stylesheet = nullptr;
bsp_display_lock(0);
phone = new (std::nothrow) ESP_Brookesia_Phone(display);
stylesheet = new (std::nothrow) ESP_Brookesia_PhoneStylesheet_t(ESP_BROOKESIA_PHONE_DEFAULT_DARK_STYLESHEET());
stylesheet->core.manager.flags.enable_app_save_snapshot = 0;
stylesheet->core.manager.app.max_running_num = 1;
stylesheet->home.flags.enable_recents_screen = 0;
phone->addStylesheet(stylesheet);
phone->activateStylesheet(stylesheet);
phone->setTouchDevice(bsp_display_get_input_dev());
phone->registerLvLockCallback(phone_lvgl_lock, 0);
phone->registerLvUnlockCallback(phone_lvgl_unlock);
phone->begin();
phone->installApp(&minimal_app);
bsp_display_unlock();
return true;
}
代码解释
ESP_Brookesia_Phone(display):创建 Brookesia Phone 实例,绑定 LVGL 显示。ESP_Brookesia_PhoneStylesheet_t(...):使用默认深色主题样式表。phone->addStylesheet(stylesheet)/phone->activateStylesheet(stylesheet):添加并激活样式表。phone->setTouchDevice(bsp_display_get_input_dev()):设置触摸输入设备。phone->registerLvLockCallback(...)/phone->registerLvUnlockCallback(...):注册 LVGL 锁回调,确保线程安全。phone->begin():启动 Phone 界面框架。phone->installApp(&minimal_app):安装最小化示例应用(显示 "Hello Brookesia" 文本)。
运行效果
- 屏幕显示 Brookesia Phone 界面,包含状态栏和应用启动器。
- 可点击应用图标进入 "Hello Brookesia Minimal App" 页面。

08_WIFI_Connect
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
Wi-Fi AP 与 Captive Portal 代码
void wifi_connect_test_run(void)
{
lv_display_t *display = NULL;
wifi_connect_init_stack();
wifi_connect_start_network();
ESP_ERROR_CHECK(bsp_display_set_partial_mode(true, 40));
display = bsp_display_start();
ESP_ERROR_CHECK(bsp_display_brightness_set(100));
ESP_ERROR_CHECK(bsp_display_lock(0));
wifi_connect_create_screen();
bsp_display_unlock();
while (true) {
vTaskDelay(pdMS_TO_TICKS(WIFI_CONNECT_IDLE_MS));
}
}
代码解释
wifi_connect_init_stack():初始化 NVS、网络接口和默认事件循环。wifi_connect_start_network():创建 AP(SSID 基于 MAC 地址),启动 HTTP 服务器和 DNS 服务器,实现 Captive Portal。bsp_display_set_partial_mode(true, 40):设置 LVGL 局部刷新模式,降低显存占用。wifi_connect_create_screen():创建包含二维码和状态栏的配网页面,二维码包含 AP 的 SSID 和密码。- 用户手机连接 AP 后,自动弹出配网页面,输入家庭 Wi-Fi 信息后设备自动连接。
运行效果
- 屏幕显示二维码和 AP 信息,手机扫码连接 AP 后自动弹出配网页面。
- 在配网页面输入家庭 Wi-Fi SSID 和密码,设备自动连接 Wi-Fi 并在屏幕显示连接状态和 IP 地址。

09_Clock_Display
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
时钟应用初始化代码
void clock_test_run(void)
{
lv_display_t *display = NULL;
ESP_ERROR_CHECK(bsp_i2c_init());
ESP_ERROR_CHECK(bsp_rtc_init());
ESP_ERROR_CHECK(bsp_display_set_partial_mode(true, 40));
display = bsp_display_start();
ESP_ERROR_CHECK(bsp_display_brightness_set(100));
ESP_ERROR_CHECK(bsp_display_lock(0));
clock_app_create_screen();
bsp_display_unlock();
while (true) {
vTaskDelay(pdMS_TO_TICKS(CLOCK_APP_IDLE_MS));
}
}
代码解释
bsp_i2c_init()/bsp_rtc_init():初始化 I2C 总线和 PCF85063A RTC,为时钟提供时间源。bsp_display_set_partial_mode(true, 40):设置 LVGL 局部刷新模式,降低显存占用。bsp_display_start():启动 LVGL 显示。bsp_display_brightness_set(100):设置背光亮度为 100%。bsp_display_lock(0)/bsp_display_unlock():获取/释放 LVGL 互斥锁,确保 UI 操作线程安全。clock_app_create_screen():创建时钟界面,加载 Classic 表盘并启动定时器刷新指针位置。vTaskDelay(pdMS_TO_TICKS(CLOCK_APP_IDLE_MS)):按宏设定的间隔进入空闲等待。
运行效果
- 屏幕显示模拟时钟表盘,时针、分针、秒针随 RTC 时间实时移动。
10_Honeycomb_Demo
硬件连接
- 使用 USB 线将开发板接入电脑。
代码分析
蜂窝图标布局代码
void honeycomb_demo_run(void)
{
lv_display_t *display = NULL;
display = bsp_display_start();
ESP_ERROR_CHECK(bsp_display_brightness_set(100));
ESP_ERROR_CHECK(bsp_display_lock(0));
honeycomb_demo_create_screen();
bsp_display_unlock();
while (true) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static void honeycomb_demo_drag_event_cb(lv_event_t *event)
{
lv_indev_t *indev = lv_indev_active();
lv_point_t vector = {0};
lv_indev_get_vect(indev, &vector);
honeycomb_offset.x += vector.x;
honeycomb_offset.y += vector.y;
honeycomb_demo_refresh_layout();
}
代码解释
bsp_display_start():启动 LVGL 显示。honeycomb_demo_create_screen():创建蜂窝布局界面,生成 25 个圆形图标,按 5 列蜂窝阵排列。honeycomb_demo_drag_event_cb(...):触摸拖拽回调,根据手指滑动偏移量更新图标位置。honeycomb_demo_refresh_layout():刷新图标布局,根据图标到屏幕中心的距离计算缩放比例,越靠近中心图标越大。honeycomb_demo_calculate_scale(distance):基于距离的二次方衰减计算图标缩放值,实现鱼眼放大效果。
运行效果
- 屏幕显示蜂窝状排列的彩色圆形图标,中心图标放大,边缘图标缩小。
- 手指拖拽可平移图标阵列,图标随位置动态缩放,呈现鱼眼交互效果。
