esp32UART串口外设(Arduino)

通用异步接收器/发送器 (UART)

介绍

通用异步接收器/发送器 (UART) 是一种硬件功能,它使用广泛采用的异步串行通信接口(如 RS232、RS422 和 RS485)处理通信(即时序要求和数据成帧)。UART提供了一种广泛采用且廉价的方法,可实现不同设备之间的全双工或半双工数据交换。

ESP32 芯片有 3 个 UART 控制器(也称为端口),每个控制器都具有一组相同的寄存器,以简化编程并提高灵活性。

每个UART控制器都可独立配置波特率、数据位长度、位排序、停止位数、奇偶校验位等参数。所有常规UART控制器都与不同制造商的UART设备兼容,还可以支持红外数据关联(IrDA)协议。

官方手册

功能概述

本文介绍了如何使用 UART 驱动的功能和数据类型在 ESP32 和其他 UART 设备之间建立通信。典型的编程工作流程分为以下几个部分:

  1. 设置通信参数 - 设置波特率、数据位、停止位等。

  2. 设置通信引脚 - 分配用于连接到设备的引脚

  3. 安装驱动程序 - 为 UART 驱动程序分配 ESP32 的资源

  4. 运行 UART 通信 - 发送/接收数据

  5. 使用中断 - 在特定通信事件上触发中断

  6. 删除驱动程序 - 如果不再需要 UART 通信,则释放已分配的资源

步骤 1 至 3 包括配置阶段。第 4 步是 UART 开始运行的地方。步骤 5 和 6 是可选的。

UART 驱动程序的函数使用 标识每个 UART 控制器。以下所有函数调用都需要此标识。

基于Arduino的UART串口概述

ESP323个UART串口,分别是UART0UART1UART2,其中UART0用于程序下载和信息交互,UART1专门用于Flash的读写

串口的初始化

void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd)
  • unsigned long baud:波特率,表示每秒传输的位数。
  • uint32_t config:配置位,用于设置串口通信的一些选项,如数据位、停止位和奇偶校验等。
  • int8_t rxPin:接收引脚编号,用于连接接收器。
  • int8_t txPin:发送引脚编号,用于连接发射器。
  • bool invert:是否反转输入信号,如果为 true,则在接收时将信号反转。
  • unsigned long timeout_ms:超时时间(毫秒),当没有数据接收或发送时,该函数将等待指定的时间。
  • uint8_t rxfifo_full_thrhd:接收缓冲区满阈值,当接收缓冲区达到此值时,将触发中断。

以下是一个示例代码,演示如何使用 HardwareSerial::begin() 函数进行串口通信的初始化:

#include <HardwareSerial.h>

// 创建硬件串口对象
HardwareSerial mySerial;

void setup() {
  // 初始化串口通信
  mySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN, false, 1000);
}

void loop() {
  // 检查是否有可用的数据
  if (mySerial.available()) {
    // 读取一个字节的数据
    char receivedChar = mySerial.read();
    // 处理接收到的数据
    // ...
  }
}

在Arduino中,还可以使用Serial对象来处理串口通信。默认情况下,Arduino有3个串口对象:Serial, Serial1Serial2

  • Serial:默认的串口对象
  • Serial1:第二个串口对象
  • Serial2:第三个串口对象

这些串口对象具有相同的方法和属性,可以用于配置串口通信、发送数据和接收数据等操作。以下是一个简单的示例代码,演示如何使用这些串口对象进行串口通信:

void setup() {
  // 初始化串口通信
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial2.begin(9600);
}

void loop() {

}

串口的打印输出函数

Serial.print("hello world");
Serial.printf("hello world");
Serial.println("hello world");

Serial.print()Serial.println()Serial.printf()函数在Arduino编程中都被用于向串口输出数据,但它们之间存在一些主要的区别:

  1. Serial.print():这个函数会将参数转换为字符串并打印到串口,参数之间不会自动添加分隔符或换行符。
  2. Serial.println():此函数除了具有Serial.print()的功能外,还会在输出的末尾自动添加一个换行符。如果参数是字符串、数组或数字,则会将其转换为字符串然后输出。此外,当传入的参数是单个字符时,该函数还会输出该字符的ASCII编码值和一个换行符。
  3. Serial.printf():这个函数与C语言中的printf()函数类似,允许你使用格式化字符串来指定输出数据的格式。与前两者不同,Serial.printf()会将格式化后的字符串直接发送到串口,而不是逐个字符地打印。
