Roson的Qt之旅#87 QSerialPort类

160 篇文章 31 订阅

1.综述

QSerialPort类提供串口访问功能。

您可以使用QSerialPortInfo helper类获得有关可用串行端口的信息,它允许枚举系统中的所有串行端口。这对于获取您想要使用的串口的正确名称非常有用。您可以将helper类的对象作为参数传递给setPort()或setPortName()方法,以分配所需的串行设备。

设置端口后,可以使用open()方法以只读(r/o)、只写 (w/o)或可读可写 (r/w)模式打开端口。
注意:串口总是以独占访问方式打开的(也就是说,没有其他进程或线程可以访问已经打开的串口)。
使用close()方法关闭端口并取消I/O操作。

成功打开后,QSerialPort将尝试确定端口的当前配置并初始化自己。您可以使用setBaudRate(), setDataBits(), setParity(), setStopBits()和setFlowControl()方法将端口重新配置为所需的设置。
有两个属性可以处理pinout信号,即:QSerialPort::dataTerminalReady, QSerialPort::requestToSend。也可以使用pinoutSignals()方法来查询当前的pinout信号集。
一旦您知道端口已经可以读或写了,您就可以使用read()或write()方法。另外,也可以调用方便的readLine()和readAll()方法。如果不是一次读取所有数据,那么当新的传入数据被追加到QSerialPort的内部读缓冲区时,剩下的数据将在以后可用。可以使用setReadBufferSize()限制读缓冲区的大小。

QSerialPort提供了一组函数,用于挂起调用线程,直到发出某些信号。这些函数可以用来实现阻塞串口:
waitForReadyRead()会阻塞调用,直到有新的数据可供读取。
waitForBytesWritten()会阻塞调用,直到一个数据负载被写入串口。

请看下面的例子:

  int numRead = 0, numReadTotal = 0;
  char buffer[50];

  for (;;) {
      numRead  = serial.read(buffer, 50);

      // Do whatever with the array

      numReadTotal += numRead;
      if (numRead == 0 && !serial.waitForReadyRead())
          break;
  }

如果waitForReadyRead()返回false,则表示连接已经关闭或发生了错误。
如果在任何时间点发生错误,QSerialPort将发出errorOccurred()信号。您还可以调用error()来查找上次发生的错误类型。

使用阻塞串行端口编程与使用非阻塞串行端口编程截然不同。阻塞串行端口不需要事件循环,通常会导致更简单的代码。但是,在GUI应用程序中,阻塞串口应该只在非GUI线程中使用,以避免冻结用户界面。

有关这些方法的详细信息,请参阅示例应用程序。

QSerialPort类也可以与QTextStream和QDataStream的流操作符(operator<<()和operator>>())一起使用。不过,有一个问题需要注意:在尝试使用操作符>>()重载操作符进行读取之前,请确保有足够的数据可用。

相关信息还可查阅QSerialPortInfo。


2.成员类型

enum QSerialPort::BaudRate
该enum描述通信设备运行的波特率。
注意:本enum中只列出最常见的标准波特率。

ConstantValueDescription
QSerialPort::Baud120012001200 baud.
QSerialPort::Baud240024002400 baud.
QSerialPort::Baud480048004800 baud.
QSerialPort::Baud960096009600 baud.
QSerialPort::Baud192001920019200 baud.
QSerialPort::Baud384003840038400 baud.
QSerialPort::Baud576005760057600 baud.
QSerialPort::Baud115200115200115200 baud.
QSerialPort::UnknownBaud-1未知的波特。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。

enum QSerialPort::DataBits

该枚举描述使用的数据位数

ConstantValueDescription
QSerialPort::Data55每个字符的数据位数为5。它用于博多码。它通常只适用于老式设备,如电传打印机。
QSerialPort::Data66每个字符的数据位数为6。它很少被使用。
QSerialPort::Data77每个字符的数据位数为7。它用于真正的ASCII码。它通常只适用于老式设备,如电传打印机。
QSerialPort::Data88每个字符的数据位数为8。它用于大多数类型的数据,因为它的大小与一个字节的大小匹配。它几乎普遍用于较新的应用程序。
QSerialPort::UnknownDataBits-1未知位数。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。

