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. 起始位:1 位低电平(标志数据开始)
  2. 数据位:8 位(高位在前或低位在前,可配置)
  3. 校验位:0 位(无校验,用于验证数据正确性)
  4. 停止位 :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 回环测试)

c 复制代码
// 定义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   |   0x00
  0x01   |   0x01
  0x02   |   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. 代码实现(指令解析与硬件控制)

c 复制代码
#include <Servo.h>

// 舵机配置
Servo myServo;
#define SERVO_PIN 13

// LED配置
#define LED_PIN 48

void 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. 实验操作与现象

  1. 打开电脑串口助手(如 Arduino IDE 串口监视器),设置波特率 115200,换行符选 "Newline"
  2. 发送指令 "LED ON"→ 板载 LED 点亮,串口返回 "指令执行:LED 已点亮"
  3. 发送指令 "SERVO 90"→ 舵机转到 90° 中位,串口返回角度确认信息
  4. 发送无效指令→ 串口返回错误提示

五、实战项目:多串口协同 ------ 传感器数据上报

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. 代码实现(多串口数据流转)

c 复制代码
#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() {
  // 初始化各UART
  Serial.begin(115200);    // UART0:调试
  UART1.begin(9600, SERIAL_8N1, DHT_PIN, 10);  // UART1:RX=9, TX=10
  UART2.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) {

&#x20; 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入门第八天:往期知识回顾与实战练习

相关推荐
【云轩】2 小时前
嵌入式开发常见问题解决:Keil头文件路径与MCUXpresso外设配置错误
经验分享·单片机
早日退休!!!2 小时前
C 内存布局
c语言·开发语言
三佛科技-134163842123 小时前
电动修眉刀MCU方案开发,基于国产单片机方案设计
单片机·嵌入式硬件·智能家居·pcb工艺
沐欣工作室_lvyiyi4 小时前
一种物联网的节水灌溉系统(论文+源码)
单片机·物联网·毕业设计·zigbee·灌溉
文慧的科技江湖4 小时前
开源 | 充电桩 运维 管理平台(IoT+运维工单平台)功能清单 - 慧知开源充电桩平台
运维·分布式·物联网·机器人·开源·充电桩平台
hazy1k4 小时前
K230基础-RTC时钟介绍及使用
stm32·单片机·嵌入式硬件·k230
czhaii4 小时前
STC定时器 RTC 时分 秒
单片机
小柯博客4 小时前
从零开始WebRTC(一)
stm32·单片机·嵌入式硬件·青少年编程·嵌入式·webrtc
路弥行至4 小时前
C语言入门教程 | 第四讲:深入理解数制与码制,掌握基本数据类型的奥秘
服务器·c语言·开发语言·经验分享·笔记·其他·入门教程