void setup() {
  // 初始化串口通信
  Serial.begin(9600);
}

void loop() {
  // 使用Serial.print()函数打印数据
  Serial.print("Hello, ");
  Serial.print("World!");
  
  // 使用Serial.println()函数打印数据
  Serial.println("Hello, World!");	//有回车换行
  Serial.println();	//回车换行
  Serial.println(14,HEX);	//以16进制打印输出数值14
  
  // 使用Serial.printf()函数打印数据
  int dat= 15;
  Serial.printf("Sensor Value: %d", dat);
}

串口的单字发送与接收

串口写单个字节
void Serial.write(uint8_t byte)
  • uint8_t byte:串口待发送的字节数据

在Arduino中使用Serial.write()函数来向串口写入单个字节示例:

void setup() {
  // 打开串口
  Serial.begin(9600);
}

void loop() {
  // 要发送的字节数据
  byte data = 'A';

  // 将字节数据写入串口
  Serial.write(data);

  // 延时一段时间,以便观察输出结果
  delay(1000);
}
检测串口数据接收长度并读取串口缓冲区数据
int Serial.available()
int Serial.read()
  • Serial.available()函数。该函数返回可用的字节数,即从串口缓冲区中可以读取的数据长度。
  • Serial.read()函数。该函数从串口缓冲区中读取一个字节的数据,并将其作为整数返回。

示例:

void setup() {
  // 打开串口
  Serial.begin(9600);
}

void loop() {
  // 检查是否有可用数据
  int availableBytes = Serial.available();

  // 如果有可用数据,则读取并处理
  if (availableBytes > 0) {
    // 读取数据
    char receivedData = Serial.read();

    // 处理数据(例如打印到串口监视器)
    Serial.print("Received data: ");
    Serial.println(receivedData);
  }
}

Serial.available()函数用于检测串口缓冲区中可用的字节数。如果返回值大于0,表示有可用数据,然后使用Serial.read()函数读取一个字节的数据,并进行相应的处理。

串口多字节发送与接收

串口写多个字节
size_t write(const char * buffer, size_t size)
  • buffer:要发送的字节数组指针
  • size:数组的长度
  • 函数的返回值是写入的字节数

Serial.write() 函数发送多个字节数组示例:

#include <Arduino.h>

void setup() {
  // 初始化串口通信
  Serial.begin(9600);
}

void loop() {
  // 定义要发送的字节数组
  byte data[] = {0x01, 0x02, 0x03, 0x04};
  
  // 获取字节数组的长度
  int length = sizeof(data) / sizeof(data[0]);
  
  // 通过串口发送字节数组
  Serial.write(data, length);
  
  // 延时一段时间,以便观察输出结果
  delay(1000);
}

串口读多个字节
size_t HardwareSerial::read(uint8_t *buffer, size_t size)
  • buffer 读取数据保存的数据缓冲区
  • size 将要读取的数据长度,单位为字节

要通过串口读取多个字节,可以使用Serial.available()函数来检查可用的字节数,然后使用Serial.read(buffer, size)函数读取多个字节。以下是一个示例代码:

#include <Arduino.h>

void setup() {
  // 初始化串口通信
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {

    // 创建字节数组来存储读取到的字节
    byte receivedData[64];

    delay(10);

    // 读取可用的字节数
    int  numBytes = Serial.available();

    // 逐个读取字节并存储到字节数组中
    Serial.read(receivedData,numBytes);
    // 处理接收到的数据
    //pas
  }
}


实训项目案例

1.单字节数据接收处理在发送

功能要求是接收通过串口(Serial)发送的数据,并将接收到的每个字节数据加1后重新发送回去。
代码:

#include <Arduino.h>

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

void loop() {
  unsigned char dat;
  if(Serial.available()>0){
    dat=Serial.read();
    dat++;
    Serial.write(dat);
  }
}

效果:
在串口助手中发送1接收到2
在这里插入图片描述

2.多字节数据接收处理在发送

功能要求接收数据,并发送字符串的大小和字符串

代码:

#include <Arduino.h>

void setup() {
  // 初始化串口通信
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {

    // 创建字节数组来存储读取到的字节
    byte receivedData[64];

    delay(10);

    // 读取可用的字节数
    int  numBytes = Serial.available();

    // 逐个读取字节并存储到字节数组中
    Serial.read(receivedData,numBytes);
    // 处理接收到的数据(这里只是简单地打印出来)
    Serial.printf("Received len:%d",numBytes);
    Serial.println();
    Serial.print("Received data: ");
    Serial.write(receivedData, numBytes);
    Serial.println();
    Serial.print("-----------------------");
    Serial.println();
  }
}

