现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

Qt5中的串口编程之三

2015-03-02 06:36 工业·编程 ⁄ 共 8353字 ⁄ 字号 暂无评论

今天我们来介绍一下QtSerialPort模块的源代码,学习一下该可移植的串口编程库是怎么实现的。

首先,我们下载好了源代码之后,使用QtCreator打开整个工程,可以看到如下图的源代码结构:

我们先来看一下serialport-lib.pri这个文件,serialport.pro工程文件就是靠这个文件来控制整个源代码的编译的。,具体内容如下:

上面的内容只是最基本的类,大家知道,跨平台的类一般在底层都包含这与操作系统相关的一些实现,这里也不例外,大家看看下面的图就明白了,

这里只以类unix操作系统为例来做说明:

也许看到这个大家不是很明白:

      这与qmake的一些特性相关:CONFIG、DEFINE、PKGCONFIG都是qmake私有的一些变量,而packagesExist()则是qmake私有的函数,

整个这一块要表达的意思是"如果udev这个库存在,则编译程序的时候就定义HAVE_LIBUDEV这个宏定义(在我们的代码中使用了这个宏定义),

并且链接程序的时候,也链接udev这个库"。至于qmake的一些特性以及使用方法,后续会专门写几篇博文详细介绍。

      至于udev这个库的介绍,请见:libudev

      我们在代码中是如下使用udev库的:

      在serialport源代码中还是用了另外一个开源库,那就是lockdev,该库主要提供的功能就是“Lockdev is a setgid binary,
which provides a reliable way to put an exclusive lock in /var/lock to devices (e.g. ttyS0) using both FSSTND and SVr4 methods,
so regular users don't need write access there.”

      下面,看看我们在代码中是如何使用lockdev的:

      对于lockdev,我们在下一篇博客中将详细介绍它的功能的和实现。

好了,言归正传,我们来看看serialport库在类unix操作系统上是如何实现的:

头文件:

与平台无关的公共头文件:qserialportglobal.h qserialport.h qserialportinfo.h
与平台无关的私有头文件:qserialport_p.h qserialportinfo_p.h
与平台有关的头文件:       qttylocker_unix_p.h qserialport_unix_p.h

源文件:

与平台无关的源文件:qserialport.cpp qserialportinfo.cpp
与平台有关的源文件:qttylocker_unix.cpp qserialport_unix.cpp qserialportinfo_unix.cpp

源代码解析:

1、QSerialPort类源码解析

(1)QSerialPort类继承自QIODevice,包含对串口的基本操作:

与该类有关系的类主要是如下几个:

QIODevice、QSerialPort、QSerialPortPrivate、QSerialPortPrivateData。

它们的关系如下:

QSerialPort继承自QIODevice,继承了对设备文件基本的操作。

QSerialPortPrivate是QSerialPort对象中表示操作一类的,该部分与操作系统有关。QSerialPortvate继承自QSerialPortPrivateData。

QSerialPortPrivateData是一个串口设备的初始化数据,例如波特率等等。

QSerialPortPrivateData更多表示串口设备的初始数据,QSerialPortPrivate更多表示平台相关的对串口设备的操作。

(2)QSerialPort类定义:

class QSerialPortInfo; 

class QSerialPortPrivate; 

class Q_SERIALPORT_EXPORT QSerialPort : public QIODevice 

    Q_OBJECT 

    Q_PROPERTY(qint32 baudRate READ baudRate WRITE setBaudRate NOTIFY baudRateChanged) 

    Q_PROPERTY(DataBits dataBits READ dataBits WRITE setDataBits NOTIFY dataBitsChanged) 

    Q_PROPERTY(Parity parity READ parity WRITE setParity NOTIFY parityChanged) 

    Q_PROPERTY(StopBits stopBits READ stopBits WRITE setStopBits NOTIFY stopBitsChanged) 

    Q_PROPERTY(FlowControl flowControl READ flowControl WRITE setFlowControl NOTIFY flowControlChanged) 

    Q_PROPERTY(DataErrorPolicy dataErrorPolicy READ dataErrorPolicy WRITE setDataErrorPolicy NOTIFY dataErrorPolicyChanged) 

    Q_PROPERTY(bool dataTerminalReady READ isDataTerminalReady WRITE setDataTerminalReady NOTIFY dataTerminalReadyChanged) 

    Q_PROPERTY(bool requestToSend READ isRequestToSend WRITE setRequestToSend NOTIFY requestToSendChanged) 

    Q_PROPERTY(SerialPortError error READ error RESET clearError NOTIFY error) 

    Q_PROPERTY(bool settingsRestoredOnClose READ settingsRestoredOnClose WRITE setSettingsRestoredOnClose NOTIFY settingsRestoredOnCloseChanged) 

    Q_ENUMS( Directions Rate DataBits Parity StopBits FlowControl PinoutSignals DataErrorPolicy SerialPortError ) 

