Qt入门——串口编程(Qt帮助手册)

本文主要内容来自Qt官方帮助手册

目录


Qt下串口介绍

Qt串口提供基本功能,包括配置、I/O操作、获取和设置RS-232引脚的控制信号。

此模块不支持以下项:

  • 终端特性,如数据回传、控制CR/LF(Carriage Returun,“回车” 和 Line Feed,“换行”)等。
  • 文本模式。
  • 在读取或写入时设置超时和延迟。
  • 引脚输出信号变换的通知。

要在应用程序中使用串行端口,添加以下include语句:

#include <QSerialPort>

要获取可用串口的信息,可以使用下面的include语句:

#include <QSerialPortInfo>

要将串口模块加入到Qt工程,需要在你的工程文件 qmake.pro 中添加以下内容

QT += serialport


串口C++类

QSerialPort类

提供访问串行端口的函数。

串口操作步骤:

  1. 使用QSerilPortInfo类的函数获取所有可用的串口。
  2. 使用open函数打开串口设备。
  3. 成功打开设备后,可以对串口进行配置,如波特率、停止位等。
  4. 如果是RS-232,还可以设置和获取一些线路信号(DTR和RTS)。
  5. 串口通信时使用read()或write()等函数。

注意
串口总是以独占访问方式打开的(也就是说,没有其他进程或线程可以访问已经打开的串口)。

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,串口断开(close)或者出现了错误(error错误码)。
阻塞式的串口编程和非阻塞式的有很大区别。阻塞式串口不需要使用事件循环,只需要简单的代码。但是,如果应用是带图形界面的,阻塞式串口最好是用在没有图形操作的线程中,这样可以避免界面被冻结。

QSerialPort成员

注意
这个类中的所有函数都是可重入的(线程安全)。

公有成员
BaudRate
enum QSerialPort::BaudRate

此枚举描述串口通信的波特率。
:此枚举只列出了最常用的标准波特率。

Qt源码:

enum BaudRate {
        Baud1200 = 1200,
        Baud2400 = 2400,
        Baud4800 = 4800,
        Baud9600 = 9600,
        Baud19200 = 19200,
        Baud38400 = 38400,
        Baud57600 = 57600,
        Baud115200 = 115200,
        UnknownBaud = -1
    };

DataBits
enum QSerialPort::DataBits

该枚举描述串口通信的数据位。

Qt源码:

enum DataBits {
        Data5 = 5,
        Data6 = 6,
        Data7 = 7,
        Data8 = 8,   //常用
        UnknownDataBits = -1
    };

Direction
enum QSerialPort::Direction

该枚举描述数据传输的方向。
:当此枚举用于在某些操作系统(例如POSIX-like)上时,要为每个方向分别设置波特率。
Qt源码:

enum Direction  {
        Input = 1,
        Output = 2,
        AllDirections = Input | Output
    };
    Q_FLAG(Direction)
    Q_DECLARE_FLAGS(Directions, Direction)

Directions
flags QSerialPort::Directions

Directions是QFlags的类型重定义(typedef)。它存储一个或多个方向值的组合。(QFlags在Qt中用于存储枚举值的组合)

FlowControl
enum QSerialPort::FlowControl

该枚举描述流控制。
Qt源码:

enum FlowControl {
        NoFlowControl,
        HardwareControl, //硬流控制(RTS/CTS)
        SoftwareControl, //软流控制(XON/XOFF)
        UnknownFlowControl = -1
    };
    Q_ENUM(FlowControl)

Parity
enum QSerialPort::Parity

该枚举描述奇偶校验。

Qt源码:

enum Parity {
        NoParity = 0,  //无校验,最常用
        EvenParity = 2, //偶校验
        OddParity = 3,  //奇校验
        SpaceParity = 4, 
        MarkParity = 5,
        UnknownParity = -1
    };
    Q_ENUM(Parity)

PinoutSignal
enum QSerialPort::PinoutSignal

该枚举描述RS-232输出脚信号

Qt源码:

enum PinoutSignal {
        NoSignal = 0x00,
        TransmittedDataSignal = 0x01, //TxD
        ReceivedDataSignal = 0x02, //RxD
        DataTerminalReadySignal = 0x04, //DTR
        DataCarrierDetectSignal = 0x08, //DCD
        DataSetReadySignal = 0x10,  //DSR
        RingIndicatorSignal = 0x20, //RNG
        RequestToSendSignal = 0x40, //RTS
        ClearToSendSignal = 0x80, //CTS
        SecondaryTransmittedDataSignal = 0x100, //STD
        SecondaryReceivedDataSignal = 0x200 //SRD
    };
    Q_FLAG(PinoutSignal)
    Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal)

