What's New in Qt 5.1: QtSerialPort

By Jeff Tranter

Introduction

QtSerialPort is a Qt module that provides support for serial ports such as those that follow the RS-232 standard. Serial port modules for Qt have existed for some time, going back at least as far as QExtSerialPort under Qt version 2, but none of them were officially part of Qt. QtSerialPort originated from the third-party library QSerialDevice and was subsequently made part of the Qt project. It officially becomes part of Qt with the 5.1.0 release.

QtSerialPort supports Qt versions 4 and 5. With versions of Qt prior to 5.1.0 you can get the source code separately from gitorious.org. The module supports most 32 and 64-bit versions of Microsoft Windows, Linux, Mac OS X, and POSIX-compatible systems such as UNIXes. There is partial support for Windows CE and Symbian but these aren't likely to be actively supported in future since Qt 5 does not support them.

Using It

The module provides two main classes: QSerialPort and QSerialPortInfo. To use the module with Qt 5 add this line to your qmake project file:

QT += serialport

You can then include the header files <QSerialPort> or <QSerialPortInfo>. There is quite good documentation for the classes. You can view it from Qt Assistant or on-line here (once Qt 5.1.0 is released).

APIs

The QSerialPortInfo class provides information about a serial port on the system. You can create a QSerialPortInfo object by specifying a device name or an existing QSerialPort object. You can also get a list of QSerialPort objects for all serial ports by calling the static method availablePorts(). Once you have a QSerialPortInfo object you can call various methods to get information such as the port's name, location, description, and manufacturer.

QSerialPort is the class used for communication. It inherits from QIODevice, the base class of all I/O devices in Qt, including files, buffers, and TCP and UDP sockets. This allows you to leverage your knowledge of input/output in Qt and use it with any class that operates on a QIODevice, like the XML classes. The QSerialPort class was modelled on the functionality and behavior of the QAbstractSocket class, so if you have used network sockets with Qt it should be familiar to you. The API documentation describes the class in detail. You can use the serial port in blocking or non-blocking modes. Note that the serial port is always opened for exclusive access so no other process or thread can access the opened serial port. To maintain portability across platforms more advanced features such as setting timeouts and delays are not provided.

The module comes with example applications that illustrate blocking and non-blocking I/O and how to get and display the serial port information.

Here is a code example that displays information about each port found. It uses both the QSerialPortInfo and QSerialPort classes. It is similar to the "cenumerator" example that comes with the source distribution.

#include <QCoreApplication>
#include <QDebug>
#include <QSerialPort>
#include <QSerialPortInfo>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "Number of serial ports:" << QSerialPortInfo::availablePorts().count();

    foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {

        qDebug() << "\nPort:" << serialPortInfo.portName();
        qDebug() << "Location:" << serialPortInfo.systemLocation();
        qDebug() << "Description:" << serialPortInfo.description();
        qDebug() << "Manufacturer:" << serialPortInfo.manufacturer();
        qDebug() << "Vendor Identifier:" << (serialPortInfo.hasVendorIdentifier() ? QByteArray::number(serialPortInfo.vendorIdentifier(), 16) : QByteArray());
        qDebug() << "Product Identifier:" << (serialPortInfo.hasProductIdentifier() ? QByteArray::number(serialPortInfo.productIdentifier(), 16) : QByteArray());
        qDebug() << "Busy:" << (serialPortInfo.isBusy() ? QObject::tr("Yes") : QObject::tr("No"));

        QSerialPort *port = new QSerialPort(serialPortInfo);
        if (port->open(QIODevice::ReadWrite)) {
            qDebug() << "Baud rate:" << port->baudRate();
            qDebug() << "Data bits:" << port->dataBits();
            qDebug() << "Stop bits:" << port->stopBits();
            qDebug() << "Parity:" << port->parity();
            qDebug() << "Flow control:" << port->flowControl();
            qDebug() << "Read buffer size:" << port->readBufferSize();
            port->close();
        } else {
            qDebug() << "Unable to open port, error code" << port->error();
        }
        delete port;
    }

    return 0;
}

Here is the output of the program on one of my Linux systems:

Number of serial ports: 1 

Port: "ttyUSB0" 
Location: "/dev/ttyUSB0" 
Description: "USB-Serial Controller" 
Manufacturer: "Prolific Technology Inc." 
Vendor Identifier: "67b" 
Product Identifier: "2303" 
Busy: "No" 
Baud rate: 9600 
Data bits: 8 
Stop bits: 1 
Parity: 0 
Flow control: 0 
Read buffer size: 0 

The library makes it quite easy to implement a terminal emulator, for example. One of the examples that comes with the source is a simple graphical terminal program. A screen shot is shown below.

There is currently no support for using the QtSerialPort module from QML; it is a C++ API only.

A lot of newer desktop PC systems do not include a serial port. However, there is often still a need for serial ports, especially if you work with embedded systems than use a serial port for communication. A common solution is to use a low cost USB to serial adaptor. These are supported if the operating system has a driver for it.

A Tip: Many embedded systems use serial interfaces running at 3.3 volt or 5 volt signal levels rather than the RS-232 standard. The Raspberry Pi, for example, has a built in serial port that can be used as a console. To communicate with these from a desktop system you can use a device such as the FTDI Friend which supports serial ports using these voltage levels. If you work a lot with serial ports on embedded systems it is also helpful to have a good selection of cables and gender adaptors/null modems on hand as these devices tend to vary in the cables and connectors needed to connect to them.

Conclusions

In summary, if you need to work with serial ports the new QtSerialPort module included in Qt 5.1 makes this easy to do in a portable way.

Note that the above information was based on the Qt 5.1 Beta release and could possibly change before Qt 5.1.0 final.