找回密码
 立即注册
收起左侧

尝试用多线程处理数据时,串口数据传输出现问题

12
回复
6964
查看
[复制链接]

尚未签到

来源: 2018-11-18 22:27:18 显示全部楼层 |阅读模式
5Qter豆
之前在主界面处理串口传输的数据发生界面卡死状态,经过大神指点,可以使用多线程解决问题,最近两天学习了多线程,并尝试编写,但效果不佳。编译倒是没有问题,但运行时出现QIODevice::read (QSerialPort): device not open的情况,添加了OPEN也不行。程序太多,放在附件上了。希望大佬们不吝赐教QAQ


附件: 您需要 登录 才可以下载或查看,没有帐号?立即注册
回复

使用道具 举报

累计签到:9 天
连续签到:1 天
2018-11-19 11:09:49 显示全部楼层
既然开辟线程就想多次执行,有可能线程执行一次就退出了,可以添加QEventLoop loop; loop.exec(); 防止线程退出
回复

使用道具 举报

尚未签到

2018-11-19 16:11:41 显示全部楼层
  1. #ifndef MYTHREAD_H
  2. #define MYTHREAD_H

  3. #include <QObject>
  4. #include <QThread>

  5. class MyThread : public QObject
  6. {
  7.     Q_OBJECT
  8. public:
  9.     explicit MyThread(QObject *parent = 0);
  10.     void read(QByteArray temp);
  11. signals:
  12.     void update(QByteArray temp);
  13. };


  14. #endif // MYTHREAD_H
复制代码
回复

使用道具 举报

尚未签到

2018-11-19 16:13:48 显示全部楼层
  1. #include "mymainwindow.h"
  2. #include "ui_mymainwindow.h"
  3. MyMainWindow::MyMainWindow(QWidget *parent) :
  4.     QMainWindow(parent),
  5.     ui(new Ui::MyMainWindow)
  6. {
  7.     ui->setupUi(this);
  8.     //查找可用的串口
  9.        foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
  10.        {
  11.            QSerialPort serial;
  12.            serial.setPort(info);
  13.            if(serial.open(QIODevice::ReadWrite))
  14.            {
  15.                ui->PortBox->addItem(serial.portName());
  16.                serial.close();
  17.            }
  18.        }
  19.        //设置波特率下拉菜单默认显示第0项
  20.        ui->BaudBox->setCurrentIndex(0);
  21.        //关闭发送按钮的使能
  22.        ui->sendButton->setEnabled(false);
  23.        qDebug() << tr("界面设定成功!");
  24.        thread = new QThread(this);
  25.        myThread = new MyThread;
  26.        myThread->moveToThread(thread);
  27.        thread->start();
  28.        connect(ui->pushButton, &QPushButton::pressed, myThread, &MyThread::drawImage);
  29.        connect(this, &MyMainWindow::update, thread, &MyThread::read);
  30.        connect(this, &MyMainWindow::destroyed, this, &MyMainWindow::dealClose);
  31. }
复制代码

void MyMainWindow::Read_Data()
{
    QByteArray buf;
    buf = serial->readAll();
    QDataStream out(&buf,QIODevice::ReadWrite);    //将字节数组读入
     while(!out.atEnd())
    {
        qint8 outChar = 0;
        out>>outChar;   //每字节填充一次,直到结束
        QString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0'));//十六进制的转换
        ui->textEdit->insertPlainText(str.toUpper());//大写
        ui->textEdit->insertPlainText(" ");//每发送两个字符后添加一个空格
        ui->textEdit->moveCursor(QTextCursor::End);
     }
     emit update(buf);
}
void MyMainWindow:n_openButton_clicked()
{
    if(ui->openButton->text()==tr("打开串口"))
    {
        serial = new QSerialPort;
        //设置串口名
        serial->setPortName(ui->ortBox->currentText());
        //打开串口
        serial->open(QIODevice::ReadWrite);
        //设置波特率
        serial->setBaudRate(ui->BaudBox->currentText().toInt());
        //设置数据位数
        switch(ui->BitNumBox->currentIndex())
        {
        case 8: serial->setDataBits(QSerialPort:ata8); break;
        default: break;
        }
        //设置奇偶校验
        switch(ui->arityBox->currentIndex())
        {
        case 0: serial->setParity(QSerialPort::NoParity); break;
        default: break;
        }
        //设置停止位
        switch(ui->StopBox->currentIndex())
        {
        case 1: serial->setStopBits(QSerialPort::OneStop); break;
        case 2: serial->setStopBits(QSerialPort::TwoStop); break;
        default: break;
        }
        //设置流控制
        serial->setFlowControl(QSerialPort::NoFlowControl);
        //关闭设置菜单使能
        ui->ortBox->setEnabled(false);
        ui->BaudBox->setEnabled(false);
        ui->BitNumBox->setEnabled(false);
        ui->arityBox->setEnabled(false);
        ui->StopBox->setEnabled(false);
        ui->openButton->setText(tr("关闭串口"));
        ui->sendButton->setEnabled(true);
        //连接信号槽
        QObject::connect(serial, &QSerialPort::readyRead, this, &MyMainWindow::Read_Data);
    }
    else
    {
        //关闭串口
        serial->clear();
        serial->close();
        serial->deleteLater();
        //恢复设置使能
        ui->ortBox->setEnabled(true);
        ui->BaudBox->setEnabled(true);
        ui->BitNumBox->setEnabled(true);
        ui->arityBox->setEnabled(true);
        ui->StopBox->setEnabled(true);
        ui->openButton->setText(tr("打开串口"));
        ui->sendButton->setEnabled(false);
    }
}
void MyMainWindow::dealClose()
{
    //退出子线程
   thread->quit();
   //当子线程结束后,完成相关的资源回收工作
   thread->wait();

   //因为(作为子线程加载)的类没有指定父对象, 所以在这里手动回收
   delete myThread;
}
回复