enum QSerialPort::Direction

此枚举描述了数据传输可能的方向。
注意:此枚举用于在某些操作系统(例如,类posix)上为每个方向分别设置设备的波特率。

ConstantValue描述
QSerialPort::Input1输入方向。
QSerialPort::Output2输出方向。
QSerialPort::AllDirectionsInput | Output同时在两个方向上。

方向类型是QFlags<Direction>的类型定义。它存储方向值的OR组合。

enum QSerialPort::FlowControl

此枚举描述所使用的流控制。

ConstantValue描述
QSerialPort::NoFlowControl0没有流控制。
QSerialPort::HardwareControl1硬件流控制(RTS/CTS)。
QSerialPort::SoftwareControl2软件流控制(XON/XOFF)。
QSerialPort::UnknownFlowControl-1未知的流控制。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。

enum QSerialPort::Parity

描述所使用的奇偶校验方案。

ConstantValueDescription
QSerialPort::NoParity0它没有发送奇偶校验位。这是最常见的奇偶校验设置。错误检测由通信协议处理。
QSerialPort::EvenParity2每个字符中1位的数目,包括奇偶校验位,总是偶数。
QSerialPort::OddParity3每个字符中1位的数目,包括奇偶校验位,总是奇数。它确保每个字符中至少发生一个状态转换。
QSerialPort::SpaceParity4空间平价。奇偶校验位在空间信号条件下被发送。它不提供错误检测信息。
QSerialPort::MarkParity5马克平价。奇偶校验位总是设置为标记信号条件(逻辑1),它不提供错误检测信息。
QSerialPort::UnknownParity-1未知的平价。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。

enum QSerialPort::PinoutSignal

此枚举描述可能的RS-232接口输出信号。

ConstantValueDescription
QSerialPort::NoSignal0x00没有行活动
QSerialPort::TransmittedDataSignal0x01TxD(传输数据)。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。
QSerialPort::ReceivedDataSignal0x02RxD(接收的数据)。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。
QSerialPort::DataTerminalReadySignal0x04DTR(数据终端就绪)。
QSerialPort::DataCarrierDetectSignal0x08DCD(数据载波检测)。
QSerialPort::DataSetReadySignal0x10DSR(数据集就绪)。
QSerialPort::RingIndicatorSignal0x20RNG(环指标)。
QSerialPort::RequestToSendSignal0x40RTS(请求发送)。
QSerialPort::ClearToSendSignal0x80CTS(清除发送)。
QSerialPort::SecondaryTransmittedDataSignal0x100STD(二次传输数据)。
QSerialPort::SecondaryReceivedDataSignal0x200SRD (Secondary Received Data)。

PinoutSignals类型是QFlags<PinoutSignal>的类型定义。它存储PinoutSignal值的OR组合。

enum QSerialPort::SerialPortError

该enum描述QSerialPort::error属性可能包含的错误。

ConstantValueDescription
QSerialPort::NoError0没有错误发生。
QSerialPort::DeviceNotFoundError1试图打开不存在的设备时出错。
QSerialPort::PermissionError2当试图打开另一个进程或用户没有足够的权限和凭据打开一个已经打开的设备时,发生了一个错误。
QSerialPort::OpenError3试图打开此对象中已打开的设备时出错。
QSerialPort::NotOpenError13此错误发生在执行操作时,只有在设备打开时才能成功执行操作。该值在QtSerialPort 5.2中引入。
QSerialPort::ParityError4读取数据时,硬件检测到奇偶校验错误。这个值已经过时了。我们强烈建议不要在新代码中使用它。
QSerialPort::FramingError5读取数据时硬件检测到的帧错误。这个值已经过时了。我们强烈建议不要在新代码中使用它。
QSerialPort::BreakConditionError6硬件在输入线上检测到的断路状态。这个值已经过时了。我们强烈建议不要在新代码中使用它。
QSerialPort::WriteError7事件解释写入数据时发生I/O错误。
QSerialPort::ReadError8读取数据时发生I/O错误。处理步骤
QSerialPort::ResourceError9资源不可用时发生I/O错误,例如设备意外从系统中移除。
QSerialPort::UnsupportedOperationError10正在运行的操作系统不支持或禁止请求的设备操作。
QSerialPort::TimeoutError12发生超时错误。该值在QtSerialPort 5.2中引入。
QSerialPort::UnknownError11发生了一个无法确认的错误。

