显示如何使用QSerialPort的各种功能。
终端展示了如何使用Qt串行端口为简单串行接口创建终端。
此示例显示了QSerialPort类的主要功能,如配置、I/O实现等。此外,调用类QSerialPortInfo以显示有关系统中可用串行端口的信息。
QSerialPort支持两种通用编程方法:
异步(非阻塞)方法:当控制返回到Qt的事件循环时,安排并执行操作。QSerialPort在操作完成时发出信号。例如,QSerialPort::write()会立即返回。当数据发送到串行端口时,QSerialPort会发出bytesWritten()。
同步(阻塞)方法:在非GUI和多线程应用程序中,可以调用waitForReadyRead()以挂起调用线程,直到操作完成。
在这个示例中,演示了异步方法。阻塞接收器示例说明了同步方法。
我们的示例包含一些GUI小部件:
MainWindow(terminal/MainWindow.cpp)-是主应用程序窗口,它包含串行端口编程的所有工作逻辑,包括配置、I/O处理等,同时继承QMainWindow。
控制台(terminal/Console.cpp)-是主窗口的中心小部件,显示传输或接收的数据。该小部件派生自QPlainTextEdit类。
设置对话框(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);
...
}
单击“Connect”按钮可调用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"));
}
}
在此插槽中,将从设置对话框中读取设置,并尝试相应地打开和初始化串行端口。如果成功,状态栏将显示一条消息,说明在给定配置下打开成功;否则,将显示一个消息框,其中包含相应的错误代码和消息。如果从未调用过串行端口设置,则终端尝试使用默认设置打开端口:9600 8N1。
单击Disconnect按钮可调用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"));
}
在这种情况下,通过关闭串行端口来处理。
单击Configure按钮将调用属于SettingsDialog小部件的show()插槽。
此方法(terminal/settingsdialog.cpp)显示设置对话框,用户可以在其中选择所需的串行端口,查看有关所选端口的信息,并设置给定串行端口的所需参数。
写数据
在控制台中键入字符会调用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);
}
此插槽从串行端口读取数据,并将其显示在Console小部件中。