本页内容

串行终端

介绍如何使用QSerialPort 的各项功能。

“终端”部分介绍了如何使用 Qt Serial Port。

Qt Serial Port 终端

本示例展示了QSerialPort 类的主要功能,例如配置、I/O实现等。此外,还调用了QSerialPortInfo 类来显示系统中可用串行端口的相关信息。

QSerialPort 支持两种通用的编程方法:

  • 异步(非阻塞)方法。操作会被排入队列,并在控制权返回 Qt 事件循环时执行。QSerialPort 会在操作完成时发出信号。例如,QSerialPort::write() 会立即返回。当数据发送至 Qt Serial Port 时,QSerialPort 会发出bytesWritten() 信号。
  • 同步(阻塞)方法。在非GUI和多线程应用程序中,可以调用waitFor...() 函数(即QSerialPort::waitForReadyRead()),以使调用线程暂停,直到操作完成。

本示例演示了异步方法。阻塞接收器示例则演示了同步方法。

本示例包含一些GUI控件:

  • MainWindow (terminal/mainwindow.cpp)——这是主应用程序窗口,包含串口编程的所有工作逻辑(包括配置、I/O 处理等),同时继承自 QMainWindow。
  • Console (terminal/console.cpp) —— 是主窗口的核心控件,用于显示已发送或接收的数据。该控件继承自 QPlainTextEdit 类。
  • SettingsDialog (terminal/settingsdialog.cpp) — 这是一个用于配置串口、以及显示可用串口及其相关信息的对话框。

串行端口在MainWindow 的构造函数中实例化。主控件作为父控件被传递进去,因此对象的销毁将根据Qt中的父子机制自动进行:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    m_ui(new Ui::MainWindow),
    m_serial(new QSerialPort(this))
{
    ...

本示例演示了以下QSerialPort 信号:

  • readyRead() - 表示已接收新数据且数据已可用
  • bytesWritten() - 用于检查所有数据是否已成功写入
    ...
    connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData);
    connect(m_serial, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten);
    ...
}

点击“连接”按钮将调用openSerialPort() 的槽:

void MainWindow::openSerialPort()
{
    const SettingsDialog::Settings p = m_settings->settings();
    m_serial->setPortName(p.name);
    m_serial->setBaudRate(p.baudRate);
    m_serial->setDataBits(p.dataBits);
    m_serial->setParity(p.parity);
    m_serial->setStopBits(p.stopBits);
    m_serial->setFlowControl(p.flowControl);
    if (m_serial->open(QIODevice::ReadWrite)) {
        m_console->setEnabled(true);
        m_console->setLocalEchoEnabled(p.localEchoEnabled);
        m_ui->actionConnect->setEnabled(false);
        m_ui->actionDisconnect->setEnabled(true);
        m_ui->actionConfigure->setEnabled(false);
        showStatusMessage(tr("Connected to %1 : %2, %3, %4, %5, %6")
                          .arg(p.name, p.stringBaudRate, p.stringDataBits,
                               p.stringParity, p.stringStopBits, p.stringFlowControl));
    } else {
        QMessageBox::critical(this, tr("Error"), m_serial->errorString());

        showStatusMessage(tr("Open error"));
    }
}

在此槽中,程序会从SettingsDialog 读取设置,并尝试据此打开和初始化串行端口。若成功,状态栏将显示一条消息,表明已使用给定配置成功打开端口;否则,将显示一个包含相应错误代码和消息的消息框。 如果从未调用过串口设置,则终端将尝试使用默认设置(9600 8N1)打开该端口:

点击“断开连接”按钮将调用closeSerialPort() 槽:

void MainWindow::closeSerialPort()
{
    if (m_serial->isOpen())
        m_serial->close();
    m_console->setEnabled(false);
    m_ui->actionConnect->setEnabled(true);
    m_ui->actionDisconnect->setEnabled(false);
    m_ui->actionConfigure->setEnabled(true);
    showStatusMessage(tr("Disconnected"));
}

在此情况下,由关闭串口来处理。

点击“配置”按钮将调用属于“SettingsDialog ”控件的show() 槽:

该方法(terminal/settingsdialog.cpp )会显示“SettingsDialog ”对话框,用户可在其中选择所需的串行端口、查看所选端口的信息,并设置该串行端口的所需参数。

写入数据

在控制台中输入字符会触发writeData() 槽:

void MainWindow::writeData(const QByteArray &data)
{
    const qint64 written = m_serial->write(data);
    if (written == data.size()) {
        m_bytesToWrite += written;
        m_timer->start(kWriteTimeout);
    } else {
        const QString error = tr("Failed to write all data to port %1.\n"
                                 "Error: %2").arg(m_serial->portName(),
                                                  m_serial->errorString());
        showWriteError(error);
    }
}

该槽会将指定控制台控件中输入的字符发送至串口——详见terminal/console.cpp 。它还会启动一个计时器,用于跟踪写入操作是否真正成功。我们使用bytesWritten() 信号来确保所有字节均已实际写入。该信号连接至MainWindow::handleBytesWritten() 槽:

void MainWindow::handleBytesWritten(qint64 bytes)
{
    m_bytesToWrite -= bytes;
    if (m_bytesToWrite == 0)
        m_timer->stop();
}
读取数据

当串口接收到新数据时,会发出readyRead() 信号,该信号连接到MainWindow::readData() 槽:

void MainWindow::readData()
{
    const QByteArray data = m_serial->readAll();
    m_console->putData(data);
}

该插槽从串口读取数据,并在“控制台”控件中显示该数据。

运行示例

您可以通过以下方式运行示例:

示例项目 @ code.qt.io

另请参阅 阻塞式接收器。

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.