效果:
在这里插入图片描述

3.串口字节命令控制灯光开关

#include <Arduino.h>
#define d2 2

void setup() {
    //初始化灯光
    pinMode(d2,OUTPUT);
    //初始化UART
    Serial.begin(115200);
}

void loop() {
  //灯光的控制
  if(Serial.available()>0)
  {
    uint8_t cmd=0;
    cmd=Serial.read();
    switch(cmd)
    {
        case 0xA1:
            digitalWrite(d2,HIGH);
            Serial.println("d2 is ON!");
            break;
        case 0xA2:
            digitalWrite(d2,LOW);
            Serial.println("d2 is OFF!");
            break;
        default:
            Serial.println("输入命令错误");
    }
  }
}

在这里插入图片描述
发送A1,d2被点亮

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/307383.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

@FunctionalSpringBootTest 和@SpringBootTest注解的区别

FunctionalSpringBootTest 和 SpringBootTest 是Spring框架中用于测试的两个不同注解。下面是它们之间的主要区别&#xff1a; 用途和范围&#xff1a; SpringBootTest&#xff1a;这个注解用于需要测试Spring应用程序上下文的场合。它会加载完整的应用程序上下文&#xff0c;适…

案例:自定义下拉刷新动画(ArkTS)

文章目录 介绍相关概念完整示例代码结构解读 自定义下拉组件自定义刷新动画总结 介绍 本篇Codelab主要介绍组件动画animation属性设置。当组件的某些通用属性变化时&#xff0c;可以通过属性动画实现渐变效果&#xff0c;提升用户体验。 本Codelab使用的display接口处于mock阶…

Python 镜像源使用指南:加速你的开发过程

&#x1f31f;&#x1f30c; 欢迎来到知识与创意的殿堂 — 远见阁小民的世界&#xff01;&#x1f680; &#x1f31f;&#x1f9ed; 在这里&#xff0c;我们一起探索技术的奥秘&#xff0c;一起在知识的海洋中遨游。 &#x1f31f;&#x1f9ed; 在这里&#xff0c;每个错误都…

MongoDB存储原理

存储引擎是数据库的组件&#xff0c;负责管理数据如何存储在内存和磁盘上。MongoDB 支持多个存储引擎&#xff0c;因为不同的引擎对于特定的工作负载表现更好。选择合适的存储引擎可以显著影响应用程序的性能。 WiredTiger 介绍 MongoDB 从 3.0 开始引入可插拔存储引擎的概念…

Linux内存管理:(七)页面回收机制

文章说明&#xff1a; Linux内核版本&#xff1a;5.0 架构&#xff1a;ARM64 参考资料及图片来源&#xff1a;《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址&#xff1a; zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 1. 触发页面回收 Linux内核中触发页…

vue中使用component中的is渲染组件如何使用,:is 等价 v-if渲染组件。

动态组件顾名思义动态加载不同的组件&#xff0c;is属性用于加载不同组件&#xff0c;传参使用属性传递 1、使用v-for遍历component&#xff0c;组件都会执行 <componentv-for"(item, index) in TAB_PANE":key"index":is"item.componentName"…

什么是springmvc(介绍)

什么是springmvc 1. 什么是springmvc2.项目中加入springmvc支持2.1 导入依赖2.2 springMVC配置文件2.3 web.xml配置2.4 中文编码处理 3. 编写一个简单的controller4. 视图层配置4.1 视图解析器配置4.2 静态资源配置4.2 编写页面4.3 页面跳转方式 5. SpringMVC处理请求的流程6. …

如何本地搭建DolphinScheduler并无公网ip远程访问管理界面

文章目录 前言1. 安装部署DolphinScheduler1.1 启动服务 2. 登录DolphinScheduler界面3. 安装内网穿透工具4. 配置Dolphin Scheduler公网地址5. 固定DolphinScheduler公网地址 前言 本篇教程和大家分享一下DolphinScheduler的安装部署及如何实现公网远程访问&#xff0c;结合内…

计算机网络教程题(详解)

1、一个网络的物理线路上抓到 011001 位串的波形如下 请问该线路采用了 (B)编码方式。 A.二进制编码 B.曼彻斯特编码 c.差分曼彻斯特编码 D.归零编码 曼彻斯特编码:每一周期分为两个相等的间隔&#xff0c;二进制”1“位在发送时&#xff0c;在第一个间隔中为高电压&#…