PinoutSignals
flags QSerialPort::PinoutSignals

SerialPortError
enum QSerialPort::SerialPortError

该枚举描述出错类型 (类型由QSerialPort::error决定)。

Qt源码:

 enum SerialPortError {
        NoError,
        DeviceNotFoundError, //设备不存在
        PermissionError, //无权限
        OpenError, //打开失败(已经被别的程序打开)
        ParityError, //校验错误
        FramingError, //帧错误
        BreakConditionError, //
        WriteError, //写入失败
        ReadError, //读取失败
        ResourceError, //资源访问出错,例如设备被移除
        UnsupportedOperationError, //不支持的操作
        UnknownError, //未知错误
        TimeoutError, //超时
        NotOpenError  //设备没打开,但试图进行操作
    };
    Q_ENUM(SerialPortError)

StopBits
enum QSerialPort::StopBits

该枚举描述停止位 。

Qt源码:

 enum StopBits {
        OneStop = 1,
        OneAndHalfStop = 3, //1.5停止位,Windows独有
        TwoStop = 2,
        UnknownStopBits = -1
    };
    Q_ENUM(StopBits)

参数属性
baudRate : qint32

该属性为数据的波特率。
:如果该属性在打开串口设备之前设置的,要想设置生效,必须调用QSerialPort::open()函数。
注意:所有平台都支持设置ALLDirections标志,Windows仅支持这一种模式,即Windows平台任何方向的波特率相等。
波特率默认值为Baud9600,即每秒9600位。

breakEnabled : bool

该属性表示传输线路是否处于断开状态。
注:在设置和获取这个属性前,必须将串口打开。
该属性在Qt 5.5版本中被引进。

dataBits : DataBits

该属性为每帧的数据位。
:和波特率一样,可以在open之前设置,但必须等open才会生效。
默认值为Data8,即数据位为8。

dataTerminalReady : bool

该属性为线路信号DTR的状态。
:该状态必须在设备打开后才能设置或获取。

error : SerialPortError

该属性为串口的错误状态。
默认:QSerialPort::NoError。

flowControl : FlowControl

该属性为流控制的模式。
:如果open前设置,则open才能生效。
默认值为NoFlowControl。

parity : Parity

该属性为奇偶校验模式。
:如果open前设置,需要open后才能生效。
默认值为NoParity,即无校验。

requestToSend : bool

该属性为线路信号RTS的状态。
:该属性必须在设备打开后才能设置或读取。
:如果RTS处于HardwareControl模式时去控制RTS,将会失败同时设置错误码UnsupportedOperationError。

stopBits : StopBits

该属性为每帧数据的停止位。
:设备打开前设置该属性的话,需要调用open才能生效。
默认值为OneStop,即1停止位。

objectName : QString (继承自QObject)

公有函数
QSerialPort

该函数名有三种不同的重载:

1.
QSerialPort::QSerialPort(QObject *parent = nullptr)

构造一个串口对象,参数为父类的指针对象(代表串口端口)。

2.
QSerialPort::QSerialPort(const QString &name, QObject *parent = nullptr)

构造一个指定名称的串口对象,名称有特定的格式(格式参考SetPort()函数)。

3.
QSerialPort::QSerialPort(const QSerialPortInfo &serialPortInfo, QObject *parent = nullptr)

根据给定的辅助类(QSerialPortInfo)构建一个串口对象。

~QSerialPort

构析函数,关闭串口,必要时摧毁对象。

baudRate

获取波特率。
Qt源码

qint32 QSerialPort::baudRate(Directions directions) const
{
    Q_D(const QSerialPort);
    if (directions == QSerialPort::AllDirections)
        return d->inputBaudRate == d->outputBaudRate ?
                    d->inputBaudRate : -1;
    return directions & QSerialPort::Input ? d->inputBaudRate : d->outputBaudRate;
}

clear
bool QSerialPort::clear(QSerialPort::Directions directions = AllDirections)

根据给定的方向,丢弃输入或输出的所有字符.包括清除所有内部类的缓存和UART(驱动程序)的缓存区,同时将挂起的读写操作终止。如果成功,返回true,否则返回false。
:在clear之前,串口设备必须打开,否则将返回false,同时设置NotOpenError错误码。
Qt源码:

bool QSerialPort::clear(Directions directions)
{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return false;
    }

    if (directions & Input)
        d->buffer.clear();
    if (directions & Output)
        d->writeBuffer.clear();
    return d->clear(directions);
}

clearError

将错误标志恢复默认(NoError)
Qt源码:

void QSerialPort::clearError()
{
    Q_D(QSerialPort);
    d->setError(QSerialPortErrorInfo(QSerialPort::NoError));
}

dataBits

获取数据位。
Qt源码:

QSerialPort::DataBits QSerialPort::dataBits() const
{
    Q_D(const QSerialPort);
    return d->dataBits;
}

error

获取错误状态。
Qt源码:

QSerialPort::SerialPortError QSerialPort::error() const
{
    Q_D(const QSerialPort);
    return d->error;
}

flowContrl

获取流控制模式。
Qt源码:

QSerialPort::FlowControl QSerialPort::flowControl() const
{
    Q_D(const QSerialPort);
    return d->flowControl;
}

flush
bool QSerialPort::flush()

此函数在不阻塞的情况下尽可能多地从内部写入缓冲区写入底层串行端口。如果写入了数据,此函数返回true;否则返回false。
调用此函数将缓冲数据立即发送到串行端口。成功写入的字节数取决于操作系统。在大多数情况下,不需要调用此函数,因为一旦控件返回到事件循环,QSerialPort类将自动开始发送数据。如果没有事件循环,则改为调用waitForBytesWritten()。
:在调用函数之前,串口设备必须打开。
Qt源码:

bool QSerialPort::flush()
{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return false;
    }

    return d->flush();
}

handle
QSerialPort::Handle QSerialPort::handle() const

如果平台支持串口且串口已打开,返回串口的handle,否则返回-1.
注意:
这个函数是在qt5.2中引入的。此功能仅供专家使用;使用风险自负。此外,此函数在次要的Qt版本没有兼容性承诺。

isBreakEnabled

获取BreakEnable的状态。
Qt源码:

bool QSerialPort::isBreakEnabled() const
{
    Q_D(const QSerialPort);
    return d->isBreakEnabled;
}

isDataTerminalReady

获取DTR的状态。
Qt源码:

bool QSerialPort::isDataTerminalReady()
{
    Q_D(QSerialPort);
    return d->pinoutSignals() & QSerialPort::DataTerminalReadySignal;
}

isRequestToSend

获取RTS的状态。
Qt源码:

bool QSerialPort::isRequestToSend()
{
    Q_D(QSerialPort);
    return d->pinoutSignals() & QSerialPort::RequestToSendSignal;
}

parity

获取奇偶校验方式。
Qt源码

QSerialPort::Parity QSerialPort::parity() const
{
    Q_D(const QSerialPort);
    return d->parity;
}

pinoutSignals
QSerialPort::PinoutSignals QSerialPort::pinoutSignals()

以位图格式返回线路信号的状态。
根据该结果,可以用掩码“AND”来分配所需信号的状态,其中掩码是QSerialPort::PinoutSignals的枚举值。
注意:该函数会执行系统调用,从而确保正确返回线路信号的状态。当底层操作系统不能在串口引脚状态发生变化时进行通知时,这个函数是很必要的。
:在调用函数之前,串口设备必须打开。
Qt源码:

QSerialPort::PinoutSignals QSerialPort::pinoutSignals()
{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return QSerialPort::NoSignal;
    }

    return d->pinoutSignals();
}

portName
QString QSerialPort::portName() const

返回setPort()或QSerialPort构造函数设定的名字,这个名字很短,即从设备的内部的变量系统位置中提取和转换,转换算法由系统平台决定。

平台描述
Windows从系统位置删除前缀“\.\”或“//”,并返回字符串的其余部分。
Unix, BSD从系统位置删除前缀“/dev/”,并返回字符串的其余部分。

Qt源码:

QString QSerialPort::portName() const
{
    Q_D(const QSerialPort);
    return QSerialPortInfoPrivate::portNameFromSystemLocation(d->systemLocation);
}

readBufferSize
qint64 QSerialPort::readBufferSize() const

返回内部读取缓存区的大小,该大小限制了客户端在调用read()或readAll()函数前可以接收的数据量。
读取缓存区大小为0(默认值)代表着缓存区没有大小限制,可以确保数据不丢失。
Qt源码:

qint64 QSerialPort::readBufferSize() const
{
    Q_D(const QSerialPort);
    return d->readBufferMaxSize;
}

sendBreak
bool QSerialPort::sendBreak(int duration = 0)

如果终端使用异步串行数据,则在指定时间内以毫秒为单位发送连续的零位流(stream of zero bits)。
如果持续时间为0,则零位的传输时间至少为0.25秒,但不超过0.5秒。
如果持续时间不为0,则在指定时间段内传输零位。
:在使用该函数前,必须将串口打开,否则返回false并设置NotOpenError错误码。
Qt源码:

