# 第2周：ESP32硬件平台 - 讲义

## 教学目标

| 目标 | 内容 |
|-----|------|
| 知识目标 | 掌握ESP32芯片架构、理解GPIO原理、理解PWM脉宽调制 |
| 能力目标 | 能够使用GPIO控制LED、实现呼吸灯效果 |
| 情感目标 | 建立"单片机可以创造有趣效果"的认知 |

---

## 课程导入（10分钟）

### 2.1 开场Demo设计

**Demo名称：ESP32音乐灯光秀**

**演示流程：**
1. 打开Arduino IDE，预览即将上传的代码
2. 点击上传，观察LED开始闪烁
3. 连接功放和音箱，播放《生日快乐》音乐
4. 让几位同学上来体验"喊节拍控制灯光"

**引导语：**
> "同学们，刚才你们看到了ESP32的两个能力：第一，它能播放音乐；第二，它能控制灯光。这两个能力结合起来，就做出了音乐灯光秀。今天我们就来学习ESP32是怎么做到这些的。"

---

## 原理讲解（40分钟）

### 2.2 ESP32芯片家族

#### 2.2.1 乐鑫芯片发展史

| 年份 | 芯片 | 特点 |
|-----|------|------|
| 2014 | ESP8266 | 乐鑫第一款WiFi芯片，开创物联网时代 |
| 2016 | ESP32 | WiFi+蓝牙双模，性能大幅提升 |
| 2019 | ESP32-S2 | 单核，低功耗，USB OTG |
| 2020 | ESP32-C3 | RISC-V核心，WiFi6 |
| 2021 | ESP32-S3 | **AI向量指令，BLE5.0，课程使用** |
| 2022 | ESP32-C6 | WiFi6，BLE5.0，RISC-V |
| 2023 | ESP32-P4 | 更高性能，AI加速 |

#### 2.2.2 ESP32-S3 vs ESP32（普通版）

| 对比项 | ESP32 | ESP32-S3 |
|-------|-------|----------|
| CPU | LX6 单核/双核 | **LX7 双核** |
| 主频 | 240MHz | **240MHz** |
| RAM | 520KB | **512KB + 8MB PSRAM** |
| AI加速 | 无 | **向量指令集 ESP-NN** |
| 蓝牙 | 4.2 | **BLE 5.0** |
| USB | 无 | **USB OTG** |
| GPIO | 34个 | **44个** |

**为什么选择ESP32-S3？**
1. 内置AI加速指令（适合TinyML）
2. 更多内存（可运行较大模型）
3. BLE 5.0（更省电）
4. USB OTG（方便调试）

---

### 2.3 ESP32-S3系统架构

#### 2.3.1 CPU核心

```
Xtensa LX7 双核处理器：

┌────────────────────────────────────────┐
│                                        │
│         CPU Core 0    CPU Core 1       │
│         (系统用)      (用户用)         │
│                                        │
└────────────────────────────────────────┘
        ↑                       ↑
    共享Cache              共享Cache
        ↑                       ↑
    ┌────────────────────────────────┐
    │         共享外设               │
    │   WiFi / 蓝牙 / GPIO / ...    │
    └────────────────────────────────┘
```

**双核的作用：**
- Core 0：运行FreeRTOS系统，处理WiFi/蓝牙等任务
- Core 1：运行用户代码，主要的计算任务

#### 2.3.2 存储结构

| 类型 | 大小 | 用途 |
|-----|------|------|
| ROM | 384KB | 固化引导程序，不可修改 |
| SRAM | 512KB | 运行内存，程序运行时使用 |
| PSRAM | 8MB | 额外大内存，ESP32-S3专有 |
| Flash | 4-16MB | 存储程序代码和文件系统 |

**类比理解：**
```
ROM  = 印刷好的说明书（不可改）
SRAM = 桌面（正在用的东西）
PSRAM = 额外的桌面（摊开更多资料）
Flash = 书架（存放不常用的东西）
```

#### 2.3.3 外设资源

