ESP32 与 ESP8266 的区别
ESP8266 是乐鑫 2014 年发布的第一款 Wi-Fi SoC,以极低的价格(约 1 美元)迅速风靡 Maker 社区。ESP32 是其 2016 年发布的继任者,在几乎所有维度都做了大幅提升。理解它们的区别有助于你在项目中做出正确的芯片选型。
| 特性 | ESP8266 | ESP32 |
|---|---|---|
| CPU 核心 | 单核 Xtensa LX106 @160MHz | 双核 Xtensa LX6 @240MHz |
| SRAM | 80KB(可用约 50KB) | 520KB(分段) |
| Flash | 外部 SPI Flash(通常 4MB) | 外部 SPI Flash(通常 4MB) |
| Wi-Fi | 802.11 b/g/n 2.4GHz | 802.11 b/g/n 2.4GHz |
| 蓝牙 | 无 | BLE 4.2 + 经典蓝牙 |
| ADC | 1 路 10bit ADC | 18 路 12bit ADC(2 组) |
| DAC | 无 | 2 路 8bit DAC |
| GPIO | 17 个(部分有复用限制) | 34 个(GPIO 矩阵任意复用) |
| 深度睡眠电流 | 约 20μA | 约 10μA |
| 硬件安全 | 无 | 安全启动、Flash 加密、硬件加密加速 |
如果你的项目只需要基本 Wi-Fi 联网且成本极度敏感,ESP8266 仍是合理选择。但如果需要蓝牙、多路 ADC、更多内存或更复杂的任务处理,ESP32 是不二之选。本教程全程使用 ESP32。
双核 Xtensa LX6 架构详解
ESP32 的处理器是 Tensilica 公司(现属 Cadence)设计的 Xtensa LX6 架构,乐鑫对其进行了定制化扩展。理解这个架构对于后续的多任务开发和调试至关重要。
两个核心的职责分工
开发框架对比
ESP32 生态支持三种主流开发框架,各有侧重:
ESP-IDF(官方 C/C++ SDK)
乐鑫官方维护,功能最完整,文档最权威。使用 CMake 构建系统,FreeRTOS 为内置 OS。适合生产级产品和需要精细控制的项目。学习曲线较陡,但收益最大。
Arduino Core for ESP32
将 Arduino API 移植到 ESP32,代码风格熟悉,生态库丰富(数千个 Arduino 库)。适合快速原型和 Maker 项目。底层仍调用 ESP-IDF,但封装了复杂细节。
PlatformIO
作为 VS Code 插件运行的现代化 IDE,支持 ESP-IDF 和 Arduino 两套框架,提供依赖管理、串口监视器、调试器集成。推荐作为 Arduino 开发的 IDE 替代。
MicroPython / CircuitPython
在 ESP32 上运行精简版 Python,开发速度最快,适合教学和脚本级应用。性能较差,不适合实时要求高的项目,内存占用也较大。
安装 ESP-IDF 开发环境
前置要求
ESP-IDF 需要 Python 3.7+、Git 和若干系统工具。以下是各平台的安装方式:
# ── macOS ──
# 1. 安装 Homebrew(如未安装)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# 2. 安装依赖
brew install cmake ninja dfu-util python3
# ── Ubuntu / Debian Linux ──
sudo apt-get install git wget flex bison gperf python3 python3-pip \
python3-venv cmake ninja-build ccache libffi-dev libssl-dev \
dfu-util libusb-1.0-0
# ── Windows ──
# 推荐使用官方 ESP-IDF Windows Installer:
# https://dl.espressif.com/dl/esp-idf/?idf=latest
克隆 ESP-IDF 并安装工具链
# 克隆 ESP-IDF(推荐使用稳定版,如 v5.2)
mkdir -p ~/esp
cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
git checkout v5.2
git submodule update --init --recursive
# 安装 Xtensa/RISC-V 工具链和工具
./install.sh esp32
# 设置环境变量(每个终端会话都需要运行)
. $HOME/esp/esp-idf/export.sh
# 或将以下别名加入 ~/.bashrc / ~/.zshrc 方便调用
alias get_idf='. $HOME/esp/esp-idf/export.sh'
# 验证安装
idf.py --version # 应输出 ESP-IDF v5.2.x
安装 Espressif IDF 官方 VS Code 扩展(ID: espressif.esp-idf-extension),它会自动完成 ESP-IDF 的下载、配置和工具链安装,并提供图形化的 Flash、Monitor、调试界面,是最推荐的入门方式。
创建第一个 ESP-IDF 项目
项目结构
# 复制 hello_world 示例
cp -r $IDF_PATH/examples/get-started/hello_world ~/esp/
cd ~/esp/hello_world
# ESP-IDF 项目标准结构:
hello_world/
├── CMakeLists.txt # 顶层 CMake:注册项目名
├── sdkconfig # 配置文件(menuconfig 生成)
├── partitions.csv # 可选:自定义分区表
└── main/
├── CMakeLists.txt # 组件 CMake:注册源文件
└── hello_world_main.c
Hello World 源码解析
// main/hello_world_main.c
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_chip_info.h"
static const char *TAG = "HELLO";
void app_main(void)
{
/* ESP_LOGI:Info 级别日志,格式类似 printf */
ESP_LOGI(TAG, "Hello, ESP32!");
/* 获取芯片信息 */
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
ESP_LOGI(TAG, "ESP32 芯片:%d 个 CPU 核心, Wi-Fi%s%s",
chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
for (int i = 10; i >= 0; i--) {
ESP_LOGI(TAG, "%d 秒后重启...", i);
vTaskDelay(pdMS_TO_TICKS(1000)); // 延迟 1000ms
}
esp_restart(); // 软件重启
}
ESP-IDF 使用 ESP_LOGE/W/I/D/V 五个级别的日志宏(Error/Warning/Info/Debug/Verbose)。TAG 是模块标识字符串,便于过滤。日志级别可在 menuconfig 中全局或按 TAG 控制,Release 时可完全关闭节省 Flash 空间。
编译、烧录与监视
# 配置目标芯片(首次必须运行)
idf.py set-target esp32
# 可选:打开图形化配置菜单
idf.py menuconfig
# 编译项目
idf.py build
# 烧录到设备(替换 /dev/ttyUSB0 为实际串口)
idf.py -p /dev/ttyUSB0 flash
# 打开串口监视器(Ctrl+] 退出)
idf.py -p /dev/ttyUSB0 monitor
# 一键:编译 + 烧录 + 监视
idf.py -p /dev/ttyUSB0 flash monitor
LED 闪烁实战
ESP-IDF 版本
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#define LED_PIN GPIO_NUM_2 // 大多数 DevKit 板载 LED 在 GPIO2
static const char *TAG = "BLINK";
void app_main(void)
{
/* 配置 GPIO2 为输出模式 */
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << LED_PIN),
.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_set_level(LED_PIN, 1); // LED 亮
ESP_LOGI(TAG, "LED ON");
vTaskDelay(pdMS_TO_TICKS(500));
gpio_set_level(LED_PIN, 0); // LED 灭
ESP_LOGI(TAG, "LED OFF");
vTaskDelay(pdMS_TO_TICKS(500));
}
}
Arduino 版本(对比参考)
#define LED_PIN 2
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED ON");
delay(500);
digitalWrite(LED_PIN, LOW);
Serial.println("LED OFF");
delay(500);
}
GPIO2 在许多 ESP32 开发板上连接了板载 LED,同时也与 SD 卡的数据引脚复用,还影响 Boot 模式(上电时低电平进入下载模式)。烧录时如果 LED 不断闪烁导致失败,可以尝试断开连接到 GPIO2 的外部设备。