public: 

enum Direction  { 

        Input = 1, 

        Output = 2, 

        AllDirections = Input | Output 

    }; 

    Q_DECLARE_FLAGS(Directions, Direction) 

enum BaudRate { 

        Baud1200 = 1200, 

        Baud2400 = 2400, 

        Baud4800 = 4800, 

        Baud9600 = 9600, 

        Baud19200 = 19200, 

        Baud38400 = 38400, 

        Baud57600 = 57600, 

        Baud115200 = 115200, 

        UnknownBaud = -1 

    }; 

enum DataBits { 

        Data5 = 5, 

        Data6 = 6, 

        Data7 = 7, 

        Data8 = 8, 

        UnknownDataBits = -1 

    }; 

enum Parity { 

        NoParity = 0, 

        EvenParity = 2, 

        OddParity = 3, 

        SpaceParity = 4, 

        MarkParity = 5, 

        UnknownParity = -1 

    }; 

enum StopBits { 

        OneStop = 1, 

        OneAndHalfStop = 3, 

        TwoStop = 2, 

        UnknownStopBits = -1 

    }; 

enum FlowControl { 

        NoFlowControl, 

        HardwareControl, 

        SoftwareControl, 

        UnknownFlowControl = -1 

    }; 

enum PinoutSignal { 

        NoSignal = 0x00, 

        TransmittedDataSignal = 0x01, 

        ReceivedDataSignal = 0x02, 

        DataTerminalReadySignal = 0x04, 

        DataCarrierDetectSignal = 0x08, 

        DataSetReadySignal = 0x10, 

        RingIndicatorSignal = 0x20, 

        RequestToSendSignal = 0x40, 

        ClearToSendSignal = 0x80, 

        SecondaryTransmittedDataSignal = 0x100, 

        SecondaryReceivedDataSignal = 0x200 

    }; 

    Q_DECLARE_FLAGS(PinoutSignals, PinoutSignal) 

enum DataErrorPolicy { 

        SkipPolicy, 

        PassZeroPolicy, 

        IgnorePolicy, 

        StopReceivingPolicy, 

        UnknownPolicy = -1 

    }; 

enum SerialPortError { 

        NoError, 

        DeviceNotFoundError, 

        PermissionError, 

        OpenError, 

        ParityError, 

        FramingError, 

        BreakConditionError, 

        WriteError, 

        ReadError, 

        ResourceError, 

        UnsupportedOperationError, 

        UnknownError 

    }; 

explicit QSerialPort(QObject *parent = 0); 

explicit QSerialPort(const QString &name, QObject *parent = 0); 

explicit QSerialPort(const QSerialPortInfo &info, QObject *parent = 0); 

virtual ~QSerialPort(); 

void setPortName(const QString &name); 

    QString portName() const; 

void setPort(const QSerialPortInfo &info); 

bool open(OpenMode mode) Q_DECL_OVERRIDE; 

void close() Q_DECL_OVERRIDE; 

void setSettingsRestoredOnClose(bool restore); 

bool settingsRestoredOnClose() const; 

bool setBaudRate(qint32 baudRate, Directions dir = AllDirections); 

    qint32 baudRate(Directions dir = AllDirections) const; 

bool setDataBits(DataBits dataBits); 

    DataBits dataBits() const; 

bool setParity(Parity parity); 

    Parity parity() const; 

bool setStopBits(StopBits stopBits); 

    StopBits stopBits() const; 

bool setFlowControl(FlowControl flow); 

    FlowControl flowControl() const; 

bool setDataTerminalReady(bool set); 

bool isDataTerminalReady(); 

bool setRequestToSend(bool set); 