使用道具 举报

尚未签到

2018-11-19 16:14:42 显示全部楼层
  1. #include "mythread.h"
  2. #include <QElapsedTimer>

  3. MyThread::MyThread(QObject *parent) : QObject(parent)
  4. {

  5. }
  6. void MyThread::read()
  7. {
  8.         QByteArray buf=temp;
  9.         QByteArray kjs;
  10.         QPalette pal(ui->widget_1->palette());
  11.         QPalette pal2(ui->widget_2->palette());
  12.         QPalette pal3(ui->widget_3->palette());
  13.         QElapsedTimer t;
  14.         int i=0;
  15.             while(buf.contains("\001"))
  16.             {
  17.                for(i=0;i<buf.length()/4;i++)
  18.                 {
  19.                  //kjs = buf.left(buf.indexOf('#')-1);*/
  20.                  kjs = buf.left(4);
  21.                if(kjs.at(0)==0)//0X00表示停机
  22.                {
  23.                     pal.setColor(QPalette::Background, Qt::yellow); //设置背景黄色
  24.                     ui->widget_1->setAutoFillBackground(true);
  25.                     ui->widget_1->setPalette(pal);
  26.                     ui->widget_1->show();
  27.                     t.start();
  28.                     while(t.elapsed()<10000);//停机30秒
  29.                     {
  30.                         if(kjs.at(0)==0)
  31.                         {
  32.                             pal.setColor(QPalette::Background, Qt::red); //设置背景红色
  33.                             ui->widget_1->setAutoFillBackground(true);
  34.                             ui->widget_1->setPalette(pal);
  35.                             ui->widget_1->show();
  36.                         }
  37.                     }
  38.                 }
  39.                 else if(kjs.at(0)==1)
  40.                 {

  41.                     pal.setColor(QPalette::Background, Qt::green); //设置背景绿色
  42.                     ui->widget_1->setAutoFillBackground(true);
  43.                     ui->widget_1->setPalette(pal);
  44.                     ui->widget_1->show();
  45.                 }
  46.                 else
  47.                 {

  48.                     pal.setColor(QPalette::Background, Qt::gray); //设置背景灰色
  49.                     ui->widget_1->setAutoFillBackground(true);
  50.                     ui->widget_1->setPalette(pal);
  51.                     ui->widget_1->show();
  52.                 }
  53.                if(kjs.at(1)==0)//0X00表示停机
  54.                {

  55.                     pal2.setColor(QPalette::Background, Qt::yellow); //设置背景黄色
  56.                     ui->widget_2->setAutoFillBackground(true);
  57.                     ui->widget_2->setPalette(pal2);
  58.                     ui->widget_2->show();
  59.                     t.start();
  60.                     while(t.elapsed()<10000);//停机30秒
  61.                     {
  62.                         if(kjs.at(1)==0)
  63.                         {
  64.                             pal2.setColor(QPalette::Background, Qt::red); //设置背景红色
  65.                             ui->widget_2->setAutoFillBackground(true);
  66.                             ui->widget_2->setPalette(pal2);
  67.                             ui->widget_2->show();
  68.                         }
  69.                     }
  70.                 }
  71.                 else if(kjs.at(1)==1)
  72.                 {
  73.                     pal2.setColor(QPalette::Background, Qt::green); //设置背景绿色
  74.                     ui->widget_2->setAutoFillBackground(true);
  75.                     ui->widget_2->setPalette(pal2);
  76.                     ui->widget_2->show();
  77.                 }
  78.                 else
  79.                 {
  80.                     pal2.setColor(QPalette::Background, Qt::gray); //设置背景灰色
  81.                     ui->widget_2->setAutoFillBackground(true);
  82.                     ui->widget_2->setPalette(pal2);
  83.                     ui->widget_2->show();
  84.                 }
  85.                if(kjs.at(2)==0)//0X00表示停机
  86.                {
  87.                     pal3.setColor(QPalette::Background, Qt::yellow); //设置背景黄色
  88.                     ui->widget_3->setAutoFillBackground(true);
  89.                     ui->widget_3->setPalette(pal3);
  90.                     ui->widget_3->show();
  91.                     t.start();
  92.                     while(t.elapsed()<10000);//停机30秒
  93.                     {
  94.                         if(kjs.at(2)==0)
  95.                         {
  96.                             pal3.setColor(QPalette::Background, Qt::red); //设置背景红色
  97.                             ui->widget_3->setAutoFillBackground(true);
  98.                             ui->widget_3->setPalette(pal);
  99.                             ui->widget_3->show();
  100.                         }
  101.                     }
  102.                 }
  103.                 else if(kjs.at(2)==1)
  104.                 {
  105.                    qDebug() << tr("界面颜色设定成功!");
  106.                     pal3.setColor(QPalette::Background, Qt::green); //设置背景绿色
  107.                     ui->widget_3->setAutoFillBackground(true);
  108.                     ui->widget_3->setPalette(pal3);
  109.                     ui->widget_3->show();
  110.                 }
  111.                 else
  112.                 {
  113.                     pal3.setColor(QPalette::Background, Qt::gray); //设置背景灰色
  114.                     ui->widget_3->setAutoFillBackground(true);
  115.                     ui->widget_3->setPalette(pal3);
  116.                     ui->widget_3->show();
  117.                 }
  118.                  buf=buf.right(buf.size()-4*i);

  119.                }

  120.            }
  121.        buf.clear();
  122. }
