QT 高效串口读取、显示与存储软件开发之二:串口高效读取(线程讨论)
串口数据操作
搜了大量的资料,也看了QT的文档,串口读取有以下几种方案,包括:connect直接连接、线程中直接读取(Run)、利用movetothread、在线程中开启串口(打开串口)。所有的串口操作均封装在动态连接库中,名为:hdntCom,对外输入输出接口如下:
class SerialSetInfo{
public:
QString ComName;
QString BaudRate;
QString DataBit;
QString StopBit;
QString Parity;
QString Protocol;
};
class HDNTCOMSHARED_EXPORT hdntCom:public QThread
{
Q_OBJECT
public:
hdntCom(QObject *parent);
~hdntCom();
int Init(SerialSetInfo *SerialSetParm); //Init the serial port
int Open(); //open
int Close();
int Write(QByteArray *Dat);
QByteArray Read();
bool isOpen();
QByteArray ComData;
uint8_t *uComData;
uint16_t ComDataLength;
QSerialPort * m_serial = nullptr;
bool mThreadRun=true;
bool OpenFlag=false;
void setCallback(std::function<void(void)> func);
private slots:
void ReceiveComData(void);
signals:
void SendReceiveData(QByteArray Dat);
void Sg_ComReady(void);
private:
std::function<void(void)> m_func;
uint8_t BufferNum=2;
bool SolveFlag=true;
QByteArray Buffer1,Buffer2;
protected:
void run();
};
connect直接连接
利用connect命令,直接将readready与一个槽函数相连,代码如下:
connect(m_serial,SIGNAL(readyRead()),this,SLOT(ReceiveComData()));//有数据就读
该种方法,ReceiveComData函数运行在主线程中,一旦GUI负载过重,则串口卡顿明显。
线程中直接读取
将hdntCom继承于QThread,重构run函数
void hdntCom::run(){
while(mThreadRun)
{
if(m_serial->isOpen()){
if(m_serial->waitForReadyRead(-1)) //等待有数据到达,-1表示永不超时
{
this->usleep(1000); //延时一会,等待数据全部到达
ComData.clear();
Buffer1=m_serial->readAll();
ComData=Buffer1;
ComDataLength=ComData.length();
emit Sg_ComReady();
m_func();
}
}else{
this->terminate();
mThreadRun=false;
}
}
}
利用movetothread
新建一个类命名为工作线程,如下
#include <QObject>
#include <QtCore/qglobal.h>
#include <functional>
class WorkThread:public QObject
{
Q_OBJECT
public:
WorkThread(QObject *parent);
void setCallback(std::function<void(void)> func);
public slots:
void Slot_RecieveDat();
signals:
private:
std::function<void(void)> m_func;
};
使用方式如下
m_ComThread=new WorkThread(this);
Th_ComWork=new QThread;
m_ComThread->moveToThread(Th_ComWork);
Th_ComWork->start();
connect(m_serial, SIGNAL(readyRead()), m_ComThread, SLOT(Slot_RecieveDat()));
该方法,可把数据读取放到子线程中,但是经实测该方法串口总非正常卡死。
可以看出,多线程已经出来了,但是还是很卡,不知道什么原因。信号传的是读到的数组。
在线程中开启串口
这种方法在网上看到有人提,单个人认为纯属瞎扯。
本软件,最终会通过github开源社区共享,有意共同开发者,可留言。
目前版本软件下载地址:https://github.com/liuning19861103/HDNT-Center
持续更新中。。。。
有时间争取每天都写写,希望大家支持。