SoftwareSerial库【学习】

SoftwareSerial.h 文件解析

这个头文件定义了用于 ESP8266 和 ESP32 的软件串口实现的接口和一些功能。下面是关键部分的详细解释:

1. 文件头部注释
/*
SoftwareSerial.h - Implementation of the Arduino software serial for ESP8266/ESP32.
...
*/

这是文件的版权声明和许可证信息,表明这是为 ESP8266 和 ESP32 实现的 Arduino 软件串口库,并遵循 GNU Lesser General Public License。

2. 预处理器指令
#ifndef __SoftwareSerial_h
#define __SoftwareSerial_h

这部分代码是预处理器指令,用于防止头文件被多次包含,避免重复定义。

3. 包含其他头文件
#include "circular_queue/circular_queue.h"
#include <Stream.h>

这部分代码包含了其他必要的头文件,circular_queue.hStream.h,分别用于循环队列实现和串流接口。

4. 命名空间和接口定义
namespace EspSoftwareSerial {...
}

所有的代码都被包含在 EspSoftwareSerial 命名空间中,以避免命名冲突。IGpioCapabilities 接口定义了 GPIO 引脚的功能检查,例如是否为有效引脚,是否有上拉电阻等。

5. GpioCapabilities
class GpioCapabilities : private IGpioCapabilities {
public:static constexpr bool isValidPin(int8_t pin) {...}...
};

这个类继承了 IGpioCapabilities 并实现了具体的方法来检查 GPIO 引脚的能力。不同的处理器(ESP8266 和 ESP32)有不同的实现。

6. BasicUART 类模板和 UART 类型
template <typename GpioType>
class BasicUART : public UARTBase {...
};using UART = BasicUART<GpioCapabilities>;

BasicUART 是一个模板类,使用 GpioCapabilities 作为模板参数来实现具体的 UART 功能。UARTBasicUART 的具体实例。

7. 导出接口
using SoftwareSerial = EspSoftwareSerial::UART;
using namespace EspSoftwareSerial;

这部分代码将 SoftwareSerial 定义为 EspSoftwareSerial::UART,并使用 EspSoftwareSerial 命名空间,以便于使用。

8. 显式模板实例化
#if __GNUC__ < 12
...
#endif // __GNUC__ < 12

为了处理 GCC 编译器的特定问题,这部分代码显式实例化了一些模板函数。

9. 结束预处理器指令
#endif // __SoftwareSerial_h

结束预处理器指令,防止头文件被多次包含。

接下来,我将查看并解析 SoftwareSerial.cpp 文件。

SoftwareSerial.cpp 文件解析

这个文件实现了 SoftwareSerial.h 中声明的功能。以下是关键部分的详细解释:

1. 文件头部注释
/*
SoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266/ESP32.
...
*/

和头文件类似,这是版权声明和许可证信息。

2. 包含头文件
#include "SoftwareSerial.h"
#include <Arduino.h>

包含 SoftwareSerial.h 头文件和 Arduino 的核心头文件 Arduino.h

3. 使用命名空间
using namespace EspSoftwareSerial;

使用 EspSoftwareSerial 命名空间中的所有内容。

4. 条件编译变量定义
#ifndef ESP32
uint32_t UARTBase::m_savedPS = 0;
#else
portMUX_TYPE UARTBase::m_interruptsMux = portMUX_INITIALIZER_UNLOCKED;
#endif

根据是否是 ESP32 平台,定义不同的变量以处理中断。

5. 中断处理函数
ALWAYS_INLINE_ATTR inline void IRAM_ATTR UARTBase::disableInterrupts()
{
#ifndef ESP32m_savedPS = xt_rsil(15);
#elsetaskENTER_CRITICAL(&m_interruptsMux);
#endif
}ALWAYS_INLINE_ATTR inline void IRAM_ATTR UARTBase::restoreInterrupts()
{
#ifndef ESP32xt_wsr_ps(m_savedPS);
#elsetaskEXIT_CRITICAL(&m_interruptsMux);
#endif
}

这两个内联函数用于禁用和恢复中断,以确保在关键代码段内操作的原子性。

6. 常量定义
constexpr uint8_t BYTE_ALL_BITS_SET = ~static_cast<uint8_t>(0);

定义了一个常量 BYTE_ALL_BITS_SET,它的值是 0xFF(所有位都设置为1)。

7. UARTBase 构造函数和析构函数
UARTBase::UARTBase() {
}UARTBase::UARTBase(int8_t rxPin, int8_t txPin, bool invert)
{m_rxPin = rxPin;m_txPin = txPin;m_invert = invert;
}UARTBase::~UARTBase() {end();
}

这些是 UARTBase 类的构造函数和析构函数。它们分别初始化和清理串口。