复制代码
回复

使用道具 举报

尚未签到

2018-11-19 16:15:26 显示全部楼层
  1. #ifndef MYMAINWINDOW_H
  2. #define MYMAINWINDOW_H

  3. #include <QMainWindow>
  4. #include <QThread>
  5. #include <QDebug>
  6. #include <mythread.h>
  7. #include <QtSerialPort/QSerialPort>
  8. #include <QtSerialPort/QSerialPortInfo>
  9. namespace Ui {
  10. class MyMainWindow;
  11. }

  12. class MyMainWindow : public QMainWindow
  13. {
  14.     Q_OBJECT

  15. public:
  16.     explicit MyMainWindow(QWidget *parent = 0);
  17.     ~MyMainWindow();

  18. private slots:
  19.     void on_clearButton_clicked();
  20.     void on_sendButton_clicked();
  21.     void on_openButton_clicked();
  22.     void Read_Data();
  23.     void dealClose();
  24.     void on_checkBox_toggled(bool checked);

  25. private:
  26.     Ui::MyMainWindow *ui;
  27.     QSerialPort *serial;
  28.     MyThread *myThread;
  29.     QThread *thread;
  30.     QByteArray temp;
  31. };

  32. #endif // MYMAINWINDOW_H
复制代码
回复

使用道具 举报

尚未签到

2018-11-19 16:27:17 显示全部楼层
以上的程序是我的新改动,把图形界面刷新放在了次线程里,IO数据没出错,但是显示这个错误 error: 'class Ui::MyMainWindow' has no member named 'pushButton'
        connect(ui->pushButton, &QPushButton::pressed, myThread, &MyThread::drawImage);
                    ^
回复

使用道具 举报

尚未签到

2018-11-19 16:40:46 显示全部楼层
非白不是黑 发表于 2018-11-19 16:13
void MyMainWindow::Read_Data()
{
    QByteArray buf;

connect(ui->pushButton, &QPushButton::pressed, myThread, &MyThread::drawImage);这个是我复制错了没有这个~
回复

使用道具 举报

尚未签到

2018-11-19 17:05:45 显示全部楼层
思路有点乱,我再去学习一下线程,打扰各位了,不好意思QAQ
回复

使用道具 举报

累计签到:157 天
连续签到:1 天
2018-11-21 01:47:19 显示全部楼层
QT是不能在子线程里面更新界面的,也就是子线程不可以操作UI界面,我记得是这样的
回复

使用道具 举报

累计签到:375 天
连续签到:1 天
2019-1-12 09:00:37 显示全部楼层
楼主解决了吗?我这两天也在做这个,对线程有点懵
回复

使用道具 举报

尚未签到

2019-11-14 13:38:39 显示全部楼层
没有回答了吗,这个一收一发多线程了解一下
回复

使用道具 举报

累计签到:7 天
连续签到:5 天
2020-10-12 16:21:54 显示全部楼层
楼主解决了吗?我这两天也在做这个,对线程有点懵
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

公告
可以关注我们的微信公众号yafeilinux_friends获取最新动态,或者加入QQ会员群进行交流:190741849、186601429(已满) 我知道了