{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return false;
    }

    return d->sendBreak(duration);
}

setBaudRate

设置波特率。
Qt源码:

bool QSerialPort::setBaudRate(qint32 baudRate, Directions directions)
{
    Q_D(QSerialPort);

    if (!isOpen() || d->setBaudRate(baudRate, directions)) {
        if (directions & QSerialPort::Input) {
            if (d->inputBaudRate != baudRate)
                d->inputBaudRate = baudRate;
            else
                directions &= ~QSerialPort::Input;
        }

        if (directions & QSerialPort::Output) {
            if (d->outputBaudRate != baudRate)
                d->outputBaudRate = baudRate;
            else
                directions &= ~QSerialPort::Output;
        }

        if (directions)
            emit baudRateChanged(baudRate, directions);

        return true;
    }

    return false;
}

setBreakEnabled

设置断开使能(???)。
Qt源码:

bool QSerialPort::sendBreak(int duration)
{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return false;
    }

    return d->sendBreak(duration);
}

setDataBits

设置每帧的数据位。
Qt源码:

bool QSerialPort::setDataBits(DataBits dataBits)
{
    Q_D(QSerialPort);

    if (!isOpen() || d->setDataBits(dataBits)) {
        if (d->dataBits != dataBits) {
            d->dataBits = dataBits;
            emit dataBitsChanged(d->dataBits);
        }
        return true;
    }

    return false;
}

setDataTerminalReady

设置STR。
Qt源码:

bool QSerialPort::setDataTerminalReady(bool set)
{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return false;
    }

    const bool dataTerminalReady = isDataTerminalReady();
    const bool retval = d->setDataTerminalReady(set);
    if (retval && (dataTerminalReady != set))
        emit dataTerminalReadyChanged(set);

    return retval;
}

setFlowControl

设置流控制模式。
Qt源码:

bool QSerialPort::setFlowControl(FlowControl flowControl)
{
    Q_D(QSerialPort);

    if (!isOpen() || d->setFlowControl(flowControl)) {
        if (d->flowControl != flowControl) {
            d->flowControl = flowControl;
            emit flowControlChanged(d->flowControl);
        }
        return true;
    }

    return false;
}

setParity

设置奇偶检验方式。
Qt源码:

bool QSerialPort::setParity(Parity parity)
{
    Q_D(QSerialPort);

    if (!isOpen() || d->setParity(parity)) {
        if (d->parity != parity) {
            d->parity = parity;
            emit parityChanged(d->parity);
        }
        return true;
    }

    return false;
}

setPort
void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)

设置串口,串口信息存放在SerialPortInfo的对象里。
Qt源码:

void QSerialPort::setPort(const QSerialPortInfo &serialPortInfo)
{
    Q_D(QSerialPort);
    d->systemLocation = serialPortInfo.systemLocation();
}

setPortName
void QSerialPort::setPortName(const QString &name)

设置串口的名字,可以是一个短的名字,如果有必要,也可以是一个系统位置。
Qt源码:

void QSerialPort::setPortName(const QString &name)
{
    Q_D(QSerialPort);
    d->systemLocation = QSerialPortInfoPrivate::portNameToSystemLocation(name);
}

setReadBufferSize
void QSerialPort::setReadBufferSize(qint64 size)

设置内部读取缓存区大小,单位为字节。
如果应用会在短时间接收很多数据,最后不要对缓存区进行设置(默认为0,即无限制大小),以免程序出现异常,如run out of memeory。
Qt源码:

void QSerialPort::setReadBufferSize(qint64 size)
{
    Q_D(QSerialPort);
    d->readBufferMaxSize = size;
    if (isReadable())
        d->startAsyncRead();
}

setRequestToSend

设置RTS的状态。
Qt源码:

bool QSerialPort::setRequestToSend(bool set)
{
    Q_D(QSerialPort);

    if (!isOpen()) {
        d->setError(QSerialPortErrorInfo(QSerialPort::NotOpenError));
        qWarning("%s: device not open", Q_FUNC_INFO);
        return false;
    }

    if (d->flowControl == QSerialPort::HardwareControl) {
        d->setError(QSerialPortErrorInfo(QSerialPort::UnsupportedOperationError));
        return false;
    }

    const bool requestToSend = isRequestToSend();
    const bool retval = d->setRequestToSend(set);
    if (retval && (requestToSend != set))
        emit requestToSendChanged(set);

    return retval;
}

setStopBits

设置每帧的停止位。
Qt源码:

