Qt中利用多线程读取串口数据

需求:有多个串口进行数据的处理,最好需要把线程封装到串口类(serialPort)中
        这样就可以在主线程中通过new多个serialport对象myPort1、myPort2等来创建多个线程管理各个串口
            
实现方式:继承QObject的方式来写线程,  所有东西都需要用信号和槽来进行交互!!!
思路:
主线程中需要的操作:通过控制一个按钮来操作一个串口的关闭,即控制一个线程的关闭
串口类中需要的操作:
1、不想把new QThread和myPort1->moveToThread等操作,放到主线程初始化函数中,这样程序会臃肿
        所以应把上述操作放到串口类serialPort初始化中,这就需要在主程序的初始化中new一个serialport对象myPort
        此时串口类serialPort初始化线程和主线程是同一个线程id
        注意:那可以把new一个serialport对象myPort这个过程放到按钮下面吗?
                据大神说是不行的,逻辑有问题的,我在这里始终没有想明白。
                我的想法(还没有进行验证):这样做后果是每次点击打开串口按钮都会new一个内存,但是可以再关闭掉。
        
2、如何开始线程,UI中开始按钮发送信号,serialport类中槽函数1-SLot_StartThread()响应这个信号,
    serialport中槽函数1就是thread->start()操作来开始线程,此时这个槽函数1的线程id和主线程相同
        再将thread->start()连接一个槽函数2-Slot_OpenComPort,槽函数2进行串口的初始化和打开串口,
        打开串口后利用串口的readyRead()信号连接一个槽函数3-Slot_ReadSerialPortData()
            此时槽函数2和槽函数3的线程号相同,但是和主线程线程id不同,开始了一个新的线程
            注意:我自己在串口的多次打开和关闭试验得知,串口打开后将只需要connect一次readyRead()信号和槽函数                  
                    不然多次打开和关闭后可能会读出空字符,意思是实际发一个字符可是收到了一个字符+一个空字符
                    我想的是每次打开和关闭串口都会重新connect,重复了多次就会输出多的东西(有可能是我还是没有弄明白)

3、槽函数3读取接收值并发送信号给主线程,更新UI

困难:
1、这里要重点理解connect机制,也就是connect的第五个参数,
    借鉴一个老哥的博客:https://blog.csdn.net/kamereon/article/details/49582617
    a)DirectConnection,信号发送后槽函数立即执行,由sender的所在线程执行;
    b)QueuedConnection,信号发送后返回,相关槽函数由receiver所在的线程在返回到事件循环后执行;

    c)默认使用的是Qt::AutoConnection,当sender和receiver在同一个线程内时,采用DirectConnection的方式,
        当sender和receiver在不同的线程时,采用QueuedConnection的方式。

    按钮打开串口需要槽函数1立即响应,所以连接方式为DirectConnection,所以执行者是主程序,都为主线程
    槽函数2和3都是通过AutoConnecTion方式连接的,和主线程不在一个线程
    关闭按钮信号是在主线程,想要发送信号关闭子线程,则连接方式一定为默认的方式即QueuedConnection
    不然就会出现跨线程的操作。
    
2、线程和串口是如何关闭的?
    直接关掉串口和线程,但是不能删除串口和线程。

下面开始上代码:

mySerialPort.h
#ifndef MYSERIALPORT_H
#define MYSERIALPORT_H
#include 
#include 
#include 
#include
#include
class mySerialPort : public QObject
{
    Q_OBJECT
public:
    mySerialPort(QString port,int bara);
private:
    QString COM;
    int BauaRate;

    QSerialPort *myPort;
    QThread *thread;
    bool isConnectFlag;
signals:
    void Sig_SendSerialPortData(QString);
public slots:
    void SLot_StartThread();//槽函数1
    void Slot_OpenComPort();//槽函数2
    void Slot_ReadSerialPortData();//槽函数3

    void SLot_CloseThread();
};

#endif // MYSERIALPORT_H


mySerialPort.cpp
#include "myserialport.h"

mySerialPort::mySerialPort(QString port,int bara)
{
    COM = port;
    BauaRate = bara;
    isConnectFlag = true;
    myPort = new QSerialPort();
    thread = new QThread();
    this->moveToThread(thread);
    myPort->moveToThread(thread);
    connect(thread,SIGNAL(started()),this,SLOT(Slot_OpenComPort()));
    qDebug()<<"创建对象初始化线程为:"<isRunning()){
        thread->start();
        qDebug()<<"线程开始了,线程号:"<setPortName(COM);
    myPort->setBaudRate(BauaRate);
    myPort->setDataBits(QSerialPort::Data8);
    myPort->setStopBits(QSerialPort::OneStop);
    myPort->setParity(QSerialPort::NoParity);
    myPort->setFlowControl(QSerialPort::NoFlowControl);
    if(myPort->open(QIODevice::ReadWrite))
    {
        qDebug()<<"串口打开成功,子线程号"<readAll();
    if(!buf.isEmpty()){
        QString str = buf;
        qDebug()<clear();
    myPort->close();
    //myPort->deleteLater();

    //杀死线程
    if(thread->isRunning())
    {
        thread->quit();
        thread->wait();
        //thread->deleteLater();
    }
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
public slots:
    void Slot_ReveiceData(QString);
    void Slot_OpenCom();
signals:
    void Sig_StartThread();
    void Sig_CloseThread();
private:
    Ui::Widget *ui;
    mySerialPort *GpsSerialPort;

};

#endif // WIDGET_H

widget.cpp

#include "myserialport.h"

mySerialPort::mySerialPort(QString port,int bara)
{
    COM = port;
    BauaRate = bara;
    isConnectFlag = true;
    myPort = new QSerialPort();
    thread = new QThread();
    this->moveToThread(thread);
    myPort->moveToThread(thread);
    connect(thread,SIGNAL(started()),this,SLOT(Slot_OpenComPort()));
    qDebug()<<"创建对象初始化线程为:"<isRunning()){
        thread->start();
        qDebug()<<"线程开始了,线程号:"<setPortName(COM);
    myPort->setBaudRate(BauaRate);
    myPort->setDataBits(QSerialPort::Data8);
    myPort->setStopBits(QSerialPort::OneStop);
    myPort->setParity(QSerialPort::NoParity);
    myPort->setFlowControl(QSerialPort::NoFlowControl);
    if(myPort->open(QIODevice::ReadWrite))
    {
        qDebug()<<"串口打开成功,子线程号"<readAll();
    if(!buf.isEmpty()){
        QString str = buf;
        qDebug()<clear();
    myPort->close();
    //myPort->deleteLater();

    //杀死线程
    if(thread->isRunning())
    {
        thread->quit();
        thread->wait();
        //thread->deleteLater();
    }
}

 

你可能感兴趣的:(QT学习)