# 第4周：通信接口（一）- UART与I2C - 讲义

## 教学目标

| 目标 | 内容 |
|-----|------|
| 知识目标 | 掌握UART串口通信原理、I2C协议理解 |
| 能力目标 | 能够使用Arduino读取I2C传感器数据 |
| 情感目标 | 建立"数据是怎么传输的"的系统性思维 |

---

## 课程导入（10分钟）

### 4.1 开场Demo设计

**Demo名称：传感器上云**

**演示流程：**
1. 展示：DHT11温湿度传感器实时读取数据
2. 演示：数据通过ESP32上传到手机APP显示
3. 引导：这节课学完，你们也能做出来

**引导语：**
> "同学们，刚才看到温度湿度数据从传感器到手机实时显示，这个过程是怎么实现的？今天学完通信接口，你们就知道了。"

---

## 原理讲解（40分钟）

### 4.2 UART串口通信

#### 4.2.1 什么是UART

```
UART = Universal Asynchronous Receiver/Transmitter
      通用异步收发传输器
```

**特点：**
- 异步通信（不需要时钟线）
- 两根线：TX（发送）和RX（接收）
- 电脑和ESP32通信的主要方式

#### 4.2.2 UART接线

```
电脑(TX) →───────────────→ ESP32(RX)
电脑(RX) ←───────────────← ESP32(TX)
电脑(GND) ──公共地──────── ESP32(GND)
```

**注意：TX接RX，RX接TX！**

#### 4.2.3 波特率

| 波特率 | 用途 |
|-------|------|
| 9600 | 慢速设备 |
| 115200 | ESP32常用高速 |

**Arduino代码：**
```cpp
void setup() {
  Serial.begin(115200);  // 初始化串口，波特率115200
}

void loop() {
  Serial.println("Hello!");  // 发送数据
  delay(1000);
}
```

---

### 4.3 I2C通信协议

#### 4.3.1 I2C是什么

```
I2C = Inter-Integrated Circuit
     内部集成电路
```

**特点：**
- 两根数据线：SDA（数据）和SCL（时钟）
- 可以接多个设备（每个设备有唯一地址）
- ESP32连接传感器的首选方式

#### 4.3.2 I2C地址

每个I2C设备都有唯一地址：

| 设备 | I2C地址 |
|------|--------|
| DHT11 | 0x27 或 0x28（软件模拟） |
| BMP180 | 0x77 |
| MPU6050 | 0x68 |
| OLED屏幕 | 0x3C 或 0x3D |

**查询地址方法：**
```cpp
#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin();
  
  Serial.println("I2C Scanner");
  for (byte address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    if (Wire.endTransmission() == 0) {
      Serial.print("Found: 0x");
      Serial.println(address, HEX);
    }
  }
}
```

#### 4.3.3 I2C通信时序

```
        Start   地址   ACK   数据   ACK   Stop
SDA:  ─┐    ┌─┐ ┌─────┐  ┌─┐ ┌───┐ ┌─┐  ┌────
       └────┘ └─────┘  └─┘ └───┘ └─┘  └──
SCL:   ────────┐  ┌───┐  ┌───┐  ┌───┐  ─────
                └──┘   └──┘   └──┘  └──
```

---

### 4.4 DHT11温湿度传感器

#### 4.4.1 引脚定义

```
DHT11引脚：
- VCC (接3.3V或5V)
- DATA (数据线)
- NC (不连接)
- GND (接地)
```

#### 4.4.2 接线图

```
ESP32    DHT11
-------- --------
3.3V  →  VCC
GPIO21 →  DATA
GND   →  GND
```

**注意：DATA和VCC之间需要接一个4.7KΩ上拉电阻**

#### 4.4.3 Arduino代码

```cpp
#include <DHT.h>
#include <DHT_U.h>

#define DHTPIN 21      // DATA引脚连接GPIO21
#define DHTTYPE DHT11  // DHT11传感器

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();
}

void loop() {
  float humidity = dht.readHumidity();    // 读取湿度
  float temperature = dht.readTemperature(); // 读取温度(摄氏度)
  
  Serial.print("湿度: ");
  Serial.print(humidity);
  Serial.print(" %\t");
  Serial.print("温度: ");
  Serial.print(temperature);
  Serial.println(" °C");
  
  delay(2000);  // 等待2秒
}
```

---

## 实验操作（40分钟）

### 4.5 实验：I2C传感器数据采集

#### 实验目的
- 掌握I2C传感器的连接方法
- 学习使用Wire库读取传感器数据
- 理解温湿度数据采集原理

#### 实验器材
- ESP32开发板 × 1
- DHT11温湿度传感器 × 1
- 4.7KΩ电阻 × 1
- 杜邦线若干

#### 实验步骤

**1. 硬件连接**
```
ESP32 GPIO21 → DHT11 DATA
ESP32 3.3V  → DHT11 VCC
ESP32 GND   → DHT11 GND
(4.7K电阻接在DATA和VCC之间)
```

**2. 安装库**
- 在Arduino IDE中：工具 → 管理库 → 搜索"DHT sensor library" → 安装

**3. 编写代码**
```cpp
#include <DHT.h>

#define DHTPIN 21
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(115200);
  Serial.println("DHT11 传感器测试");
  dht.begin();
}

void loop() {
  delay(2000);
  
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  
  if (isnan(h) || isnan(t)) {
    Serial.println("读取传感器失败!");
    return;
  }
  
  Serial.print("湿度: ");
  Serial.print(h);
  Serial.print(" %  ");
  Serial.print("温度: ");
  Serial.print(t);
  Serial.println(" °C");
}
```

**4. 验证输出**
- 打开串口监视器（波特率115200）
- 观察温湿度数据输出

#### 常见问题

| 问题 | 原因 | 解决 |
|------|------|------|
| 显示NaN | 接线错误 | 检查DATA/VCC/GND连接 |
| 读数不变 | 传感器损坏 | 更换传感器 |
| 数值异常 | 上拉电阻缺失 | 并联4.7K电阻 |

---

## 知识总结

### 4.6 UART vs I2C 对比

| 特性 | UART | I2C |
|------|------|-----|
| 线数 | 2根（TX/RX） | 2根（SDA/SCL） |
| 设备数量 | 1对1 | 多设备 |
| 距离 | 短距离 | 短距离 |
| 速度 | 可达1Mbps | 400KHz高速模式 |
| 典型应用 | 电脑通信 | 传感器连接 |

### 4.7 本周核心概念

```
1. UART：异步串口，电脑和ESP32通信
2. I2C：两线制协议，多设备连接
3. 波特率：串口通信速度
4. I2C地址：每个设备的唯一标识
5. Wire库：Arduino的I2C通信库
```

---

## 课后作业

1. **理论题**：解释UART和I2C的区别
2. **实践题**：使用I2C扫描程序找出你连接的传感器地址
3. **思考题**：如果连接多个I2C设备，需要注意什么？

---

## 延伸阅读

- 《ESP32权威指南》第6章：通信接口
- Arduino官方文档：https://docs.arduino.cc/learn/communication/wire
