# 第5周：通信接口（二）- SPI与WiFi - 讲义

## 教学目标

| 目标 | 内容 |
|-----|------|
| 知识目标 | 掌握SPI协议原理、WiFi连接与HTTP通信 |
| 能力目标 | 能够用手机通过WiFi控制ESP32的LED |
| 情感目标 | 建立"让设备连上网络"的物联网思维 |

---

## 课程导入（10分钟）

### 5.1 开场Demo设计

**Demo名称：手机遥控灯**

**演示流程：**
1. 展示：手机APP发送开灯指令
2. 演示：ESP32接收指令，LED亮起
3. 引导：这节课学完，你们也能做出来

**引导语：**
> "同学们，刚才用手机控制了ESP32的灯——这就是物联网的典型应用。今天学完WiFi，你们也能做出来。"

---

## 原理讲解（40分钟）

### 5.2 SPI通信协议

#### 5.2.1 SPI是什么

```
SPI = Serial Peripheral Interface
     串行外设接口
```

**特点：**
- 高速同步通信
- 四根线：MOSI、MISO、SCK、CS
- 比I2C速度更快

#### 5.2.2 SPI四根线

| 引脚 | 全称 | 功能 |
|------|------|------|
| MOSI | Master Out Slave In | 主设备发送，从设备接收 |
| MISO | Master In Slave Out | 从设备发送，主设备接收 |
| SCK | Serial Clock | 时钟信号 |
| CS | Chip Select | 片选信号 |

#### 5.2.3 SPI vs I2C 对比

| 特性 | SPI | I2C |
|------|-----|-----|
| 速度 | 可达数十MHz | 最大400KHz |
| 线数 | 4根（+多设备多CS） | 2根 |
| 复杂度 | 简单 | 复杂 |
| 应用 | 显示屏、存储卡 | 传感器 |

---

### 5.3 WiFi连接原理

#### 5.3.1 ESP32 WiFi模式

```
ESP32支持三种WiFi模式：
┌─────────────────────────────────────┐
│  1. Station (STA)  - 连接WiFi热点  │
│  2. SoftAP         - 创建WiFi热点   │
│  3. AP+STA         - 两者同时      │
└─────────────────────────────────────┘
```

**我们用的是 Station 模式（ESP32连接手机热点）**

#### 5.3.2 WiFi连接步骤

```cpp
#include <WiFi.h>

// WiFi配置
const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";

void setup() {
  Serial.begin(115200);
  
  // 连接WiFi
  WiFi.begin(ssid, password);
  
  // 等待连接
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("WiFi已连接!");
  Serial.print("IP地址: ");
  Serial.println(WiFi.localIP());
}
```

#### 5.3.3 WiFi.status() 返回值

| 返回值 | 含义 |
|--------|------|
| WL_CONNECTED | 连接成功 |
| WL_NO_SSID_AVAIL | 找不到WiFi名称 |
| WL_CONNECT_FAILED | 密码错误 |
| WL_IDLE_STATUS | 正在连接 |

---

### 5.4 HTTP协议基础

#### 5.4.1 HTTP请求格式

```
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  HTTP请求格式：                                             │
│                                                             │
│  GET /path HTTP/1.1\r\n                                    │
│  Host: server.com\r\n                                      │
│  \r\n                                                       │
│                                                             │
│  HTTP响应格式：                                             │
│                                                             │
│  HTTP/1.1 200 OK\r\n                                       │
│  Content-Type: text/html\r\n                               │
│  Content-Length: 123\r\n                                   │
│  \r\n                                                       │
│  <html>...</html>                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

#### 5.4.2 ESP32作为Web服务器

```cpp
#include <WiFi.h>
#include <WebServer.h>

WebServer server(80);  // HTTP默认端口80

void setup() {
  // ... WiFi连接代码 ...
  
  // 定义路由处理函数
  server.on("/led/on", []() {
    digitalWrite(LED_PIN, HIGH);
    server.send(200, "text/plain", "LED ON");
  });
  
  server.on("/led/off", []() {
    digitalWrite(LED_PIN, LOW);
    server.send(200, "text/plain", "LED OFF");
  });
  
  server.begin();
}

