2. ESP-IDF 开发环境搭建:从零开始跑通第一个程序

说实话,搭建开发环境这件事,很多初学者觉得枯燥。但我做了这么多年嵌入式,深知一个道理:环境顺了,后面才顺。ESP-IDF 这个框架,我第一次接触时也觉得有点复杂,但摸清楚它的套路后,你会发现它其实很优雅。

本章核心目标:让你能在自己的电脑上,从零搭建 ESP-IDF 开发环境,成功编译并烧录一个 Hello World 程序,并通过串口看到它打印出来的信息。

2.1 ESP-IDF 框架到底是什么?

ESP-IDF,全称 Espressif IoT Development Framework。说白了,它是乐鑫官方为 ESP32 系列芯片打造的一套软件开发套件。

我习惯把它理解成一个「乐高积木盒」。里面装好了各种模块:Wi-Fi 驱动、蓝牙协议栈、FreeRTOS 实时操作系统、各种外设驱动库……你不需要从零去写底层寄存器操作,直接调用 API 就行。

组件 作用 我的评价
FreeRTOS 实时操作系统内核,管理任务调度 嵌入式开发的「心脏」
Wi-Fi / BLE 协议栈 无线通信的底层实现 乐鑫的看家本领,稳定
驱动库 (Driver) GPIO、I2C、SPI、UART 等外设接口 封装得很好,上手快
构建系统 (CMake) 管理编译、链接、烧录全过程 比 Makefile 清晰多了
工具链 (Toolchain) 交叉编译器,把代码变成 ESP32 能跑的机器码 装一次就行,别乱动

你想想看,如果没有这个框架,你要自己搞定上面这些东西……嗯,估计项目还没开始就结束了。

ESP-IDF 框架结构图 用户应用程序 (User App) API 接口层 (Wi-Fi / BLE / 驱动 / 文件系统) 核心组件 FreeRTOS 内核 | 协议栈 | 驱动框架 | 事件循环 硬件抽象层 (HAL / 寄存器操作) ESP32 芯片硬件 你只需要 关注这一层 ↓ 调用 API 即可 框架帮你 处理好了 ↓ 不用操心 底层细节

2.2 Windows 环境安装:一步步来

我个人建议 Windows 用户直接用乐鑫官方提供的 ESP-IDF 离线安装包。它把 Python、工具链、CMake、Git 全都打包好了,省心。

安装步骤

  1. 下载安装包:去乐鑫官网找 ESP-IDF Windows Installer,选离线版(Offline Installer)。
  2. 运行安装:一路 Next,但注意安装路径不要有中文和空格。我习惯装到 C:\esp\esp-idf。
  3. 选择组件:默认勾选就行。它会装好 ESP-IDF、工具链、以及一个叫 ESP-IDF CMD 的命令行快捷方式。
  4. 验证安装:打开 ESP-IDF CMD,输入 idf.py --version。如果看到版本号,说明成了。

我的小技巧:安装完成后,在 ESP-IDF CMD 里先跑一次 idf.py set-target esp32。这步会下载一些依赖,提前跑完,后面编译时就不会卡住了。

2.3 Linux 环境安装:命令行玩家的乐园

Linux 下安装更灵活。我平时在 Ubuntu 20.04 上开发,流程很稳定。

快速安装脚本

# 安装依赖
sudo apt-get install git wget flex bison gperf python3 python3-pip \
  python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util

# 克隆 ESP-IDF 仓库
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git

# 运行安装脚本
cd ~/esp/esp-idf
./install.sh esp32

# 设置环境变量(每次打开新终端都要执行)
. ./export.sh

这里有个坑,我踩过好几次:git clone 时一定要加 --recursive,否则子模块拉不下来。如果你已经忘了加,可以进目录跑 git submodule update --init --recursive 补救。

注意:export.sh 只在当前终端生效。我建议把它加到 ~/.bashrc 里,这样每次打开终端就不用重复执行了。

2.4 Hello World:第一个 ESP32 程序

环境搭好了,我们来写个 Hello World。这个程序会通过串口打印信息,证明你的开发板是活的。

创建项目

# 回到你的工作目录
cd ~/esp

# 从模板创建项目
cp -r $IDF_PATH/examples/get-started/hello_world ./my_hello_world
cd my_hello_world

打开 main/hello_world_main.c,核心代码就几行:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"

void app_main(void)
{
    printf("Hello world!\n");

    // 打印芯片信息
    esp_chip_info_t chip_info;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s\n",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    printf("Silicon revision %d\n", chip_info.revision);

    // 循环打印
    int counter = 0;
    while (1) {
        printf("Restarting in %d seconds...\n", 10 - counter);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        counter++;
        if (counter == 10) {
            break;
        }
    }
    printf("Restarting now.\n");
    fflush(stdout);
    esp_restart();
}

编译与烧录

# 配置目标芯片(第一次做)
idf.py set-target esp32

# 编译
idf.py build

# 烧录(开发板通过 USB 连接电脑)
idf.py -p COM3 flash    # Windows 用户把 COM3 换成实际端口
idf.py -p /dev/ttyUSB0 flash  # Linux 用户

编译时如果报错,八成是环境变量没设对。检查一下 export.sh 有没有执行。

2.5 串口监视器:看你的程序在说什么

程序烧进去了,怎么知道它跑没跑?用串口监视器。

idf.py -p COM3 monitor    # Windows
idf.py -p /dev/ttyUSB0 monitor  # Linux

你会看到这样的输出:

Hello world!
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE
Silicon revision 1
Restarting in 10 seconds...
Restarting in 9 seconds...
...
Restarting now.

退出监视器:按 Ctrl+] 退出。别按 Ctrl+C,那会直接杀掉整个进程。

我曾经在项目调试时,发现串口一直没输出。折腾了半天,结果是 USB 线只能充电不能传数据。嗯,这种坑遇到一次就记住了。

2.6 常见问题与避坑指南

问题 原因 解决办法
编译时报 Python 版本错误 系统默认 Python 版本不对 用 python3 --version 检查,确保是 3.6 以上
烧录时提示无法打开端口 权限不足或端口被占用 Linux 下加 sudo,或把用户加入 dialout 组
串口输出乱码 波特率不匹配 ESP-IDF 默认 115200,检查监视器设置
编译极慢 第一次编译要下载工具链 耐心等,或者用离线安装包

我曾经遇到一个坑:在 Windows 上用 VS Code 终端执行 idf.py flash,结果一直报错。后来发现是 VS Code 的终端没有继承 ESP-IDF 的环境变量。解决办法:用 ESP-IDF CMD 或者 VS Code 的 ESP-IDF 插件来操作。

好了,到这里你的 ESP-IDF 开发环境已经跑通了。后面我们会在这个基础上,一步步深入低功耗设计和 OTA 升级。记住,环境搭好了,后面的事就顺了。