8. 设置 GPIO 引脚模式
void UARTBase::setRxGPIOPinMode() {if (m_rxValid) {pinMode(m_rxPin, m_rxGPIOHasPullUp && m_rxGPIOPullUpEnabled ? INPUT_PULLUP : INPUT);}
}void UARTBase::setTxGPIOPinMode() {if (m_txValid) {pinMode(m_txPin, OUTPUT);digitalWrite(m_txPin, !m_invert);}
}

这些函数设置接收和发送引脚的模式。根据引脚是否有效和是否需要上拉电阻,选择合适的模式。

9. 启动串口
void UARTBase::begin(uint32_t baud, Config config, int8_t rxPin, int8_t txPin, bool invert)
{// 配置波特率、引脚和其他参数
}

这个函数启动串口,配置波特率、引脚和其他参数。

10. 接收和发送处理函数
void UARTBase::handleRx()
{// 接收处理逻辑
}void UARTBase::handleTx()
{// 发送处理逻辑
}

这些函数处理接收和发送数据的逻辑。

11. 接收中断服务程序
void IRAM_ATTR UARTBase::rxISR(UARTBase* self)
{// 中断服务程序逻辑
}

这是接收中断服务程序,当接收到数据时触发,处理数据并调用相应的回调函数。

整体功能总结

  • SoftwareSerial.h 文件:定义了类和接口,用于管理软件串口的配置和功能,包括引脚有效性检查、串口配置等。
  • SoftwareSerial.cpp 文件:实现了这些功能,提供了具体的串口初始化、中断处理、数据接收和发送的实现。

这两个文件共同实现了在 ESP8266 和 ESP32 上使用软件串口通信的功能,允许在硬件串口不够用的情况下通过软件模拟更多的串口。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell脚本if/else使用示例

if判断字符串是否为空实例 #!/bin/bashread -p "input string > " str if [ -z "$str" ] thenecho "str是空" elseecho "str非空" fiif判断整数是否为…

每日一学(1)

目录 1、ConCurrentHashMap为什么不允许key为null&#xff1f; 2、ThreadLocal会出现内存泄露吗&#xff1f; 3、AQS理解 4、lock 和 synchronized的区别 1、ConCurrentHashMap为什么不允许key为null&#xff1f; 底层 putVal方法 中 如果key || value为空 抛出…

深度解析RocketMq源码-高可用存储组件(四)Dledger框架日志同步流程

1.绪论 在深度解析RocketMq源码-高可用存储组件&#xff08;一&#xff09; raft协议详解-CSDN博客 中讲过&#xff0c;raft协议中&#xff0c;日志同步主要有两个地方&#xff0c;一个是leader会跟follower同步数据&#xff0c;另一个是在新leader诞生的时候&#xff0c;会与…

6.浏览器缓存

上一篇&#x1f449;: 浏览器存储 浏览器缓存 文章目录 浏览器缓存1. 浏览器缓存机制的理解初次加载资源强制缓存阶段协商缓存阶段服务器响应版本控制策略 2 浏览器资源缓存的位置Service Worker缓存Memory Cache&#xff08;内存缓存&#xff09;Disk Cache&#xff08;磁盘缓…

更换Homebrew镜像源

Homebrew 是 macOS 上非常受欢迎的包管理工具&#xff0c;但有时由于网络问题&#xff0c;从默认源下载软件包可能会非常缓慢。为了解决这个问题&#xff0c;我们可以将 Homebrew 的源更换为国内的镜像&#xff0c;以提高下载速度。以下是更换 Homebrew 镜像源的通用步骤及错误…

【Pytorch实战教程】基于投影梯度下降(PGD)方法的对抗样本生成