enum QSerialPort::StopBits

这个枚举描述使用的停止位数。

ConstantValueDescription
QSerialPort::OneStop11停止位。
QSerialPort::OneAndHalfStop31.5停止位。这仅适用于Windows平台。
QSerialPort::TwoStop22停止位。
QSerialPort::UnknownStopBits-1停止位的数目未知。这个值已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。


3.属性介绍

baudRate : qint32
此属性保存所需方向的数据波特率

如果设置成功或在打开端口之前设置,则返回true;否则返回false并设置一个错误码,该错误码可以通过访问QSerialPort::error属性的值获得。要设置波特率,使用枚举QSerialPort::BaudRate或任何正的qint32值。

注意:如果该设置是在打开端口之前设置的,那么在端口成功打开之后,实际的串口设置将在QSerialPort::open()方法中自动完成。

警告:所有平台都支持设置AllDirections标志。Windows仅支持该模式。
警告:在Windows上,在任何方向返回相同的波特率。

缺省值为波特9600,即每秒9600位。

关联函数:
qint32 baudRate(Directions directions = AllDirections) const
bool setBaudRate(qint32 baudRate, Directions directions = AllDirections)

关联信号:
void baudRateChanged(qint32 baudRate, QSerialPort::Directions directions)


breakEnabled : bool

此属性保存处于断开状态的传输线的状态

成功返回true,否则返回false。如果标志为真,则传输线处于断路状态;否则处于非中断状态。
注意:在设置或获取此属性之前,必须打开串口;否则返回false并设置NotOpenError错误码。与类的常规Qt属性设置相比,这有点不同寻常。但是,这是一个特殊的用例,因为属性是通过与内核和硬件的交互来设置的。因此,这两种情况不能完全相互比较。
这个属性是在Qt 5.5中引入的。

关联函数:
bool isBreakEnabled() const
bool setBreakEnabled(bool set = true)

关联信号:
void breakEnabledChanged(bool set)

dataBits : DataBits

这个属性保存帧中的数据位

如果设置成功或在打开端口之前设置,则返回true;否则返回false并设置一个错误码,该错误码可以通过访问QSerialPort::error属性的值获得。

注意:如果该设置是在打开端口之前设置的,那么在端口成功打开之后,实际的串口设置将在QSerialPort::open()方法中自动完成。默认值是Data8,即8个数据位。

关联函数:
DataBits dataBits() const
bool setDataBits(DataBits dataBits)

关联信号:
void dataBitsChanged(QSerialPort::DataBits dataBits)

dataTerminalReady : bool

这个属性保存线路信号DTR的状态(高或低)

成功返回true,否则返回false。如果标志为true,则DTR信号设置为高;否则低。

注意:在设置或获取此属性之前,必须打开串口;否则返回false,错误码设置为NotOpenError。

关联函数:
bool isDataTerminalReady()
bool setDataTerminalReady(bool set)

关联信号:
void dataTerminalReadyChanged(bool set)

See also pinoutSignals().


error : SerialPortError

此属性保存串口的错误状态

I/O设备状态返回错误码。例如,如果open()返回false,或者读/写操作返回-1,这个属性可以用来找出操作失败的原因。

在调用clearError()之后,错误码被设置为默认的QSerialPort::NoError

关联函数:
SerialPortError error() const
void clearError()

flowControl : FlowControl

此属性保存所需的流控制模式

如果设置成功或在打开端口之前设置,则返回true;否则返回false并设置一个错误码,该错误码可以通过访问QSerialPort::error属性的值获得。

注意:如果该设置是在打开端口之前设置的,那么在端口成功打开之后,实际的串口设置将在QSerialPort::open()方法中自动完成。

