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

Qt5.4:对QSerialPort的多线程扩展

2015-04-10 06:20 工业·编程 ⁄ 共 5418字 ⁄ 字号 评论 1 条

有时候经常需要把串口放到单独的一个线程去处理数据,于是我就把串口封装了一下,即支持了多线程也方便使用。

特性介绍:

1.串口工作是在一个单独的线程,更加稳定

2.实例化的对象可在多个线程被调用且不会出错

注意:

1.一些control开头的信号,是内部通讯用的,请勿直接使用

2.一般来说,只要管accepted和error两个信号就可以了

3.JasonQt_SerialPort_Run这个是工作用的类,不推荐直接使用

4.用到了C++11语法,所以请务必开启11模式,不然会编译报错

5.我使用的是Qt5.4.0,理论上5.2开始都可以用这份源码

6.使用前请在pro文件中加入

    QT += serialport

    CONFIG += c++11

不多说,上源码。

JasonQt_SerialPort.h

#ifndef __JasonQt_Serialport_h__

#define __JasonQt_Serialport_h__

// Qt lib import

#include <QSerialPort>

#include <QSerialPortInfo>

#include <QThread>

#include <QEventLoop>

class JasonQt_SerialPort; 

class JasonQt_SerialPort_run: public QObject 

    Q_OBJECT 

private: 

    JasonQt_SerialPort *m_parent = NULL; 

    QSerialPort *m_serialPort = NULL; 

public: 

    JasonQt_SerialPort_run(JasonQt_SerialPort *parent); 

public slots: 

void open(const QString &portName, const int &baudRate, const QSerialPort::DataBits &dataBits, const QSerialPort::Parity &parity, const QSerialPort::StopBits &stopBits); 

void close(void); 

void send(const QByteArray &data); 

private slots: 

void accepted(void); 

void error(const QSerialPort::SerialPortError &error); 

signals: 

void controlOpened(const bool isOpen); 

}; 

class JasonQt_SerialPort: public QThread 

    Q_OBJECT 

private: 

    JasonQt_SerialPort_run *m_serialPort = NULL; 

public: 

    JasonQt_SerialPort(void); 

    ~JasonQt_SerialPort(void); 

public slots: 

bool open(const QString &portName, const int &baudRate, 

const QSerialPort::DataBits &dataBits = QSerialPort::Data8, 

const QSerialPort::Parity &parity = QSerialPort::NoParity, 

const QSerialPort::StopBits &stopBits = QSerialPort::OneStop); 

void close(void); 

void send(const QByteArray &data); 

private: 

void run(void); 

signals: 

void accepted(const QByteArray data); 

void error(const QSerialPort::SerialPortError error); 

void controlOpen(const QString portName, const int baudRate, const QSerialPort::DataBits dataBits, const QSerialPort::Parity parity, QSerialPort::StopBits stopBits); 

void controlClose(void); 

void controlSend(const QByteArray data); 

}; 

#endif//__JasonQt_Serialport_h__

JasonQt_SerialPort.cpp

#include "JasonQt_SerialPort.h"

// JasonQt_SerialPort_run

JasonQt_SerialPort_run::JasonQt_SerialPort_run(JasonQt_SerialPort *parent) 

    m_parent = parent; 

    m_serialPort = NULL; 

void JasonQt_SerialPort_run::open(const QString &portName, const int &baudRate, const QSerialPort::DataBits &dataBits, const QSerialPort::Parity &parity, const QSerialPort::StopBits &stopBits) 

if(m_serialPort) 

    { 

this->close(); 

    } 

    m_serialPort = new QSerialPort(portName); 

#ifndef Q_OS_WIN

    m_serialPort->setBaudRate(baudRate); 

    m_serialPort->setDataBits(dataBits); 

    m_serialPort->setParity(parity); 

    m_serialPort->setStopBits(stopBits); 

#endif

    connect(m_serialPort, SIGNAL(readyRead()), this, SLOT(accepted()), Qt::DirectConnection); 

    connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(error(QSerialPort::SerialPortError)), Qt::DirectConnection); 