bool isRequestToSend(); 

    PinoutSignals pinoutSignals(); 

bool flush(); 

bool clear(Directions dir = AllDirections); 

bool atEnd() const Q_DECL_OVERRIDE; 

bool setDataErrorPolicy(DataErrorPolicy policy = IgnorePolicy); 

    DataErrorPolicy dataErrorPolicy() const; 

    SerialPortError error() const; 

void clearError(); 

    qint64 readBufferSize() const; 

void setReadBufferSize(qint64 size); 

bool isSequential() const Q_DECL_OVERRIDE; 

    qint64 bytesAvailable() const Q_DECL_OVERRIDE; 

    qint64 bytesToWrite() const Q_DECL_OVERRIDE; 

bool canReadLine() const Q_DECL_OVERRIDE; 

bool waitForReadyRead(int msecs) Q_DECL_OVERRIDE; 

bool waitForBytesWritten(int msecs) Q_DECL_OVERRIDE; 

bool sendBreak(int duration = 0); 

bool setBreakEnabled(bool set = true); 

Q_SIGNALS: 

void baudRateChanged(qint32 baudRate, QSerialPort::Directions dir); 

void dataBitsChanged(QSerialPort::DataBits dataBits); 

void parityChanged(QSerialPort::Parity parity); 

void stopBitsChanged(QSerialPort::StopBits stopBits); 

void flowControlChanged(QSerialPort::FlowControl flow); 

void dataErrorPolicyChanged(QSerialPort::DataErrorPolicy policy); 

void dataTerminalReadyChanged(bool set); 

void requestToSendChanged(bool set); 

void error(QSerialPort::SerialPortError serialPortError); 

void settingsRestoredOnCloseChanged(bool restore); 

protected: 

    qint64 readData(char *data, qint64 maxSize) Q_DECL_OVERRIDE; 

    qint64 readLineData(char *data, qint64 maxSize) Q_DECL_OVERRIDE; 

    qint64 writeData(const char *data, qint64 maxSize) Q_DECL_OVERRIDE; 

private: 

void setError(QSerialPort::SerialPortError error, const QString &errorString = QString()); 

    QSerialPortPrivate * const d_ptr; 

    Q_DECLARE_PRIVATE(QSerialPort) 

    Q_DISABLE_COPY(QSerialPort) 

}; 

Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::Directions) 

Q_DECLARE_OPERATORS_FOR_FLAGS(QSerialPort::PinoutSignals) 

2、QserialPortInfo类源码解析

(1)QserialPortInfo主要是枚举系统上可用串口设备的信息:

与该类的类主要是如下几个:

QSerialPort、QSerialPortInfo、QSerialPortInfoPrivate、QSerialPortInfoPrivateDeleter。

QSerialPortInfo的构造函数中使用到了QSerialPort。

QSerialPortInfoPrivate则代表QSerialPortInfo的私有数据。

(2)QserialPortInfo类定义:

class QSerialPort; 

class QSerialPortInfoPrivate; 

class QSerialPortInfoPrivateDeleter; 

class Q_SERIALPORT_EXPORT QSerialPortInfo 

    Q_DECLARE_PRIVATE(QSerialPortInfo) 

public: 

    QSerialPortInfo(); 

explicit QSerialPortInfo(const QSerialPort &port); 

explicit QSerialPortInfo(const QString &name); 

    QSerialPortInfo(const QSerialPortInfo &other); 

    ~QSerialPortInfo(); 

    QSerialPortInfo& operator=(const QSerialPortInfo &other); 

void swap(QSerialPortInfo &other); 

    QString portName() const; 

    QString systemLocation() const; 

    QString description() const; 

    QString manufacturer() const; 

    quint16 vendorIdentifier() const; 

    quint16 productIdentifier() const; 

bool hasVendorIdentifier() const; 

bool hasProductIdentifier() const; 

bool isNull() const; 

bool isBusy() const; 

bool isValid() const; 

static QList<qint32> standardBaudRates(); 

static QList<QSerialPortInfo> availablePorts(); 

private: 

    QScopedPointer<QSerialPortInfoPrivate, QSerialPortInfoPrivateDeleter> d_ptr; 

}; 

inline bool QSerialPortInfo::isNull() const

{ return !d_ptr; } 

作者:chenlong12580

给我留言

留言无头像?