默认值为“NoFlowControl”,即不进行流量控制。

关联函数:
FlowControl flowControl() const
bool setFlowControl(FlowControl flowControl)

关联信号:
void flowControlChanged(QSerialPort::FlowControl flow)

parity : Parity

此属性保存奇偶校验模式

如果设置成功或在打开端口之前设置,则返回true;否则返回false并设置一个错误码,该错误码可以通过访问QSerialPort::error属性的值获得。

注意:如果该设置是在打开端口之前设置的,那么在端口成功打开之后,实际的串口设置将在QSerialPort::open()方法中自动完成。

默认值为“NoParity”,即不校验。

关联函数:
Parity parity() const
bool setParity(Parity parity)

关联信号:
void parityChanged(QSerialPort::Parity parity)

requestToSend : bool

这个属性保存线路信号RTS的状态(高或低)

成功返回true,否则返回false。如果该标志为真,则RTS信号将设为高位;否则低。

注意:在设置或获取此属性之前,必须打开串口;否则返回false,错误码设置为NotOpenError。
注意:试图在硬件控制模式下控制RTS信号将失败,错误代码设置为UnsupportedOperationError,因为信号是由驱动程序自动控制的。

关联函数:
bool isRequestToSend()
bool setRequestToSend(bool set)

关联信号:
void requestToSendChanged(bool set)

See also pinoutSignals().

stopBits : StopBits

这个属性保存帧中的停止位数

如果设置成功或在打开端口之前设置,则返回true;否则返回false并设置一个错误码,该错误码可以通过访问QSerialPort::error属性的值获得。

注意:如果该设置是在打开端口之前设置的,那么在端口成功打开之后,实际的串口设置将在QSerialPort::open()方法中自动完成。

缺省值为一站式,即1个停止位。

关联函数:
StopBits stopBits() const
bool setStopBits(StopBits stopBits)

关联信号:
void stopBitsChanged(QSerialPort::StopBits stopBits)


4.成员函数

QSerialPort::QSerialPort(QObject *parent = nullptr)
用给定的父对象构造一个新的串行端口对象。

QSerialPort::QSerialPort(const QString &name, QObject *parent = nullptr)
构造一个新的串口对象与给定父代表指定名称的串行端口。
名称应具有特定的格式;参见setPort()方法。

QSerialPort::QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent = nullptr)
构造一个新的串口对象与给定父代表指定的串口助手类serialPortInfo。

[virtual] QSerialPort::~QSerialPort()
如果需要,关闭串口,然后销毁对象。

[virtual] bool QSerialPort::atEnd() const
重新实现从QIODevice: atEnd()。
如果当前没有更多数据可供读取,则返回true;否则返回false。
这个函数是最常用的从串口读取数据时在一个循环中。例如:

  // This slot is connected to QSerialPort::readyRead()
  void QSerialPortClass::readyReadSlot()  {
      while (!port.atEnd()) {
          QByteArray data = port.read(100);
          ....
      }
  }

See also bytesAvailable() and readyRead().

[signal] void QSerialPort::baudRateChanged(qint32 baudRate, QSerialPort::Directions directions)
这个信号是在波特率改变后发出的。新的波特率以波特率形式传递,方向以方向形式传递。
注意:属性波特率的通知信号。
参见QSerialPort::baudRate。

[virtual] qint64 QSerialPort::bytesAvailable() const
重新实现从QIODevice: bytesAvailable()。  
返回等待读取的传入字节数。  

[virtual] qint64 QSerialPort::bytesToWrite() const
重新实现从QIODevice: bytesToWrite()。
返回的字节数,等待。当控制返回到事件循环或调用flush()时,将写入字节。

[virtual] bool QSerialPort::canReadLine() const
重新实现从QIODevice: canReadLine()。
如果可以从串口读取一行数据,则返回true;否则返回false。

