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 ESP32
    m_savedPS = xt_rsil(15);
#else
    taskENTER_CRITICAL(&m_interruptsMux);
#endif
}

ALWAYS_INLINE_ATTR inline void IRAM_ATTR UARTBase::restoreInterrupts()
{
#ifndef ESP32
    xt_wsr_ps(m_savedPS);
#else
    taskEXIT_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 上使用软件串口通信的功能,允许在硬件串口不够用的情况下通过软件模拟更多的串口。

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值