文章目录 1. 总体介绍2. 完整代码3. 投影梯度下降(PGD)方法的详细介绍3.1. 背景3.2. PGD方法简介3.3. PGD攻击算法步骤3.4. PGD攻击的实现3.5. 代码解释3.6. 核心代码解释:4 补充说明x = inputs.detach()的详细解释1. 总体介绍 使用PyTorch实现基于投影梯度下降(Projected…

npm ERR! ..... reason: certificate has expired(淘宝镜像过期)

在执行npm install命令时&#xff0c;报错如下 npm ERR! request to https://registry.npm.taobao.org/babel/plugin-syntax-dynamic-import/download/babel/plugin-syntax-dynamic-import-7.8.3.tgz failed, reason: certificate has expired原因&#xff1a;淘宝证书过期 解…

vue2面试题——指令

1. 如何自定义指令 全局指令&#xff1a;在main.js里面写 /* 全局自定义指令 */ // main.js文件 import Vue from vue import App from ./App.vue import router from ./router import store from ./storeVue.config.productionTip falseVue.directive(demo,{inserted: functi…

【新闻】金融专业“免进”!私募巨头招聘涌现“新剧情”

A股市场在2024年逐渐出现新的运行特征&#xff0c;这不禁让部分主动投资的私募巨头公司重新登上招聘舞台。 但这一次&#xff0c;他们的招聘方向出现了新的变动。 有些机构有意识的为公司投研团队招聘“衔接”岗&#xff0c;有些则把重点放在了投研动作的交易层。 但这都不如…

小公司全栈是归宿吗?

在软件开发领域&#xff0c;特别是在小公司或初创公司中&#xff0c;全栈开发者的角色确实相对普遍和重要。然而&#xff0c;说“全栈是归宿”可能过于绝对&#xff0c;因为每个开发者的职业路径和兴趣点都是不同的。 以下是关于全栈开发在小公司的一些考虑&#xff1a; 需求…

JS实现:计算不同时区的当地时间

国内的时间都以北京时间为准&#xff08;即东八区的时间&#xff09;&#xff0c;如何计算同一时间下其它时区的当地时间呢&#xff1f; 通常的做法&#xff0c;是计算出时区差&#xff0c;然后进行加减。 还有另一种方法&#xff0c;就是先把本地时间转为 0时区的utc时间&…

如何使用代理 IP 防止多个 Facebook 帐户关联 - 最佳实践

在社交媒体被广泛应用的今天&#xff0c;Facebook作为全球最大的社交网络平台之一&#xff0c;面临着很多挑战&#xff0c;其中之一就是用户行为的管理和安全。 为了防止多个账户之间的关联和滥用&#xff0c;Facebook需要采取一系列措施&#xff0c;其中包括使用静态住宅代理…

云计算运维工程师的突发状况处理

云计算运维工程师在应对突发的故障和紧急情况时,需要采取一系列迅速而有效的措施来最小化服务中断的时间并恢复系统的稳定性。 以下是一些关键步骤和策略: 快速响应: 立即识别并确认故障的性质和范围。通知团队成员和相关的利益相关者,确保所有人了解当前情况。故障诊断:…

【论文阅读】-- MultiStream:探索分层时间序列的多分辨率流图方法

MultiStream: A Multiresolution Streamgraph Approach to Explore Hierarchical Time Series 摘要1 引言2相关工作2.1 堆叠图和流图可视化2.2 时间序列的层次结构2.3 交互技术 3 需求分析4 视觉映射和功能4.1 设计原理总结4.2 概述4.3 多分辨率视图4.4 控制器4.5 层次管理器 5…

使用 ADB 查看 Android 设备的 CPU 使用率(详解)

在 Android 开发和调试过程中&#xff0c;监控设备的性能数据至关重要。CPU 使用率是一个关键的性能指标&#xff0c;它能够帮助开发者识别应用的性能瓶颈和优化机会。本文将详细介绍如何使用 Android Debug Bridge (ADB) 查看设备的 CPU 使用率&#xff0c;并解释终端上各个参…

ssm日常项目中问题集合

一、 在Spring MVC和Spring Boot中&#xff0c;如果你的控制器方法参数被标注为一个Java对象&#xff0c;并且该对象的字段与表单输入字段的名称匹配&#xff0c;Spring会自动将表单数据绑定到该对象上。这种机制称为数据绑定&#xff08;Data Binding&#xff09;。 假设你有…

探索ChatGPT在程序员日常工作的多种应用

引言 在现代科技迅猛发展的今天&#xff0c;人工智能的应用已经深入到我们生活和工作的各个方面。作为程序员&#xff0c;我们时常面临大量繁杂的任务&#xff0c;从代码编写、错误调试到项目管理和团队协作&#xff0c;每一项都需要花费大量的时间和精力。近年来&#xff0c;…

基于信息论的高动态范围图像评价算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于信息论的高动态范围图像评价算法matlab仿真&#xff0c;利用一种自然图像的概率模型对图像的熵与成像动态范围之间的关系进行了数值模拟,得到了具有普遍意义上…

【数据库】Oracle安装报错(口令设置问题)

目录 一、问题场景&#xff1a; 二、问题描述 三、原因分析&#xff1a; 四、解决方案&#xff1a; 方法一&#xff1a; 方法二&#xff1a; 一、问题场景&#xff1a; Oracle安装 二、问题描述 Oracle安装意外中断导致【口令管理】用户没有取消勾选/修改密码 三、原因…

mybatis中动态sql语句like concat(“%“,#{xm},“%“)

1、动态SQL是一种可以根据不同条件生成不同SQL语句的技术&#xff0c;随着用户输入或外部条件变化而变化的SQL语句 2、SQL语句中的like模糊查询 xm like %小米%&#xff0c;但开发中经常用到 xm like concat("%",#{xm},"%")&#xff0c;可以防止sql注入…