架构说明: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);
}