串行终端
展示如何使用 QSerialPort 的各种功能。
终端 展示如何通过 Qt 串行端口 创建一个简单的串行界面的终端。
此示例展示了 QSerialPort 类的主要功能,例如配置、I/O 实现,等等。同时,调用 QSerialPortInfo 类来显示系统中可用的串行端口的详细信息。
QSerialPort 支持两种通用的编程方法
- 异步(非阻塞)方法。 在控制权返回到 Qt 的事件循环时安排和执行操作。当操作完成时,QSerialPort 发出信号。例如,QSerialPort::write() 立即返回。当数据发送到串行端口时,QSerialPort 发出 bytesWritten()。
- 同步(阻塞)方法。 在非 GUI 和多线程应用程序中,可以调用 (i.e. QSerialPort::waitForReadyRead()) 以挂起调用线程,直到操作完成。
在此示例中,演示了异步方法。Blocking Receiver 示例说明了同步方法。
我们的示例包含一些 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); }
此槽从串行端口读取数据并将其显示在控制台小部件中。
运行示例
要从Qt Creator运行示例,请打开欢迎模式,并从示例中选择示例。更多信息,请访问构建和运行示例。
另请参阅阻塞接收器。
© 2024 The Qt Company Ltd. 本文档中的贡献版权属于各自的拥有者。提供的文档受GNU自由文档许可证版本1.3的条款约束,由自由软件基金会发布。Qt及其相应的标志是The Qt Company Ltd在芬兰和其他国家的商标。所有其他商标均为其各自所有者的财产。