void loop() {
  server.handleClient();  // 处理客户端请求
}
```

---

## 实验操作（40分钟）

### 5.5 实验：手机WiFi遥控LED

#### 实验目的
- 掌握ESP32连接WiFi的方法
- 学习创建Web服务器
- 实现手机控制ESP32的LED

#### 实验器材
- ESP32开发板 × 1
- LED灯 × 1（或使用板载LED）
- 杜邦线若干
- 手机热点（需要开启）

#### 实验步骤

**1. 准备工作**
- 手机开启热点，设置名称和密码
- 记住热点名称（ssid）和密码

**2. 编写代码**
```cpp
#include <WiFi.h>
#include <WebServer.h>

// ============ WiFi配置 ============
const char* ssid = "你的手机热点名称";
const char* password = "你的手机热点密码";

// ============ 引脚定义 ============
#define LED_PIN 2  // ESP32板载LED（通常GPIO2）

// ============ Web服务器 ============
WebServer server(80);

// ============ HTML网页 ============
String getHtml() {
  String html = "<!DOCTYPE html><html>";
  html += "<head><meta charset='utf-8'>";
  html += "<title>ESP32 遥控灯</title></head>";
  html += "<body>";
  html += "<h1>ESP32 WiFi 遥控灯</h1>";
  html += "<p>当前状态: <span id='status'>...</span></p>";
  html += "<button onclick='turnOn()'>开灯</button>";
  html += "<button onclick='turnOff()'>关灯</button>";
  html += "<script>";
  html += "function turnOn(){fetch('/on')};";
  html += "function turnOff(){fetch('/off')};";
  html += "</script></body></html>";
  return html;
}

// ============ 路由处理 ============
void handleRoot() {
  server.send(200, "text/html", getHtml());
}

void handleLedOn() {
  digitalWrite(LED_PIN, HIGH);
  server.send(200, "text/plain", "ON");
}

void handleLedOff() {
  digitalWrite(LED_PIN, LOW);
  server.send(200, "text/plain", "OFF");
}

// ============ 设置 ============
void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
  
  // 连接WiFi
  Serial.print("连接 WiFi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.println("WiFi已连接!");
  Serial.print("IP地址: ");
  Serial.println(WiFi.localIP());
  
  // 设置路由
  server.on("/", handleRoot);
  server.on("/on", handleLedOn);
  server.on("/off", handleLedOff);
  
  server.begin();
  Serial.println("Web服务器已启动!");
}

void loop() {
  server.handleClient();
}
```

**3. 上传并测试**
- 修改代码中的ssid和password为你的手机热点
- 上传程序到ESP32
- 打开串口监视器，等待WiFi连接成功
- 记录显示的IP地址

**4. 手机控制**
- 手机连接与ESP32相同的WiFi
- 打开浏览器，输入ESP32的IP地址
- 点击"开灯"/"关灯"按钮

#### 常见问题

| 问题 | 原因 | 解决 |
|------|------|------|
| WiFi连接失败 | 热点名称/密码错误 | 检查并重新配置 |
| 无法打开网页 | 手机未连同一WiFi | 确保同一网络 |
| LED不亮 | LED极性接反 | 调换LED引脚 |

---

## 知识总结

### 5.6 SPI总线特点

```
SPI应用场景：
• TFT显示屏（如1.8寸彩屏）
• SD卡存储模块
• 射频芯片（nRF24L01）
• OLED显示屏（也可以用I2C）
```

### 5.7 WiFi物联网架构

```
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│              📱 手机                               ┌───────┐ │
│           ┌────────┐                                │ ESP32 │ │
│           │  浏览器 │ ←────── HTTP请求/响应 ───────→ │  服务器│ │
│           └────────┘                                └───────┘ │
│                  │                                          │
│                  │ WiFi (同一局域网)                         │
│                  │                                          │
│           ┌──────┴──────┐                                   │
│           │   手机热点   │ ← ssid + password                │
│           └─────────────┘                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
```

---

## 课后作业

1. **理论题**：解释SPI和I2C的区别
2. **实践题**：完成WiFi遥控LED实验
3. **思考题**：如何实现同时控制多个设备（多个LED）？

---

## 延伸阅读

- 《ESP32物联网开发》第4章：WiFi连接
- Arduino WiFi库文档：https://docs.arduino.cc/libraryties/wifi
