使用多线程技术的Qt串口通信上位机

当使用单线程时,对于在UI界面中需要进行逻辑运算时,界面会发生卡顿甚至无响应情况,这时需要使用多线程技术,将串口数据采集以及数据处理代码放入子线程中运行。代码如下:

主线程:

#include "widget.h"
#include "ui_widget.h"

//QSerialPort serial; //串口对象定义
//Pulling PullingData; //结构体对象定义,PullingData用来储存拉力数据
QByteArray buffer; //定义额外的缓冲区,用来缓存串口发送来的数据

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    /*创建线程对象*/
    QThread *thread = new QThread; //创建子线程对象
    serialportmanager *worker = new serialportmanager(); //创建工作类对象
    worker->moveToThread(thread); //将工作 放入子线程中

    /*连接信号和槽*/

    connect(worker,&serialportmanager::newData_send,this,&Widget::newData_receive);
    connect(worker,&serialportmanager::newStringdata_send,this,&Widget::newStringdata_receive);

    /*启动线程*/
    thread->start(); 

    /*使工作的对象开始工作,槽函数连接*/
    connect(ui->openBt,&QPushButton::clicked,worker,&serialportmanager::serialport_set);
    connect(ui->closeBt,&QPushButton::clicked,worker,&serialportmanager::serialport_close);

    setWindowTitle("薄膜双向拉伸仪拉力采集系统");

    QStringList serialNamePort; //将串口名放入QStringList列表中

    serialPort = new QSerialPort(this); //创建一个新的QSerialPort对象,并将其指针赋值给serialPort变量

    //初始化QChart
    initChart();

    //connect(serialPort,SIGNAL(readyRead()),this,SLOT(serialPortReadyRead_Slot())); //当串行端口有数据可读时,readyRead信号会被发射,马上读取串口缓冲区数据

    foreach (const QSerialPortInfo &info , QSerialPortInfo::availablePorts()) {
        serialNamePort<<info.portName();
    }
    ui->serialCb->addItems(serialNamePort); //显示连接的可用串口


    timer = new QTimer(); //创建一个定时器对象,用于运行时间计时
    TimeRecord = new QTime(0,0,0);

    ui->lcdNumber->setDigitCount(6);
    ui->lcdNumber->setMode(QLCDNumber::Dec); //十进制
    ui->lcdNumber->setSegmentStyle(QLCDNumber::Flat); //扁平显示
    ui->lcdNumber_2->setDigitCount(6);
    ui->lcdNumber_2->setMode(QLCDNumber::Dec); //十进制
    ui->lcdNumber_2->setSegmentStyle(QLCDNumber::Flat); //扁平显示
    ui->lcdNumber_3->setDigitCount(8); //设置位数
    ui->lcdNumber_3->setSegmentStyle(QLCDNumber::Flat);
    ui->lcdNumber_3->display(TimeRecord->toString("hh:mm:ss"));

    //timer->setInterval(1); //定时周期
    connect(timer,SIGNAL(timeout()),this,SLOT(updateTime())); //测量时间记录定时器的槽函数,每隔1秒触发一次
}

Widget::~Widget()
{
    delete ui;
}


/*确认是否关闭程序*/
void Widget::closeEvent(QCloseEvent *ev){
    QMessageBox::Button btn = QMessageBox::question(this,"关闭窗口","您确定要关闭程序吗?");
    if(btn==QMessageBox::Yes){
        ev->accept();
    }
    else{
        ev->ignore();
    }
}

子线程 

#include "serialportmanager.h"

//Pulling PullingData; //结构体对象定义,PullingData用来储存拉力数据

serialportmanager::serialportmanager(QObject *parent): QObject(parent)
{
    serialPort = new QSerialPort(); //创建一个新的QSerialPort对象,并将其指针赋值给serialPort变量

    //QStringList serialNamePort; //将串口名放入QStringList列表中

    connect(serialPort, &QSerialPort::readyRead, this, &serialportmanager::serialPortReadyRead_Slot); //使serialPortReadyRead_Slot自动读取数据
}


/*串口参数设置*/
void serialportmanager::serialport_set()
{
    /*将接收到的串口属性写入串口*/
    serialPort->setPortName("COM3");
    serialPort->setBaudRate(QSerialPort::Baud115200);  //试验时,直接设置窗口
    serialPort->setDataBits(QSerialPort::Data8);
    serialPort->setStopBits(QSerialPort::OneStop);
    serialPort->setParity(QSerialPort::NoParity);

    if (serialPort->open(QIODevice::ReadWrite)) {
        qDebug() << "Serial port opened successfully";
    } else {
        qDebug() << "Failed to open serial port";
    }

}

void serialportmanager::serialPortReadyRead_Slot()
{
    QByteArray buf = serialPort->readAll(); //读取串口信息
    buffer.append(buf);

    int index;
    while((index=buffer.indexOf("\r\n"))!=-1)
    {
        QByteArray message = buffer.left(index);
        buffer.remove(0,index+2);
        QStringList floatStrings = QString::fromUtf8(message).split(",");
        //emit newStringdata_send(floatStrings);
        if(floatStrings.size()==2)
        {
            float float_Vol[2];
            for(int i=0;i<2;i++)
            {
                float_Vol[i] = floatStrings[i].toFloat();//转化为浮点数
            }
            PullingData.channel_1 = float_Vol[0];
            PullingData.channel_2 = float_Vol[1];
            qDebug()<<PullingData.channel_1<<PullingData.channel_2;
            emit newData_send(PullingData.channel_1,PullingData.channel_2);

        }
        else
        {
            qDebug()<<"INVALID DATA FORMAT";
        }
    }
}

//关闭串口
void serialportmanager::serialport_close()
{
    if (serialPort->isOpen()) {
        serialPort->close();
        serialPort->clear();
        qDebug() << "Serial port closed";
    }
}

运行结果如下,测量数据流畅显示

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值