| 外设 | 数量 | 用途 |
|-----|------|------|
| GPIO | 44个 | 输入输出 |
| ADC | 20通道 | 模拟信号读取 |
| DAC | 2通道 | 模拟信号输出 |
| SPI | 4个 | 高速通信 |
| I2C | 2个 | 中速通信 |
| UART | 3个 | 串口通信 |
| I2S | 2个 | 音频 |
| LEDC | 16通道 | PWM控制 |
| WiFi | 1 | 无线网络 |
| 蓝牙 | 1 | 无线通信 |

---

### 2.4 GPIO详解

#### 2.4.1 GPIO基本概念

**GPIO = General Purpose Input/Output**
**通用输入/输出**

```
┌──────────────────────────────────────┐
│                                      │
│    CPU ◄──── 控制与状态总线 ────► GPIO引脚
│                                      │
│    • 设为输出：CPU写入 → 引脚输出电压  │
│    • 设为输入：CPU读取 ← 引脚输入电压  │
│                                      │
└──────────────────────────────────────┘
```

#### 2.4.2 GPIO工作模式

**1. 输出模式**
| 模式 | 说明 | 寄存器设置 |
|-----|------|-----------|
| 推挽输出 | 输出高/低电平 | OUTPUT |
| 开漏输出 | 只能输出低，需要上拉 | OPEN_DRAIN |

**2. 输入模式**
| 模式 | 说明 | 使用场景 |
|-----|------|---------|
| 浮空输入 | 不连接任何电平 | 适用于有源信号 |
| 上拉输入 | 默认HIGH，接按钮 | 按钮检测（省电阻） |
| 下拉输入 | 默认LOW | 特殊传感器 |

**3. 特殊模式**
| 模式 | 说明 |
|-----|------|
| ADC模式 | 模拟信号输入（0-3.3V → 0-4095） |
| PWM模式 | 模拟信号输出 |
| 复用模式 | 连接UART/I2C/SPI等外设 |

#### 2.4.3 GPIO使用注意事项

```
⚠️ 重要警告：

1. 电压限制
   • GPIO输入电压：0 ~ 3.3V
   • 超过3.3V会损坏芯片！
   • 不能直接接5V信号！

2. 电流限制
   • 每个GPIO最大输出40mA
   • 总电流不超过120mA
   • 不能直接驱动电机！

3. 启动状态
   • 上电瞬间GPIO状态不确定
   • 在setup()中先设置模式

4. 特殊引脚
   • GPIO0/2/5/12等有特殊功能
   • 启动模式选择
   • SPI flash接口
```

---

### 2.5 PWM脉宽调制

#### 2.5.1 PWM原理

**PWM = Pulse Width Modulation**
**脉冲宽度调制**

**核心思想：** 用"开关"来模拟中间电压

```
全开(HIGH)：
███████ 100%

开关50%时间：
████░░░ 50%

开关25%时间：
██░░░░░ 25%
```

#### 2.5.2 占空比

```
┌─────────────────────────────────────────────┐
│                                             │
│   占空比(Duty Cycle) = HIGH时间 / 周期时间   │
│                                             │
│   示例：                                     │
│   • 周期 = 1ms                             │
│   • HIGH时间 = 0.5ms                        │
│   • LOW时间 = 0.5ms                         │
│   • 占空比 = 50%                            │
│   • 等效电压 = 3.3V × 50% = 1.65V          │
│                                             │
└─────────────────────────────────────────────┘
```

#### 2.5.3 LED亮度控制

| PWM占空比 | LED亮度 | 等效电压 |
|----------|--------|---------|
| 100% | 最亮 | 3.3V |
| 75% | 较亮 | 2.475V |
| 50% | 中等 | 1.65V |
| 25% | 较暗 | 0.825V |
| 0% | 熄灭 | 0V |

#### 2.5.4 Arduino PWM函数

**ESP32使用LEDC（LED Controller）而不是analogWrite()：**