bool QSerialPort::setStopBits(StopBits stopBits)
{
    Q_D(QSerialPort);

    if (!isOpen() || d->setStopBits(stopBits)) {
        if (d->stopBits != stopBits) {
            d->stopBits = stopBits;
            emit stopBitsChanged(d->stopBits);
        }
        return true;
    }

    return false;
}

stopBits

获取停止位。
Qt源码:

QSerialPort::StopBits QSerialPort::stopBits() const
{
    Q_D(const QSerialPort);
    return d->stopBits;
}

重载公有函数
atEnd
[override virtual] bool QSerialPort::atEnd() const

重载自QIODevice::adEnd()。
当不再有数据读取时,返回true,否则返回false。
该函数大多数情况下在循环读取数据时使用,例如:(Qt帮助手册例子)

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

Qt源码:

bool QSerialPort::atEnd() const
{
    return QIODevice::atEnd();
}

QIODevice怎么实现的我先不研究了 ·‘ ~ ’· 。

bytesAvailable
[override virtual] qint64 QSerialPort::bytesAvailable() const

重载自QIODevice::bytesAvailable()。
返回传入的字节数并等待被读取。

bytesToWrite

重载自QIODevice::bytesToWrite()。
Qt源码:

qint64 QSerialPort::bytesToWrite() const
{
    qint64 pendingBytes = QIODevice::bytesToWrite();
#if defined(Q_OS_WIN32)
    pendingBytes += d_func()->writeChunkBuffer.size();
#endif
    return pendingBytes;
}

canReadLine
[override virtual] bool QSerialPort::canReadLine() const

重载自QIODevice::canReadLine()。
如果一行数据能被串口读取,则返回true,否则返回flase。

close
[override virtual] void QSerialPort::close()const

重载自QIODevice::close()。
关闭串口设备。
:操作前,必须先打开串口设备。

isSequential
[override virtual] bool QSerialPort::isSequential() const

重载自QIODevice::isSequential()。
总是返回true,串口是顺序设备。

open
[override virtual] bool QSerialPort::open(QIODevice::OpenMode mode)

重载自QIODevice::open()。
使用mode的模式打开串口,成功返回true,失败返回false,同时设定一个失败码(打开失败),该失败码可以被error()调用。
:如果该函数打开串口成功但不能成功设置任何串口属性,将返回false,在这种情况下,串口将放弃修改属性并自动关闭。
注意:mode只能是QIODevice::ReadOnly、QIODevice::ReadOnly或QIODevice::ReadWrite,其他模式不支持。

waitForBytesWritten
[override virtual] bool QSerialPort::waitForBytesWritten(int msecs = 30000)

重载自QIODevice::waitForBytesWritten()。
此函数进行阻塞,直到有数据被写入串口,并发出byteWrite()信号。函数在几毫秒后超时,默认超时时间为30000毫秒。如果msecs为-1,则不会进行阻塞。
函数发出byteWrite()信号则返回true,否则返回false。
源码

bool QSerialPort::waitForBytesWritten(int msecs)
{
    Q_D(QSerialPort);
    return d->waitForBytesWritten(msecs);
}

waitForReadyRead
[override virtual] bool QSerialPort::waitForReadyRead(int msecs = 30000)

重载自QIODevice::waitForReadyRead()。
此函数进行阻塞,直到有数据被串口读取,并发出readyRead()信号。函数在几毫秒后超时,默认超时时间为30000毫秒。如果msecs为-1,则不会进行阻塞。
函数发出readyRead()信号则返回true,否则返回false。
源码

bool QSerialPort::waitForReadyRead(int msecs)
{
    Q_D(QSerialPort);
    return d->waitForReadyRead(msecs);
}

44个继承自QIODevice
31个继承自QObject
信号
baudRateChanged
[signal] void QSerialPort::baudRateChanged(qint32 baudRate, QSerialPort::Directions directions)

该信号在波特率被修改后发射。baudRate作为将新的波特率,同时 directions 作为传输方向。

breakEnabledChanged

breakEnabled 状态变化时进行发射。

dataBitsChanged
[signal] void QSerialPort::dataBitsChanged(QSerialPort::DataBits dataBits)

该信号在每帧的数据位修改后发射。新的数据位将变成dataBits。

dataTerminalReadyChanged
[signal] void QSerialPort::dataTerminalReadyChanged(bool set)

该信号在线路信号DTR的状态(高或低)改变后发射。新的状态变为set。

errorOccurred
[signal] void QSerialPort::errorOccurred(QSerialPort::SerialPortError error)

该信号在错误发生时发射,错误值为error。

