ESP32-S3入门第七天:UART串口通信与设备交互
ESP32-S3 入门第七天:UART 串口通信与设备交互
一、今日目标
- 理解 UART(通用异步收发传输器)的通信原理与数据帧结构
- 掌握 ESP32-S3 硬件 UART 的配置(波特率、引脚映射、多串口)
- 完成 3 个实战实验:串口回环测试、指令控制硬件、传感器数据串口上报
二、UART 通信核心原理
1. 协议特性与优势
UART 是一种异步串行通信协议,无需时钟线即可实现设备间的数据传输,核心特点:
- 两根信号线:TX(发送端)、RX(接收端),需交叉连接(A 的 TX 接 B 的 RX)
- 异步通信:通过波特率同步数据传输节奏(双方必须一致)
- 全双工通信:可同时发送和接收数据
- 硬件支持:ESP32-S3 内置 3 个独立 UART 控制器(UART0/UART1/UART2),可同时工作
2. ESP32-S3 的 UART 硬件特性
特性 | 参数说明 | 备注 |
---|---|---|
控制器数量 | 3 个(UART0/UART1/UART2) | UART0 默认映射到 USB 串口(调试用) |
通信速率 | 300bps - 5Mbps | 常用 9600/115200/921600bps |
数据帧格式 | 可配置:8/9 位数据位、0/1 位停止位、无 / 奇 / 偶校验位 | 默认 8N1(8 数据位 + 无校验 + 1 停止位) |
引脚映射 | 支持任意 GPIO 重映射 | 需避免与其他外设冲突 |
缓冲区大小 | 发送 / 接收缓冲区各 256 字节 | 可通过软件扩展 |
3. 数据传输原理
UART 数据以「帧」为单位传输,典型 8N1 帧结构:
- 起始位:1 位低电平(标志数据开始)
- 数据位:8 位(高位在前或低位在前,可配置)
- 校验位:0 位(无校验,用于验证数据正确性)
- 停止位:1 位高电平(标志数据结束)
三、基础实验:UART 回环测试(验证通信功能)
1. 实验原理
通过短接 UART 的 TX 和 RX 引脚,使发送的数据直接被自身接收,验证 UART 收发功能是否正常。
2. 硬件准备
元件 | 数量 | 说明 |
---|---|---|
ESP32-S3 开发板 | 1 块 | 核心控制板 |
杜邦线 | 1 根 | 短接 TX 和 RX |
3. 硬件连接(使用 UART2)
ESP32-S3 引脚 | 功能 | 连接方式 |
---|---|---|
GPIO17 | UART2_TX | 与 GPIO16 短接 |
GPIO16 | UART2_RX | 与 GPIO17 短接 |
注意:UART0 默认用于 USB 调试(Serial 对象),本实验用 UART2 做回环测试,避免冲突。
4. 代码实现(UART2 回环测试)
// 定义UART2引脚(可自定义映射)
#define UART2_TX 17
#define UART2_RX 16// 创建UART2对象(硬件UART)
HardwareSerial UART2(2); // 2对应UART2控制器void setup() {// 初始化UART0(USB串口,用于打印日志)Serial.begin(115200);while (!Serial); // 等待USB串口就绪// 初始化UART2(波特率9600,8N1格式)UART2.begin(9600, SERIAL_8N1, UART2_RX, UART2_TX);Serial.println("UART2回环测试开始(TX=17,RX=16)");Serial.println("发送数据 | 接收数据");Serial.println("---------------------");
}void loop() {// 测试数据(0x00到0xFF循环)static byte testData = 0x00;// 发送数据UART2.write(testData);Serial.print(" 0x");if (testData < 0x10) Serial.print("0");Serial.print(testData, HEX);// 等待接收数据(超时100ms)delay(10);if (UART2.available() > 0) {byte recvData = UART2.read();Serial.print(" | 0x");if (recvData < 0x10) Serial.print("0");Serial.println(recvData, HEX);} else {Serial.println(" | 接收超时");}// 数据递增,循环测试testData++;delay(500);
}
5. 实验现象
USB 串口监视器显示发送数据与接收数据完全一致(因 TX 与 RX 短接),证明 UART2 通信功能正常:
UART2回环测试开始(TX=17,RX=16)
发送数据 | 接收数据
---------------------0x00 | 0x000x01 | 0x010x02 | 0x02...
四、进阶实验:串口指令控制硬件(LED + 舵机)
1. 实验原理
通过电脑串口助手发送指令(如 “LED ON”“SERVO 90”),ESP32-S3 接收并解析指令,控制 LED 开关和舵机角度,实现人机交互。
2. 硬件准备
元件 | 数量 | 说明 |
---|---|---|
板载 LED(GPIO48) | 1 个 | 状态指示 |
舵机(SG90) | 1 个 | 角度控制 |
杜邦线 | 3 根 | 舵机连接 |
3. 硬件连接
设备 | ESP32-S3 引脚 | 说明 |
---|---|---|
舵机信号 | GPIO13 | PWM 控制(复用第三天知识) |
舵机 VCC | 5V | 独立供电 |
舵机 GND | GND | 共地 |
UART 指令接收 | UART0(USB 串口) | 直接用开发板 USB 口 |
4. 代码实现(指令解析与硬件控制)
#include <Servo.h>// 舵机配置
Servo myServo;
#define SERVO_PIN 13// LED配置
#define LED_PIN 48void setup() {// 初始化USB串口(UART0,波特率115200)Serial.begin(115200);while (!Serial);// 初始化硬件pinMode(LED_PIN, OUTPUT);myServo.attach(SERVO_PIN); // 舵机初始化Serial.println("串口指令控制实验");Serial.println("支持指令:");Serial.println(" LED ON - 点亮LED");Serial.println(" LED OFF - 熄灭LED");Serial.println(" SERVO X - 舵机转到X度(0-180)");
}void loop() {// 等待接收串口指令if (Serial.available() > 0) {String cmd = Serial.readStringUntil('\n');cmd.trim(); // 去除空格和换行符// 解析LED控制指令if (cmd == "LED ON") {digitalWrite(LED_PIN, HIGH);Serial.println("指令执行:LED已点亮");} else if (cmd == "LED OFF") {digitalWrite(LED_PIN, LOW);Serial.println("指令执行:LED已熄灭");} // 解析舵机控制指令else if (cmd.startsWith("SERVO ")) {int angle = cmd.substring(6).toInt(); // 提取角度值if (angle >= 0 && angle <= 180) {myServo.write(angle);Serial.print("指令执行:舵机转到");Serial.print(angle);Serial.println("度");} else {Serial.println("错误:角度需在0-180之间");}} // 未知指令处理else {Serial.print("错误:未知指令「");Serial.print(cmd);Serial.println("」");}}delay(50);
}
5. 实验操作与现象
- 打开电脑串口助手(如 Arduino IDE 串口监视器),设置波特率 115200,换行符选 “Newline”
- 发送指令 “LED ON”→ 板载 LED 点亮,串口返回 “指令执行:LED 已点亮”
- 发送指令 “SERVO 90”→ 舵机转到 90° 中位,串口返回角度确认信息
- 发送无效指令→ 串口返回错误提示
五、实战项目:多串口协同 —— 传感器数据上报
1. 实验原理
用 UART0(USB)打印调试日志,UART1 连接 DHT11 温湿度传感器(模拟外设),UART2 将传感器数据上报到上位机,实现多串口分工协作。
2. 硬件连接(三串口同时工作)
UART 控制器 | 功能 | 引脚分配 | 连接设备 |
---|---|---|---|
UART0 | 调试日志 | TX=1, RX=3(USB 内置) | 电脑 USB |
UART1 | 传感器通信 | TX=10, RX=9 | DHT11(模拟外设) |
UART2 | 数据上报 | TX=17, RX=16 | 上位机(电脑串口助手) |
3. 代码实现(多串口数据流转)
#include "DHT.h"// DHT11配置(接UART1 RX,模拟串口传感器)
#define DHT_PIN 9
#define DHT_TYPE DHT11
DHT dht(DHT_PIN, DHT_TYPE);// 多UART定义
HardwareSerial UART1(1); // 传感器通信
HardwareSerial UART2(2); // 数据上报void setup() {// 初始化各UARTSerial.begin(115200); // UART0:调试UART1.begin(9600, SERIAL_8N1, DHT_PIN, 10); // UART1:RX=9, TX=10UART2.begin(115200, SERIAL_8N1, 16, 17); // UART2:RX=16, TX=17// 初始化传感器dht.begin();Serial.println("多串口协同实验启动");Serial.println("UART0:调试日志 | UART1:传感器 | UART2:数据上报");
}void loop() {// 1. 读取DHT11数据(模拟UART传感器)float temp = dht.readTemperature();float humi = dht.readHumidity();// 2. UART0打印调试信息Serial.print("\n【调试日志】");Serial.print("温度:");Serial.print(temp);Serial.print("℃,湿度:");Serial.print(humi);Serial.println("%");// 3. UART2上报数据到上位机(格式:TEMP:25.5,HUMI:60.2)String report = "TEMP:" + String(temp) + ",HUMI:" + String(humi);UART2.println(report);Serial.print("【UART2上报】");Serial.println(report);// 4. 模拟UART1接收传感器反馈if (UART1.available() > 0) {String feedback = UART1.readString();Serial.print("【UART1接收】");Serial.println(feedback);}delay(2000);
}
4. 实验现象
- UART0(USB 串口):每 2 秒打印调试日志,包含温湿度和各串口状态
- UART2(数据上报):同步发送格式化数据(如 “TEMP:25.6,HUMI:60.1”),可在串口助手接收
- 多串口同时工作,无数据冲突或丢失
六、UART 高级配置与故障排除
1. 关键配置技巧
(1)自定义波特率与数据格式
// 非常规波特率(如4800bps)Serial.begin(4800);// 自定义数据格式(9位数据位+奇校验+2停止位)UART1.begin(9600, SERIAL\_9O2, RX\_PIN, TX\_PIN);
(2)引脚重映射(任意 GPIO 分配)
// UART1重映射:TX=21, RX=22(原I2C引脚,可复用)HardwareSerial UART1(1);UART1.begin(9600, SERIAL\_8N1, 22, 21); // 顺序:波特率、格式、RX、TX
(3)缓冲区操作(避免数据丢失)
// 检查接收缓冲区大小if (Serial.available() > 0) {  String data = Serial.readString(); // 读取所有缓存数据}// 清空发送缓冲区Serial.flush();
2. 常见问题与解决方案
问题现象 | 可能原因 | 解决方法 |
---|---|---|
数据乱码 | 1. 波特率不匹配2. 数据格式(校验位 / 停止位)错误 | 1. 确保双方波特率完全一致(如均为 115200)2. 统一配置为 8N1(默认常用格式) |
接收不到数据 | 1. TX/RX 引脚接反2. 引脚映射错误3. 外设未上电 | 1. 交叉连接:A 的 TX 接 B 的 RX,A 的 RX 接 B 的 TX2. 重新核对 UART 初始化时的 RX/TX 引脚顺序3. 检查外设电源和 GND 连接 |
数据丢失 | 1. 接收缓冲区溢出2. 处理速度慢于接收速度 | 1. 缩短数据帧长度,或增加处理频率2. 用readStringUntil() 按分隔符读取,避免缓存堆积 |
多串口冲突 | 1. 引脚复用冲突2. 硬件资源竞争 | 1. 确保不同 UART 使用独立 GPIO(用引脚图排查冲突)2. 避免同时在多个 UART 中使用delay() 阻塞 |
七、第七天总结与第XXX天预告
1. 今日成果
- ✅ 理解 UART 异步通信原理、数据帧结构和波特率同步机制
- ✅ 掌握 ESP32-S3 3 个硬件 UART 的配置、引脚映射和多串口协同
- ✅ 实现指令控制硬件、传感器数据上报等实用场景,理解 UART 交互逻辑
2. 第XXX天预告:Wi-Fi 基础与网络连接
明天将进入物联网核心模块 ——Wi-Fi 通信,学习:
- ESP32-S3 的 Wi-Fi 模式(Station/AP)配置
- 连接家庭 Wi-Fi 并获取 IP 地址
- 实现网络时间同步(NTP)
- 基础 HTTP 请求(获取网络数据)
为后续物联网项目(如数据上传云端)打基础。
本章节系列教学
ESP32-S3 入门第一天:Arduino IDE使用
ESP32-S3 入门第二天:IO口、延时与定时器核心知识实战
ESP32-S3 入门第三天:PWM 脉冲宽度调制
ESP32-S3 入门第四天:ADC 模数转换
ESP32-S3 入门第五天:I2C通信协议
ESP32-S3入门第六天:SPI通信协议与高速外设控制
ESP32-S3入门第七天:UART串口通信与设备交互
ESP32-S3入门第八天:往期知识回顾与实战练习