En esta página

Terminal serie

Muestra cómo utilizar varias funciones de QSerialPort.

Terminal muestra cómo crear un terminal para una interfaz serie simple utilizando Qt Serial Port.

Terminal de puerto serie Qt

Este ejemplo muestra las principales características de la clase QSerialPort, como la configuración, la implementación de E/S y demás. También se invoca a la clase QSerialPortInfo para mostrar información sobre los puertos serie disponibles en el sistema.

QSerialPort soporta dos enfoques generales de programación:

  • El enfoque asíncrono (sin bloqueo). Las operaciones se programan y ejecutan cuando el control vuelve al bucle de eventos de Qt. QSerialPort emite una señal cuando la operación ha finalizado. Por ejemplo, QSerialPort::write() retorna inmediatamente. Cuando los datos se envían al puerto serie, QSerialPort emite bytesWritten().
  • El enfoque síncrono (de bloqueo). En aplicaciones no GUI y multihilo, las funciones waitFor...() pueden ser llamadas (por ejemplo, QSerialPort::waitForReadyRead()) para suspender el hilo de llamada hasta que la operación haya finalizado.

En este ejemplo, se muestra el enfoque asíncrono. El ejemplo del receptor de bloqueo ilustra el enfoque síncrono.

Nuestro ejemplo contiene algunos widgets GUI:

  • MainWindow (terminal/mainwindow.cpp) - es la ventana principal de la aplicación que contiene toda la lógica de trabajo para la programación del puerto serie, incluyendo configuración, procesamiento de E/S y demás, mientras hereda el QMainWindow.
  • Console (terminal/console.cpp) - es el widget central de la ventana principal, mostrando los datos transmitidos o recibidos. El widget es derivado de la clase QPlainTextEdit.
  • SettingsDialog (terminal/settingsdialog.cpp) - es un diálogo para configurar el puerto serie, así como para mostrar los puertos serie disponibles e información sobre ellos.

El puerto serie es instanciado en el constructor MainWindow. El widget principal se pasa como padre, por lo que la eliminación del objeto se produce automáticamente de acuerdo con el mecanismo de padres e hijos en Qt:

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

Este ejemplo demuestra las siguientes señales QSerialPort:

  • readyRead() - muestra que se han recibido nuevos datos y por lo tanto están disponibles
  • bytesWritten() - se utiliza para comprobar que todos los datos se han escrito correctamente
    ...
    connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData);
    connect(m_serial, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten);
    ...
}

Al hacer clic en el botón Conectar se invoca la ranura 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"));
    }
}

En esta ranura, se leen los ajustes de SettingsDialog y se intenta abrir e inicializar el puerto serie en consecuencia. Si tiene éxito, la barra de estado muestra un mensaje que indica que la apertura se ha realizado correctamente con la configuración dada; de lo contrario, se muestra un cuadro de mensaje con el código de error y el mensaje apropiados. Si nunca se ha llamado a la configuración del puerto serie, entonces el terminal intenta abrir el puerto con la configuración por defecto: 9600 8N1.

Al pulsar el botón Desconectar se invoca la ranura 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"));
}

En este caso, gestionado por el cierre del puerto serie.

Al hacer clic en el botón Configurar se invoca la ranura show() que pertenece al widget SettingsDialog.

Este método (terminal/settingsdialog.cpp) muestra la ranura SettingsDialog, en la que el usuario puede elegir el puerto serie deseado, ver la información sobre el puerto seleccionado y configurar los parámetros deseados del puerto serie dado.

Escribiendo Datos

Al escribir caracteres en la consola se invoca la ranura 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);
    }
}

Esta ranura envía los caracteres tecleados en el widget de Consola dado al puerto serie - ver terminal/console.cpp. También inicia un temporizador para controlar si la escritura ha tenido éxito o no. Usamos la señal bytesWritten() para asegurarnos de que todos los bytes son realmente escritos. Está conectada a la ranura MainWindow::handleBytesWritten():

void MainWindow::handleBytesWritten(qint64 bytes)
{
    m_bytesToWrite -= bytes;
    if (m_bytesToWrite == 0)
        m_timer->stop();
}
Lectura de Datos

Cuando el puerto serie recibe nuevos datos, la señal readyRead() es emitida, y esa señal es conectada a la ranura MainWindow::readData():

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

Esta ranura lee los datos del puerto serie y los muestra en el widget Consola.

Ejecutar el ejemplo

Para ejecutar el ejemplo desde Qt Creatorabra el modo Welcome y seleccione el ejemplo de Examples. Para más información, ver Qt Creator: Tutorial: Construir y ejecutar.

Proyecto de ejemplo @ code.qt.io

Véase también Receptor de bloqueo.

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