淘宝商品数据采集订单数据采集店铺数据采集API演示

淘宝商品数据采集代码 -- 请求示例 url 默认请求参数已经URL编码处理 curl -i "https://api-gw.cn/taobao/item_get/?key<您自己的apiKey>&secret<您自己的apiSecret>&num_iid652874751412&is_promotion1" 商品详情页与获取到的返回数据示…

我的128天创作纪念日

&#x1f308;前言 最近我一直忙着期末复习备考&#xff0c;前天还一不小心感冒了&#xff0c;现在头昏脑胀&#xff0c;说不出话来。刚刚查看CSDN的后台私信&#xff0c;发现官方提示今天是我的128天创作纪念日&#xff0c;正好有几天没有更新博客了&#xff0c;今天更一篇。…

4.MapReduce 序列化

目录 概述序列化序列化反序例化java自带的两种Serializable非Serializable hadoop序例化实践 分片/InputFormat & InputSplit日志 结束 概述 序列化是分布式计算中很重要的一环境&#xff0c;好的序列化方式&#xff0c;可以大大减少分布式计算中&#xff0c;网络传输的数…

【VRTK】【VR开发】【Unity】19-VRTK实现旋转运动

课程配套学习项目源码资源下载 https://download.csdn.net/download/weixin_41697242/88485426?spm=1001.2014.3001.5503 【背景】 在实际开发中,旋转运动也是时常需要模拟的重要运动类型。常见的场景有开关门,方向盘轮胎以及拉动拉杆等等。 旋转运动的实现可以基于物理系…

服务器日常维护要素,应该如何做好维护

维护服务器的目的是为了让服务器的性能保持最佳状态&#xff0c;发现问题及时解决&#xff0c;没有问题也可以对相关的应用和配置进行调优。但也有很多用户疑问&#xff0c;服务器具体会有哪些方面需要维护的&#xff0c;今天就一起来看看吧。 服务器日常维护&#xff0c;主要包…

面向对象编程的五大原则,你了解吗?

面向对象编程的五大原则&#xff0c;你了解吗&#xff1f; 一、面向对象编程的概念 面向对象编程&#xff0c;是一种程序设计范式&#xff0c;也是一种编程语言的分类。它以对象作为程序的基本单元&#xff0c;将算法和数据封装其中&#xff0c;程序可以访问和修改对象关联的…

科研绘图(一)山脊图

从今日开始&#xff0c;为大家开辟一个新的系列科研绘图。同一个竞赛下&#xff0c;大家都近乎相同的解题思路下。之所以能出现一等二等三等奖的区别很大部分都在于结果的可视化&#xff0c;为了能更好地帮助大家进行可视化&#xff0c;今后将专门推出一个可视化板块&#xff0…

B端产品经理学习-权限管理

目录 权限管理的原则 常见的权限管理模型 总结 对企业而言&#xff0c;最重要的一个资源就是有价值的专有信息&#xff0c;也就是自己知道&#xff0c;而其他企业不知道的信息&#xff0c;因此&#xff0c;专有信息是企业的重要竞争力&#xff0c;权限管理的价值体现在专有信…

centos下升级git版本

1 问题描述 centos7系统默认的git安装版本是1.8&#xff0c;但是在项目构建中发现git版本过低&#xff0c;导致构建AI模型环境时出现各种错误&#xff0c;于是用源码编译的方式进行升级&#xff0c;同时该文章也适用于安装新的git。 2. 升级安装 2.1 第一步卸载原有的git r…

HarmonyOS应用开发学习笔记 UI布局学习 相对布局 (RelativeContainer)

UI布局学习 之 相对布局 &#xff08;RelativeContainer&#xff09; 官方文档 一、关键字 RelativeContainer&#xff0c; alignRules&#xff08;适配规则&#xff09; Text(Text02).alignRules({left: { anchor: text01, align: HorizontalAlign.Start },top: { anchor: t…

精通推荐算法4:经典DNN框架特征交叉模型 Deep Crossing(面试必备)

微软2016年提出的Deep Crossing模型奠定了深度学习精排模型的基本架构&#xff0c;具有十分重要的意义。它采用“Embedding MLP”的结构&#xff0c;成为目前推荐算法的基本范式。通过深度神经网络&#xff0c;实现大规模特征自动组合&#xff0c;大大减少了对人工构造交叉组合…