if(!m_serialPort->open(QIODevice::ReadWrite)) 

    { 

        emit controlOpened(false); 

return; 

    } 

#ifdef Q_OS_WIN

    m_serialPort->setBaudRate(baudRate); 

    m_serialPort->setDataBits(dataBits); 

    m_serialPort->setParity(parity); 

    m_serialPort->setStopBits(stopBits); 

#endif

    emit controlOpened(true); 

void JasonQt_SerialPort_run::close(void) 

if(m_serialPort) 

    { 

        m_serialPort->close(); 

        m_serialPort->deleteLater(); 

        m_serialPort = NULL; 

    } 

void JasonQt_SerialPort_run::send(const QByteArray &data) 

if(m_serialPort) 

    { 

        m_serialPort->write(data); 

    } 

void JasonQt_SerialPort_run::accepted(void) 

if(m_serialPort) 

    { 

        emit m_parent->accepted(m_serialPort->readAll()); 

    } 

void JasonQt_SerialPort_run::error(const QSerialPort::SerialPortError &error) 

if(error) 

    { 

        emit m_parent->error(error); 

    } 

// JasonQt_SerialPort

JasonQt_SerialPort::JasonQt_SerialPort(void) 

static bool flag = true; 

if(flag) 

    { 

        flag = false; 

        qRegisterMetaType<QSerialPort::DataBits>("QSerialPort::DataBits"); 

        qRegisterMetaType<QSerialPort::Parity>("QSerialPort::Parity"); 

        qRegisterMetaType<QSerialPort::StopBits>("QSerialPort::StopBits"); 

        qRegisterMetaType<QSerialPort::SerialPortError>("QSerialPort::SerialPortError"); 

    } 

this->start(); 

JasonQt_SerialPort::~JasonQt_SerialPort(void) 

this->quit(); 

this->wait(); 

bool JasonQt_SerialPort::open(const QString &portName, const int &baudRate, 

const QSerialPort::DataBits &dataBits, 

const QSerialPort::Parity &parity, 

const QSerialPort::StopBits &stopBits) 

    QEventLoop eventLoop; 

bool flag = false; 

    auto a = connect(m_serialPort, SIGNAL(controlOpened(bool)), &eventLoop, SLOT(quit()), Qt::DirectConnection); 

    auto b = connect(m_serialPort, &JasonQt_SerialPort_run::controlOpened, [&](const bool &isOpen){ flag = isOpen; }); 

    emit controlOpen(portName, baudRate, dataBits, parity, stopBits); 

    eventLoop.exec(QEventLoop::ExcludeUserInputEvents); 

    disconnect(a); 

    disconnect(b); 

return flag; 

void JasonQt_SerialPort::close(void) 

    emit controlClose(); 

void JasonQt_SerialPort::send(const QByteArray &data) 

    emit controlSend(data); 

void JasonQt_SerialPort::run(void) 

    m_serialPort = new JasonQt_SerialPort_run(this); 

    connect(this, SIGNAL(controlOpen(QString,int,QSerialPort::DataBits,QSerialPort::Parity,QSerialPort::StopBits)), 

            m_serialPort, SLOT(open(QString,int,QSerialPort::DataBits,QSerialPort::Parity,QSerialPort::StopBits))); 

    connect(this, SIGNAL(controlClose()), m_serialPort, SLOT(close())); 

    connect(this, SIGNAL(controlSend(QByteArray)), m_serialPort, SLOT(send(QByteArray))); 

this->exec(); 

delete m_serialPort; 

    m_serialPort = NULL; 

} 

使用效果

作者:wsj

目前有 1 条留言    访客:1 条, 博主:0 条

  1. 枫叶 2015年06月19日 5:20 下午  @回复  Δ1楼 回复

    你好 我是一个实习生,现在在做的就是一个关于串口通信的项目,我发现我现在的问题就是在主线程里面new了serialport然后在其他的线程使用,然后就报错了。能帮忙解决一下吗?

给我留言

留言无头像?