• Qt中的串口编程之三


    QtSerialPort

    今天我们来介绍一下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; }
    


    附录:

    1、qtserialport源代码中使用了D指针,Q指针,这方面的介绍请见Qt之美(一):d指针/p指针详解

  • 相关阅读:
    golang获取变量数据类型
    有道云笔记隐藏广告
    golang搭建web服务器
    node.js搭建https服务器
    Linux查看CPU和内存信息
    go语言中文处理
    node.js压缩和解压缩
    关于同步、异步、阻塞、非阻塞简单总结
    Nginx部署静态网站
    node.js分片上传文件
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3192304.html
Copyright © 2020-2023  润新知