bool QSerialPort::clear(Directions directions = AllDirections)
根据给定的方向,丢弃输出或输入缓冲区中的所有字符。这包括清除内部类缓冲区和UART(驱动程序)缓冲区。也终止挂起的读或写操作。如果成功,返回true;否则返回false。
注意:在试图清除任何缓冲数据之前,串口必须是打开的;否则返回false并设置NotOpenError错误码。

[virtual] void QSerialPort::close()
重新实现从QIODevice: close()。
注意:串行端口被打开之前试图关闭它;否则设置NotOpenError错误代码。
参见QIODevice: close()。

[signal] void QSerialPort::dataBitsChanged(QSerialPort::DataBits dataBits)
这个信号是在帧中的数据位被改变后发出的。帧中的新数据位作为dataBits传递。
注意:属性dataBits的通知信号。
参见QSerialPort:: dataBits。

[signal] void QSerialPort::dataTerminalReadyChanged(bool set)
这个信号是在线路信号DTR的状态(高或低)被改变后发出的。线路信号DTR的新状态(高或低)作为设置传递。
注意:属性dataTerminalReady的通知信号。
参见QSerialPort:: dataTerminalReady。

[signal] void QSerialPort::errorOccurred(QSerialPort::SerialPortError error)
当串口发生错误时,发出该信号。指定的错误描述发生的错误类型。
该函数是在Qt 5.8中引入的。
参见QSerialPort::error

[signal] void QSerialPort::flowControlChanged(QSerialPort::FlowControl flow)
这个信号是在流量控制模式被改变之后发出的。新流控制方式是通过流。
注意:属性flowControl的通知信号。
参见QSerialPort:: flowControl。

bool QSerialPort::flush()
这个函数在不阻塞的情况下,尽可能多地从内部写缓冲区写入底层串口。如果写入了任何数据,这个函数返回true;否则返回false。
调用此函数,将缓冲后的数据立即发送到串口。成功写入的字节数取决于操作系统。在大多数情况下,不需要调用这个函数,因为一旦控制返回到事件循环,QSerialPort类将开始自动发送数据。如果没有事件循环,则调用waitForBytesWritten()。
注意:在尝试刷新任何缓冲数据之前,串行端口必须是打开的;否则返回false并设置NotOpenError错误码。
请参见write()和waitForBytesWritten()。

Handle QSerialPort::handle() const
如果支持平台并且串口是开放的,则返回本机串口句柄;否则返回1。
警告:此功能仅供专家使用;使用它的风险由你自己承担。此外,这个函数在小Qt版本之间没有兼容性承诺。
这个函数是在Qt 5.2中引入的。

[virtual] bool QSerialPort::isSequential() const
重新实现从QIODevice: isSequential()。
总是返回true。串口为顺序设备。

[virtual] bool QSerialPort::open(OpenMode mode)
重新实现从QIODevice:: open()。
使用OpenMode模式打开串口,成功返回true;否则返回false并设置一个可以通过调用error()方法获得的错误代码。
注意:如果打开端口成功,但不能成功设置任何端口设置,则该方法返回false。在这种情况下,端口自动关闭不要离开港口在不正确的设置。
警告:该模式必须为QIODevice::ReadOnly, QIODevice::WriteOnly或QIODevice::ReadWrite。不支持其他模式。
请参见QIODevice::OpenMode和setPort()。

[signal] void QSerialPort::parityChanged(QSerialPort::Parity parity)
这个信号在奇偶校验模式被改变后发出。新的奇偶校验模式以奇偶校验方式传递。
注意:属性奇偶校验的通知信号。
参见QSerialPort::奇偶校验。

PinoutSignals QSerialPort::pinoutSignals()
以位图格式返回行信号的状态。
从这个结果中,可以通过应用掩码“AND”来分配所需信号的状态,其中掩码是来自QSerialPort::PinoutSignals的所需枚举值。
注意:此方法执行系统调用,从而确保正确返回线路信号状态。当底层操作系统不能提供关于更改的适当通知时,这是必要的。
注:需要打开串口才能获取引脚信号;否则返回NoSignal并设置NotOpenError错误码。
参见QSerialPort::dataTerminalReady和QSerialPort::requestToSend。