flowControlChanged
[signal] void QSerialPort::flowControlChanged(QSerialPort::FlowControl flow)

该信号在流控制模式被修改后发射。flow作为将新的流控制模式。

parityChanged
[signal] void QSerialPort::parityChanged(QSerialPort::Parity parity)

该信号在奇偶校验方式被修改后发射。parity作为将新的奇偶校验设置。

requestToSendChanged
[signal] void QSerialPort::requestToSendChanged(bool set)

该信号在线路信号RTS的状态(高或低)改变后发射。新的状态变为set。

stopBitsChanged
[signal] void QSerialPort::stopBitsChanged(QSerialPort::StopBits stopBits)

该信号在每帧的停止位修改后发射。新的停止位将变成stopBits。

6个继承自QIODevice
2个继承自QObject
静态公有函数
staticMetaObject
9个继承自QObject
重载保护函数
readData
[override virtual protected] qint64 QSerialPort::readData(char *data, qint64 maxSize)

重载自QIODevice::readData()。
该函数可能并不会被用到,因为Qt使用QIODevice对象的私有缓存区进行串口操作。
Qt源码:

qint64 QSerialPort::readData(char *data, qint64 maxSize)
{
    Q_UNUSED(data);
    Q_UNUSED(maxSize);

    // In any case we need to start the notifications if they were
    // disabled by the read handler. If enabled, next call does nothing.
    d_func()->startAsyncRead();

    // return 0 indicating there may be more data in the future
    return qint64(0);
}

readLineData
[override virtual protected] qint64 QSerialPort::readLineData(char *data, qint64 maxSize)

重载自QIODevice::readLineData()。

Qt源码:

qint64 QSerialPort::readLineData(char *data, qint64 maxSize)
{
    return QIODevice::readLineData(data, maxSize);
}

writeData
[override virtual protected] qint64 QSerialPort::writeData(const char *data, qint64 maxSize)

重载自QIODevice::writeData()。

Qt源码:

qint64 QSerialPort::writeData(const char *data, qint64 maxSize)
{
    Q_D(QSerialPort);
    return d->writeData(data, maxSize);
}

5个继承自QIODevice
9个继承自QObject
其他继承成员
一个继承自QObject的公有槽
5个继承自QIODevice的保护函数
9个继承自QObject的保护函数

QSerialPortInfo类

提供串行端口的信息。

使用静态函数生成QSerialPortInfo对象的列表。列表中的每个QSerialPortInfo对象表示一个串行端口,可以查询端口名、系统位置、描述和制造商。QSerialPortInfo类还可以用作QSerialPort类的setPort()函数的输入参数。

QSerialPortInfo成员

公有函数
QSerialPortInfo

该构造函数有四种重载:

1.
QSerialPortInfo::QSerialPortInfo()

构建一个空的QSerialPortInfo对象。

2.
QSerialPortInfo::QSerialPortInfo(const QSerialPort &port)

通过QSerialPort类的一个对象来构建QSerialPortInfo的对象。

3.
QSerialPortInfo::QSerialPortInfo(const QString &name)

以串口名来构建一个QSerialPortInfo对象。
此构造函数根据端口名在可用的串口中查找相关的串口,并为该端口构造串口信息实例。

4.
QSerialPortInfo::QSerialPortInfo(const QSerialPortInfo &other)

构建一个QSerialPortInfo 的副本。

~QSerialPortInfo

构析函数。

description
QString QSerialPortInfo::description() const

如果串口可用,则返回串口信息的描述,否则返回一个空字符串。
通过QSerialPort类的一个对象来构建QSerialPortInfo的对象。
Qt源码:

QString QSerialPortInfo::description() const
{
    Q_D(const QSerialPortInfo);
    return !d ? QString() : d->description;
}

hasProductldentifier
bool QSerialPortInfo::hasProductIdentifier() const

如果存在一个有效的16位产品编号,则返回true,否则返回false。
Qt源码:

bool QSerialPortInfo::hasProductIdentifier() const
{
    Q_D(const QSerialPortInfo);
    return !d ? false : d->hasProductIdentifier;
}

hasVendorldentifier
bool QSerialPortInfo::hasVendorIdentifier() const

如果存在一个有效的16位供应商编号,则返回true,否则返回false。
Qt源码:

bool QSerialPortInfo::hasVendorIdentifier() const
{
    Q_D(const QSerialPortInfo);
    return !d ? false : d->hasVendorIdentifier;
}

isBusy
bool QSerialPortInfo::isBusy() constconst

如果串口很忙,则返回true,否则返回false。
Qt源码:

