QT_串口多线程通讯

  • Post author:
  • Post category:其他


架构说明:UI主界面定时发送读写信号,触发逻辑线程执行串口读写操作,并返回处理后的数据,由UI界面显示。

特点:

1.创建一个逻辑工作类

2.用moveToThread方法将工作类放入到线程中

3.UI主界面与线程的一切沟通均用信号槽(安全)

4.逻辑工作返回信号,刷新UI界面防死机重启定时器

5.做好内存回收,不然。。。。。。。。。。。

/**************************mywork.h*************************/
#ifndef MYWORK_H
#define MYWORK_H

#include <QObject>
#include<QtSerialPort/QSerialPort>      //串口功能头文件
#include<QTimer>

class MyWork : public QObject
{
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = nullptr);
    // 工作函数
       void working();
       void send_data();    //发送槽函数
       void receive_data(); //接收槽函数
       void data_handing(QByteArray * readtemp); //数据处理程序
       QSerialPort * Mport1;
       QByteArray read1;
       QByteArray readtemp;
public:     //数据词典
       QByteArray b1;
       QByteArray b2;
       QByteArray b3;
       QByteArray b4;
       QByteArray b5;
       QByteArray b6;
       QByteArray b7;
       QByteArray b8;

signals:

};

#endif // MYWORK_H
/**************************mywork.cpp*************************/
#include "mywork.h"
#include <QDebug>
#include <QThread>
#include<QtSerialPort/QSerialPort>      //串口功能头文件
#include<QByteArray>
#include<QTimer>
#include<QString>

MyWork::MyWork(QObject *parent) : QObject(parent)
{

}

void MyWork::working()
{
    qDebug() << "逻辑线程对象的地址: " << QThread::currentThread();
    //初始化串口------------------------------------------------------
    Mport1 = new QSerialPort(this);        //创建一个串口
    Mport1->setPortName("COM3");                        //串口名称
    Mport1->setBaudRate(QSerialPort::Baud9600);         //波特率 9600
    Mport1->setDataBits(QSerialPort::Data8);            //数据位 8位
    Mport1->setParity(QSerialPort::NoParity);           //校验位 无校验
    Mport1->setStopBits(QSerialPort::OneStop);          //停止位 1位
    Mport1->setFlowControl(QSerialPort::NoFlowControl); //无流控
    //打开串口-----------------------------------------------------------
    bool ok =Mport1->open(QSerialPort::ReadWrite);      //打开串口(可读可写方式)
    if (ok)                                                    //判断串口打开状态
    {
        Mport1->clear();
        qDebug()<<"串口打开成功";
    }else
    {
        Mport1->close();
        qDebug()<<"串口打开失败";
    }
    //定义收发数据--------------------
    QByteArray readtemp;
    read1.resize(8);
    read1[0] = 0x01;
    read1[1] = 0x04;
    read1[2] = 0x00;
    read1[3] = 0x00;
    read1[4] = 0x00;
    read1[5] = 0x08;
    read1[6] = 0xf1;
    read1[7] = 0xcc;
    qDebug()<<"待发送数据"<<read1.toHex();
    //连接接收信号槽
    connect(Mport1,&QSerialPort::readyRead,this,&MyWork::receive_data);
    qDebug() << " 执行完毕, 子线程退出...";
}

void MyWork::send_data()        //发送槽函数
{
    qDebug() << " 发送功能执行";
    Mport1->write(read1);
    qDebug() << "发送功能对象的地址: " << QThread::currentThread();
}

void MyWork::receive_data()     //接收槽函数
{
    qDebug() << "接收功能对象的地址: " << QThread::currentThread();
    readtemp.append(Mport1->readAll());
    data_handing(&readtemp);     //传入数据处理
//一次性延时缓冲读取功能 成功---------------------
//    QTimer::singleShot(50, this,[=](){
//        qDebug() << "接收数据内容: " << readtemp.toHex();
//        readtemp.clear();   //清除数据
//    });//------------------------------------
}
//使用指针的形式可以 成功
void MyWork::data_handing(QByteArray * readtemp)     //数据处理及分类
{
    if(readtemp->size()==21)         //判断型读取
    {
        qDebug() << "接收数据内容: " << readtemp->toHex();
        uchar u1 = readtemp->at(13);
        uchar u2 = readtemp->at(14);
        qDebug("6号数据高位内容十六进制:%x", u1);
        qDebug("6号数据低位内容十六进制:%x", u2);
        readtemp->clear();   //清除数据
    }
}

/**************************widget.h*************************/
#ifndef WIDGET_H
#define WIDGET_H
#include "mywork.h"
#include <QWidget>


QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    void connect_ini();
signals:
    void sig_start();           //启动信号
private:
    Ui::Widget *ui;
    QThread * _Thr_SPort;      //串口线程对象
    QTimer * _Tim_MAS_signal; //主从信号定时器
    MyWork * _Work_logic;     //串口逻辑工作
};
#endif // WIDGET_H

/**************************widget.cpp*************************/
#include "widget.h"
#include "ui_widget.h"
#include <QThread>
#include "mywork.h"
#include <QDebug>
#include<QTimer>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)            //构建函数
{
    ui->setupUi(this);
    qDebug() << "主线程对象的地址: " << QThread::currentThread();
    _Thr_SPort = new QThread;                  //创建线程对象
    _Work_logic = new MyWork;                  //创建工作的类对象
    _Tim_MAS_signal = new QTimer;        //UI-逻辑线程心跳收发信号定时器
    _Thr_SPort->start();                       //启动线程
    _Work_logic->moveToThread(_Thr_SPort);    //将工作的类对象移动到创建的子线程对象中
    connect_ini();                              //连接信号槽初始化
    emit sig_start();                           //发送启动信号
//    _Work_logic->working();                   //直接运行串口线程工作可以用但是会报错感觉不稳定
    _Tim_MAS_signal->start(1000);
//    QTimer::singleShot(5000, _Work_logic,&MyWork::working);      //一次性定时器    成功
    //连接信号槽---启动按钮
}

Widget::~Widget()   //析构函数
{
    delete ui;
}
void Widget::connect_ini()          //连接信号槽初始化
{
    //连接信号槽---启动按钮初始化串口
    connect(ui->Button_senddata,    &QPushButton::clicked,
            _Work_logic,            &MyWork::send_data);
    //连接信号槽---发送按钮读取串口数据
    connect(ui->Button_start,   &QPushButton::clicked,
            _Work_logic,        &MyWork::working);
    //连接信号槽---定时跳动读取串口数据
    connect(_Tim_MAS_signal,        &QTimer::timeout,
            _Work_logic,            &MyWork::send_data);
    //连接信号槽---主线程启动后启动子线程
    connect(this,           &Widget::sig_start,
            _Work_logic,   &MyWork::working);
}



版权声明:本文为weixin_43823261原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。