QString QSerialPort::portName() const
返回由setPort()设置或传递给QSerialPort构造函数的名称。这个名称很短,也就是说,它是从设备的内部变量系统位置中提取和转换出来的。转换算法是平台特有的:

Platform简要描述
Windows删除前缀“\\.\”。\”或“//./",并返回字符串的剩余部分。
Unix, BSD从系统位置移除前缀“/dev/”,并返回字符串的剩余部分。

qint64 QSerialPort::readBufferSize() const
返回内部读缓冲区的大小。这限制了客户端在调用read()或readAll()方法之前可以接收的数据量。
读取缓冲区大小为0(默认值)意味着缓冲区没有大小限制,确保没有数据丢失。
参见setReadBufferSize()和read()。

[virtual protected] qint64 QSerialPort::readData(char *data, qint64 maxSize)
重新实现从QIODevice: readData()。

[virtual protected] qint64 QSerialPort::readLineData(char *data, qint64 maxSize)
重新实现从QIODevice: readLineData()。

[signal] void QSerialPort::requestToSendChanged(bool set)
这个信号是在线路信号RTS的状态(高或低)被改变后发出的。线路信号RTS的新状态(高或低)被作为设置传递。
注意:属性requestToSend的通知信号。
参见QSerialPort:: requestToSend。

bool QSerialPort::sendBreak(int duration = 0)
此函数已弃用。
发送一个连续流的零位指定时间在毫秒期间是否使用异步串行数据终端。如果成功,返回true;否则返回false。
如果持续时间为零,则零比特至少通过0.25秒传输,但不超过0.5秒。
如果持续时间是非零的,则根据实现的不同,在一定的时间内传输零比特。
注意:在尝试发送中断持续时间之前,串口必须打开;否则返回false并设置NotOpenError错误码。
参见setBreakEnabled()。

void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
设置存储在串口信息实例serialPortInfo中的端口。
参见portName()和QSerialPortInfo。

void QSerialPort::setPortName(const QString &name)
设置串口的名称。
如果需要,串行端口的名称可以传递为短名称或长系统位置。
参见portName()和QSerialPortInfo。

void QSerialPort::setReadBufferSize(qint64 size)
将QSerialPort的内部读缓冲区的大小设置为字节大小。
如果缓冲区大小被限制到某个大小,QSerialPort将不会缓存超过这个大小的数据。缓冲区大小为0的特殊情况意味着读取缓冲区是无限制的,所有传入数据都被缓冲。这是默认值。
如果数据只在特定时间点读取(例如在实时流应用程序中),或者应该保护串行端口不接收过多的数据(这些数据可能最终导致应用程序耗尽内存),则此选项非常有用。
请参见readBufferSize()和read()。

[signal] void QSerialPort::stopBitsChanged(QSerialPort::StopBits stopBits)
这个信号是在帧中的停止位数被改变后发出的。帧中新的停止位数被作为stopBits传递。
注意:属性stopBits的通知信号。
参见QSerialPort:: stopBits。

[virtual] bool QSerialPort::waitForBytesWritten(int msecs = 30000)
重新实现从QIODevice: waitForBytesWritten()。
这个函数会一直阻塞,直到至少有一个字节被写入串口并且bytesWritten()信号被发出。函数将在msecs毫秒后超时;缺省超时时间为30000毫秒。如果msecs为-1,则此函数不会超时。
如果发出了bytesWritten()信号,则函数返回true;否则返回false(如果发生错误或操作超时)。

[virtual] bool QSerialPort::waitForReadyRead(int msecs = 30000)
重新实现从QIODevice: waitForReadyRead()。
这个函数会阻塞,直到有新的数据可供读取并且发出readyRead()信号。函数将在msecs毫秒后超时;缺省超时时间为30000毫秒。如果msecs为-1,则此函数不会超时。
如果发出readyRead()信号并且有可供读取的新数据,则函数返回true;否则返回false(如果发生错误或操作超时)。
参见waitForBytesWritten()。

[virtual protected] qint64 QSerialPort::writeData(const char *data, qint64 maxSize)
重新实现从QIODevice: writeData()。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Allen Roson

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值