```cpp
// 1. 配置通道
ledcSetup(channel, frequency, resolution);
// 参数：
//   channel: 0-15，选择通道号
//   frequency: 频率(Hz)，LED常用1000Hz
//   resolution: 分辨率位数，8位=0-255

// 2. 绑定引脚
ledcAttachPin(gpio, channel);

// 3. 输出PWM
ledcWrite(channel, duty);
// duty: 根据分辨率决定范围
// 8位: 0-255
// 10位: 0-1023
// 12位: 0-4095
```

---

## 实验操作（40分钟）

### 2.6 实验2 - GPIO控制LED

#### 2.6.1 基础闪烁

**代码：**
```cpp
const int LED_PIN = 2;  // GPIO2

void setup() {
  pinMode(LED_PIN, OUTPUT);  // 设置为输出模式
}

void loop() {
  digitalWrite(LED_PIN, HIGH);  // LED亮
  delay(500);                    // 延时500ms
  digitalWrite(LED_PIN, LOW);   // LED灭
  delay(500);                    // 延时500ms
}
```

#### 2.6.2 PWM呼吸灯

```cpp
const int LED_PIN = 48;  // GPIO48 (RGB LED)

void setup() {
  // 配置LEDC通道0，1kHz频率，8位分辨率
  ledcSetup(0, 1000, 8);
  // 绑定GPIO48到通道0
  ledcAttachPin(LED_PIN, 0);
}

void loop() {
  // 渐亮
  for (int i = 0; i <= 255; i++) {
    ledcWrite(0, i);
    delay(10);
  }
  // 渐暗
  for (int i = 255; i >= 0; i--) {
    ledcWrite(0, i);
    delay(10);
  }
}
```

#### 2.6.3 SOS求救信号

```cpp
const int LED_PIN = 2;

void setup() {
  pinMode(LED_PIN, OUTPUT);
}

void short_flash() {
  digitalWrite(LED_PIN, HIGH);
  delay(200);
  digitalWrite(LED_PIN, LOW);
  delay(200);
}

void long_flash() {
  digitalWrite(LED_PIN, HIGH);
  delay(600);
  digitalWrite(LED_PIN, LOW);
  delay(200);
}

void loop() {
  // S: 三短
  for (int i = 0; i < 3; i++) short_flash();
  delay(500);
  
  // O: 三长
  for (int i = 0; i < 3; i++) long_flash();
  delay(500);
  
  // S: 三短
  for (int i = 0; i < 3; i++) short_flash();
  delay(2000);  // 2秒后重复
}
```

---

## 常见问题解答

**Q: 为什么使用GPIO2而不是其他引脚？**
A: GPIO2是开发板上用户LED的引脚，方便观察效果。

**Q: delay()和millis()有什么区别？**
A: delay()是阻塞延时，程序暂停等待；millis()返回运行时间，可用于非阻塞延时。

**Q: 呼吸灯效果不平滑怎么办？**
A: 可以增加分辨率（如10位）或减小延时步进。

---

## 课堂总结

```
┌─────────────────────────────────────────────────────────┐
│                   第2周要点速记                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   📌 ESP32-S3 = 双核 + WiFi + 蓝牙 + AI加速           │
│                                                         │
│   📌 GPIO = CPU控制外设的"手"                          │
│                                                         │
│   📌 GPIO注意事项：                                     │
│       • 电压不超过3.3V                                  │
│       • 电流不超过40mA                                 │
│                                                         │
│   📌 PWM = 用开关模拟中间电压                          │
│                                                         │
│   📌 Arduino PWM：ledcSetup() + ledcAttachPin()       │
│                                                         │
└─────────────────────────────────────────────────────────┘
```

---

## 下周预告

**第3周：Arduino基础语法**

**开场Demo：循迹小车走迷宫**

---

## 参考资料

| 资源 | 链接 |
|-----|------|
| ESP32-S3数据手册 | https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_cn.pdf |
| Arduino ESP32文档 | https://docs.arduino.cc/hardware/nano-esp32 |
| 立创实战派原理图 | https://oshwhub.com/ |

---

**讲义版本**: v1.0  
**更新日期**: 2026-04-10  
**授课教师**: 李茂奎老师
