Terminal Example

Terminal shows how to create a terminal for a simple serial interface by using Qt Serial Port.

Image non disponible

This example shows the main features of the QSerialPort class, like configuration, I/O implementation and so forth. Also, the class QSerialPortInfo is invoked to display information about the serial ports available in the system.

QSerialPort supports two general programming approaches:

  • The asynchronous (non-blocking) approach. Operations are scheduled and performed when the control returns to Qt's event loop. QSerialPort emits a signal when the operation is finished. For example, QSerialPort::write() returns immediately. When the data is sent to the serial port, QSerialPort emits bytesWritten().

  • The synchronous (blocking) approach. In non-GUI and multithreaded applications, the waitFor...() functions can be called (i.e. QSerialPort::waitForReadyRead()) to suspend the calling thread until the operation has completed.

In this example, the asynchronous approach is demonstrated. The Blocking Slave example illustrates the synchronous approach.

Our example contains some GUI widgets:

  • MainWindow - is the main application window that contains all the working logic for the serial port programming, including configuration, I/O processing and so forth, while inheriting the QMainWindow.

  • Console - is the central widget of the main window, displaying the transmitted or received data. The widget is derived from the QPlainTextEdit class.

  • SettingsDialog - is a dialog for configuring the serial port, as well as for displaying the available serial ports and information about them.

The serial port is instantiated in the MainWindow constructor. The main widget is passed as the parent, so the object deletion happens automatically according to the parent and child mechanism in Qt:

 
Sélectionnez
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    m_ui(new Ui::MainWindow),
    m_status(new QLabel),
    m_console(new Console),
    m_settings(new SettingsDialog),
    m_serial(new QSerialPort(this))
{
    ...
    m_serial(new QSerialPort(this))

The only QSerialPort signal invoked in this example is readyRead(), which shows that new data has been received and hence available:

 
Sélectionnez
    ...
    connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData);
    ...
}

Clicking on the Connect button invokes the openSerialPort() slot:

 
Sélectionnez
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).arg(p.stringBaudRate).arg(p.stringDataBits)
                          .arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl));
    } else {
        QMessageBox::critical(this, tr("Error"), m_serial->errorString());

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

In this slot, the settings are read from SettingsDialog and an attempt is made to open and initialize the serial port acco