bool QSerialPortInfo::isBusy() const
{
    QString lockFilePath = serialPortLockFilePath(portName());
    if (lockFilePath.isEmpty())
        return false;

    QFile reader(lockFilePath);
    if (!reader.open(QIODevice::ReadOnly))
        return false;

    QByteArray pidLine = reader.readLine();
    pidLine.chop(1);
    if (pidLine.isEmpty())
        return false;

    qint64 pid = pidLine.toLongLong();

    if (pid && (::kill(pid, 0) == -1) && (errno == ESRCH))
        return false; // PID doesn't exist anymore

    return true;
}

isNull
bool QSerialPortInfo::isNull() const

判断该QSerialPortInfo对象是否是一个串口定义。
Qt源码:

inline bool QSerialPortInfo::isNull() const
{ return !d_ptr; }

manufacturer
QString QSerialPortInfo::manufacturer() const

如果串口有效,返回串口的制造商,否则返回一个空的字符串。
Qt源码:

QString QSerialPortInfo::manufacturer() const
{
    Q_D(const QSerialPortInfo);
    return !d ? QString() : d->manufacturer;
}

portName
QString QSerialPortInfo::portName() const

返回串口名。
Qt源码:

QString QSerialPortInfo::portName() const
{
    Q_D(const QSerialPortInfo);
    return !d ? QString() : d->portName;
}

productldentifier
quint16 QSerialPortInfo::productIdentifier() const

如果串口有效,则返回16位产品编号否则返回0。
Qt源码:

quint16 QSerialPortInfo::vendorIdentifier() const
{
    Q_D(const QSerialPortInfo);
    return !d ? 0 : d->vendorIdentifier;
}

serialNumber
QString QSerialPortInfo::serialNumber() const

如果串口有效,则返回序列号,否则返回空字符串。
Qt源码:

QString QSerialPortInfo::serialNumber() const
{
    Q_D(const QSerialPortInfo);
    return !d ? QString() : d->serialNumber;
}

swap
void QSerialPortInfo::swap(QSerialPortInfo &other)

和其他QSerialPortInfo对象进行交换,很快却不会出错。
Qt源码:

void QSerialPortInfo::swap(QSerialPortInfo &other)
{
    d_ptr.swap(other.d_ptr);
}

systemLocation
QString QSerialPortInfo::systemLocation() const

返回串口的系统位置(设备路径)。
Qt源码:

QString QSerialPortInfo::systemLocation() const
{
    Q_D(const QSerialPortInfo);
    return !d ? QString() : d->device;
}

vendorldentifier
quint16 QSerialPortInfo::vendorIdentifier() const

如果串口有效,则返回16位供应商编号否则返回0。
Qt源码:

inline bool QSerialPortInfo::isNull() const
{ return !d_ptr; }

operator=
QSerialPortInfo &QSerialPortInfo::operator=(const QSerialPortInfo &other)

QSerialPortInfo对象复制。
Qt源码:

QSerialPortInfo& QSerialPortInfo::operator=(const QSerialPortInfo &other)
{
    QSerialPortInfo(other).swap(*this);
    return *this;
}

静态公有成员
availablePorts

返回系统所有可用串口。

[static] QList<QSerialPortInfo> QSerialPortInfo::availablePorts()

Qt源码:

QList<QSerialPortInfo> QSerialPortInfo::availablePorts()
{
    const QVector<int> mib = mibFromName(QLatin1String("dev"));
    if (mib.isEmpty())
        return QList<QSerialPortInfo>();

    const QList<NodeInfo> nodes = enumerateDesiredNodes(mib);
    if (nodes.isEmpty())
        return QList<QSerialPortInfo>();

    QDir deviceDir(QLatin1String("/dev"));
    if (!(deviceDir.exists() && deviceDir.isReadable()))
        return QList<QSerialPortInfo>();

    deviceDir.setNameFilters(QStringList() << QLatin1String("cua*") << QLatin1String("tty*"));
    deviceDir.setFilter(QDir::Files | QDir::System | QDir::NoSymLinks);

    QList<QSerialPortInfo> cuaCandidates;
    QList<QSerialPortInfo> ttyCandidates;

    const auto portNames = deviceDir.entryList();
    for (const QString &portName : portNames) {
        if (portName.endsWith(QLatin1String(".init"))
                || portName.endsWith(QLatin1String(".lock"))) {
            continue;
        }

        QSerialPortInfoPrivate priv;
        priv.portName = portName;
        priv.device = QSerialPortInfoPrivate::portNameToSystemLocation(portName);

        for (const NodeInfo &node : nodes) {
            const int pnpinfoindex = node.name.indexOf(QLatin1String("\%pnpinfo"));
            if (pnpinfoindex == -1)
                continue;

            if (node.value.isEmpty())
                continue;

            QString ttyname = deviceName(node.value);
            if (ttyname.isEmpty())
                continue;

            const QString ttyportscount = deviceCount(node.value);
            if (ttyportscount.isEmpty())
                continue;

            const int count = ttyportscount.toInt();
            if (count == 0)
                continue;
            if (count > 1) {
                bool matched = false;
                for (int i = 0; i < count; ++i) {
                    const QString ends = QString(QLatin1String("%1.%2")).arg(ttyname).arg(i);
                    if (portName.endsWith(ends)) {
                        matched = true;
                        break;
                    }
                }

                if (!matched)
                    continue;
            } else {
                if (!portName.endsWith(ttyname))
                    continue;
            }

            priv.serialNumber = deviceSerialNumber(node.value);
            priv.vendorIdentifier = deviceVendorIdentifier(node.value, priv.hasVendorIdentifier);
            priv.productIdentifier = deviceProductIdentifier(node.value, priv.hasProductIdentifier);

            const QString nodebase = node.name.mid(0, pnpinfoindex);
            const QString descnode = QString(QLatin1String("%1\%desc")).arg(nodebase);

            // search for description and manufacturer properties
            for (const NodeInfo &node : nodes) {
                if (node.name != descnode)
                    continue;

                if (node.value.isEmpty())
                    continue;

                // We can not separate the description and the manufacturer
                // properties from the node value, so lets just duplicate it.
                priv.description = deviceDescriptionAndManufacturer(node.value);
                priv.manufacturer = priv.description;
                break;
            }

            break;
        }

        if (portName.startsWith(QLatin1String("cua")))
            cuaCandidates.append(priv);
        else if (portName.startsWith(QLatin1String("tty")))
            ttyCandidates.append(priv);
    }

    QList<QSerialPortInfo> serialPortInfoList;

    for (const QSerialPortInfo &cuaCandidate : qAsConst(cuaCandidates)) {
        const QString cuaPortName = cuaCandidate.portName();
        const QString cuaToken = deviceProperty(cuaPortName, "cua");
        for (const QSerialPortInfo &ttyCandidate : qAsConst(ttyCandidates)) {
            const QString ttyPortName = ttyCandidate.portName();
            const QString ttyToken = deviceProperty(ttyPortName, "tty");
            if (cuaToken != ttyToken)
                continue;

            serialPortInfoList.append(cuaCandidate);
            serialPortInfoList.append(ttyCandidate);
        }
    }

    return serialPortInfoList;
}

standardBaudRates
[static] QList<qint32> QSerialPortInfo::standardBaudRates()

返回当前平台支持的串口波特率。
Qt源码:

QList<qint32> QSerialPortInfo::standardBaudRates()
{
    return QSerialPortPrivate::standardBaudRates();
}

简单实例

下面是一个简单的串口程序,不设置串口的波特率、停止位、校验方式、流控制(都是采用默认配置),只是实现了串口发送数据和读取数据的功能。

工程文件

添加

Qt  += serialport
QT       += core gui serialport

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

头文件

添加

#include <QSerialPort>
#include <QSerialPortInfo>

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QString>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;
     QSerialPort serial;
};
#endif // MAINWINDOW_H

cpp文件

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    ui->setupUi(this);

    //获取所有串口并将名字放入comboBox
    const auto infos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : infos)
        ui->comboBox->addItem(info.portName());

}

MainWindow::~MainWindow()
{
    delete ui;
}

//发送按钮槽函数
void MainWindow::on_pushButton_clicked()
{

    if (serial.portName() != ui->comboBox->currentText())
    {
        serial.close();
        serial.setPortName(ui->comboBox->currentText());

         /* 打开串口设备 */
        if (!serial.open(QIODevice::ReadWrite))
        {
            qDebug() << (tr("Can't open %1, error code %2")
                         .arg(serial.portName()).arg(serial.error()));
            return;
        }
    }

    /* 将textEdit内容发给串口 */
    serial.write(ui->textEdit->toPlainText().toLatin1());

    /*
     * 从串口读取数据
     * 最好使用信号QSerialPort::readReady来判断是否可以读取
     * 这里只为测试,所以没有考虑其他外部因素
     */
    ui->textBrowser->append(serial.readAll());



}

ui文件

在这里插入图片描述

运行结果

编译后放到arm开发板上,将串口的Rx和Tx短接,实现自发自收。
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小辉_Super

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

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

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

打赏作者

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

抵扣说明:

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

余额充值