Auf dieser Seite

Serielle Schnittstelle

Zeigt, wie man verschiedene Funktionen von „ QSerialPort “ nutzt.

„Terminal“ zeigt, wie man mithilfe von Qt Serial Port.

Qt Serial Port für serielle Schnittstellen

Dieses Beispiel veranschaulicht die wichtigsten Funktionen der Klasse „ QSerialPort “, wie z. B. die Konfiguration, die E/A-Implementierung und so weiter. Außerdem wird die Klasse „ QSerialPortInfo “ aufgerufen, um Informationen zu den im System verfügbaren seriellen Schnittstellen anzuzeigen.

QSerialPort unterstützt zwei allgemeine Programmieransätze:

  • Den asynchronen (nicht blockierenden) Ansatz. Operationen werden eingeplant und ausgeführt, sobald die Kontrolle an die Ereignisschleife von Qt zurückgegeben wird. ` QSerialPort ` sendet ein Signal aus, wenn die Operation abgeschlossen ist. Beispielsweise kehrt ` QSerialPort::write()` sofort zurück. Wenn die Daten an den seriellen Port gesendet werden, sendet ` QSerialPort ` das Signal ` bytesWritten()` aus.
  • Der synchrone (blockierende) Ansatz. In Nicht-GUI- und Multithread-Anwendungen können die „ waitFor...() “-Funktionen (z. B. ` QSerialPort::waitForReadyRead()`) aufgerufen werden, um den aufrufenden Thread so lange anzuhalten, bis der Vorgang abgeschlossen ist.

In diesem Beispiel wird der asynchrone Ansatz demonstriert. Das Beispiel „Blocking Receiver“ veranschaulicht den synchronen Ansatz.

Unser Beispiel enthält einige GUI-Widgets:

  • MainWindow (terminal/mainwindow.cpp) – ist das Hauptanwendungsfenster, das die gesamte Arbeitslogik für die Programmierung der seriellen Schnittstelle enthält, einschließlich Konfiguration, E/A-Verarbeitung usw., und von der Klasse `QMainWindow` abgeleitet ist.
  • Console (terminal/console.cpp) – ist das zentrale Widget des Hauptfensters, das die gesendeten oder empfangenen Daten anzeigt. Das Widget leitet sich von der Klasse `QPlainTextEdit` ab.
  • SettingsDialog (terminal/settingsdialog.cpp) – ist ein Dialogfeld zur Konfiguration der seriellen Schnittstelle sowie zur Anzeige der verfügbaren seriellen Schnittstellen und der dazugehörigen Informationen.

Die serielle Schnittstelle wird im Konstruktor von „ MainWindow “ instanziiert. Das Haupt-Widget wird als übergeordnetes Element übergeben, sodass die Löschung des Objekts automatisch gemäß dem Eltern-Kind-Mechanismus in Qt erfolgt:

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

Dieses Beispiel veranschaulicht die folgenden Signale von „ QSerialPort “:

  • readyRead() – zeigt an, dass neue Daten empfangen wurden und somit verfügbar sind
  • bytesWritten() – dient zur Überprüfung, ob alle Daten erfolgreich geschrieben wurden
    ...
    connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData);
    connect(m_serial, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten);
    ...
}

Ein Klick auf die Schaltfläche „Connect“ ruft den Slot „ openSerialPort() “ auf:

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"));
    }
}

In diesem Slot werden die Einstellungen aus „ SettingsDialog “ gelesen und es wird versucht, den seriellen Port entsprechend zu öffnen und zu initialisieren. Bei Erfolg zeigt die Statusleiste eine Meldung an, dass das Öffnen mit der angegebenen Konfiguration erfolgreich war; andernfalls wird ein Meldungsfeld mit dem entsprechenden Fehlercode und der entsprechenden Fehlermeldung angezeigt. Wurden die Einstellungen für den seriellen Port noch nie aufgerufen, versucht das Terminal, den Port mit den Standardeinstellungen zu öffnen: 9600 8N1.

Ein Klick auf die Schaltfläche „Trennen“ ruft den Slot „ closeSerialPort() “ auf:

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"));
}

In diesem Fall erfolgt die Abwicklung durch das Schließen des seriellen Ports.

Ein Klick auf die Schaltfläche „Konfigurieren“ ruft den Slot „ show() “ auf, der zum Widget „ SettingsDialog “ gehört.

Diese Methode (terminal/settingsdialog.cpp) zeigt das Fenster „ SettingsDialog “ an, in dem der Benutzer den gewünschten seriellen Port auswählen, Informationen zum ausgewählten Port einsehen und die gewünschten Parameter für den jeweiligen seriellen Port einstellen kann.

Daten schreiben

Die Eingabe von Zeichen in die Konsole löst den Slot „ writeData() “ aus:

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);
    }
}

Dieser Slot sendet die im angegebenen „Console“-Widget eingegebenen Zeichen an den seriellen Port – siehe „ terminal/console.cpp “. Außerdem startet er einen Timer, um zu verfolgen, ob das Schreiben tatsächlich erfolgreich war oder nicht. Wir verwenden das Signal „ bytesWritten()“, um sicherzustellen, dass alle Bytes tatsächlich geschrieben wurden. Es ist mit dem Slot „ MainWindow::handleBytesWritten() “ verbunden:

void MainWindow::handleBytesWritten(qint64 bytes)
{
    m_bytesToWrite -= bytes;
    if (m_bytesToWrite == 0)
        m_timer->stop();
}
Daten lesen

Wenn der serielle Port neue Daten empfängt, wird das Signal „ readyRead()“ ausgelöst, und dieses Signal ist mit dem Slot „ MainWindow::readData() “ verbunden:

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

Dieser Slot liest die Daten aus der seriellen Schnittstelle aus und zeigt sie im Widget „Console“ an.

Ausführen des Beispiels

Sie können das Beispiel wie folgt ausführen:

Beispielprojekt @ code.qt.io

Siehe auch „Blockierender Empfänger“.

© 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.