QT子线程读取串口数据并传到主线程

2023-05-16

《转载》

读取串口部分借鉴于Quartz010的文章《如何在QT中读取串口数据》

http://blog.csdn.net/zz709196484/article/details/66474917  这是博客网址

 

大致思路就是子线程去读取串口数据并传送到主线程,主线程在用widget对象画图实时显示波形图

 

一、在main.cpp定义一个自己封装的类myapp的对象w,在myapp界面中new出两个button按钮用于开关控制和


QComboBox复选框选择串口端口号,并定义出自己封装好的画图的类的对象,并设置布局。如下图:  

二、直接贴上代码

myapp.h

 

#ifndef MYAPP_H

#define MYAPP_H

#include <QWidget>
#include "widget.h"
#include <QTimer>
#include <QComboBox>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QDebug>
#include <QPalette>
#include <QTextEdit>
#include "mythread.h"

class myapp : public QWidget

{
    Q_OBJECT

public:

    explicit myapp(QWidget *parent = 0);

signals:
    void close_serial(char*);//向子线程传递信号关闭串口

public slots:
      void setplay(float data1);//传数据

      void on_btn_clicked();//打开串口按钮槽函数

      void closeit();//关闭按钮槽函数

    void get_value2()
    {
        w2->setvote(data, setval,statu);//设置画图状态及数据
    }


private:

    int  setval;

    float data;

    Widget *w2;

    QPushButton *btn,*closebtn;

    QComboBox *box;

    //QTextEdit *TB;

    QString port1;//串口端口号

    int statu,j;

    MyThread *mthread;//开辟子线程,以第三方库封装的模式
};


#endif // MYAPP_H

 


   

myapp.cpp  
#include "myapp.h"

#include <QVBoxLayout>

#include <QHBoxLayout>

#include "widget.h"

myapp::myapp(QWidget *parent) : QWidget(parent)

{
    setWindowTitle("心电图");

    //setMinimumSize(800,600);

    setFixedSize(1200,800);

    data = 0;

    setval = 1;

    //w1 = new Widget;

    w2 = new Widget;

    //w3 = new Widget;

    QPalette palette;

    palette.setBrush(QPalette::Background,QBrush(QPixmap("./Tim").scaled(this->size())));

    setPalette(palette);

    btn = new QPushButton("显示心电图");

    btn->setFixedSize(100,30);

    closebtn = new QPushButton("关闭");

    closebtn->setFixedSize(100,30);

    //TB= new QTextEdit();

    box = new QComboBox();

    box->setFixedSize(100,30);

    box->addItem("COM1");

    box->addItem("COM2");

    box->addItem("COM3");

    box->addItem("COM4");

    box->addItem("COM5");

    box->addItem("COM6");

    box->addItem("COM7");

    box->addItem("COM8");

    box->addItem("COM9");

    box->addItem("COM10");

    box->addItem("COM11");

    box->addItem("COM12");

    box->addItem("COM13");

    box->addItem("COM14");

    QHBoxLayout *hbox1 = new QHBoxLayout;

    hbox1->addWidget(btn);

    hbox1->addWidget(closebtn);

    hbox1->addWidget(box);

    QVBoxLayout *vbox1 = new QVBoxLayout;

    vbox1->addLayout(hbox1);

    //vbox1->addWidget(w1);

    vbox1->addWidget(w2);

    //vbox1->addWidget(TB);

    setLayout(vbox1);

    closebtn->setEnabled(false);

    connect(btn, SIGNAL(clicked()), this, SLOT(on_btn_clicked()));

    connect(closebtn,SIGNAL(clicked()),this,SLOT(closeit()));//监听两个按钮信号

}

void myapp::setplay(float data1)

{

    data = data1;

    setval = 10;

    get_value2();//调画图函数

}

void myapp::on_btn_clicked()

{

        statu = 1;

        btn->setEnabled(false);//设置按钮使能

        closebtn->setEnabled(true);

        qDebug()<<"open ok"<< endl;

        port1 = box->currentText();//获取端口号

        qDebug()<<port1<< endl;

        mthread =new MyThread(port1);

        connect(mthread,SIGNAL(setsenddata(float)),this,SLOT(setplay(float)),Qt::QueuedConnection);

	//接收子线程传输数据的信号

        mthread->start();//开启线程

}

void myapp::closeit()

{

    statu = 0; 

    closebtn->setEnabled(false);

    btn->setEnabled(true);

  connect(this,SIGNAL(close_serial(char*)),mthread,SLOT(close_mthread_serial(char*)));

    char *a="2";

    emit this->close_serial(a);//发送关闭的信号

    delete mthread;//销毁子线程

}

   

mythread.h

#ifndef MYTHREAD_H

#define MYTHREAD_H

#include <QObject>

#include <QDebug>

#include <QThread>

#include "qextserialbase.h"

#include "win_qextserialport.h"

#include <QPushButton>

class MyThread : public QThread

{

        Q_OBJECT

public:

    MyThread(QString port1);

    void run();

signals:

    void setsenddata(float data);//向主线程发送接收到的串口数据

public slots:

    void read_serial_data();//读取串口数据

    void close_mthread_serial(char *st);//关闭

private:

    Win_QextSerialPort *mycom;

    QString port;

    float data;

};

#endif // MYTHREAD_H

mythread.cpp

#include "mythread.h"


MyThread::MyThread(QString port1)

{

    port = port1;

}

void MyThread::run()

{

    //重写run()函数初始化串口

    mycom = new Win_QextSerialPort(port,QextSerialBase::EventDriven);//读取串口采用事件驱动模式

    mycom->open(QIODevice::ReadWrite);//读写方式打开

    mycom->setBaudRate(BAUD115200);//波特率

    mycom->setDataBits(DATA_8);//数据位

    mycom->setParity(PAR_NONE);//奇偶校验

    mycom->setStopBits(STOP_1);//停止位

    mycom->setFlowControl(FLOW_OFF);//控制位

    mycom->write("1");//向下位机发送1告诉它开始发送数据

    connect(mycom,SIGNAL(readyRead()),this,SLOT(read_serial_data()));//有数据就读

}

void MyThread::read_serial_data()

{

    if(mycom->bytesAvailable()>= 9)

    {

        qDebug()<<mycom->bytesAvailable() << endl;

        QByteArray temp;

        temp = mycom->read(9);//每串数据为9个字节

          union dat{

            char a[4];

            int x;

        };

        dat data_serial;

        data_serial.a[0] = 0;

        data_serial.a[1] = temp[8];

        data_serial.a[2] = temp[7];

        data_serial.a[3] = temp[6];

        data = data_serial.x*2.4/256/8288607*10000;//提取有效数据位,根据需要的数据设计的算法

        emit setsenddata(data);//发送数据给主线程

        qDebug() <<data ;

    //TB->insertPlainText(temp.toHex()+"  ");

      }

}

void MyThread::close_mthread_serial(char *st)

{

    mycom->write(st);//告知下位机读端已关闭

    qDebug() <<"close ok"<<st<<endl;

    mycom->close();//关闭子线程

}


   

widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPainter>
#include <QPen>
#include <QDebug>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0,float pwidth = 0.5);

    ~Widget();

    void paintEvent(QPaintEvent *event)
    {
        QPainter p(this);
        QPen pen;

        pen.setColor(QColor("green"));笔的颜色
        pen.setWidth(3);//笔的粗细
        p.setPen(pen);


        QFont font;//画text的大小
        font.setPixelSize(30);//请画家并给画家一支调好的笔
        p.drawLine(0, height()/2, width(), height()/2);//X轴
        p.drawLine(0, height()-5, 0, 5);//Y轴
        pen.setColor(QColor("red"));
        p.setPen(pen);
        p.setFont(font);
        p.drawText(QPoint(width()-15, height()/2-5), "S");//横坐标
        p.drawText(QPoint(10, 15), "mv");//纵坐标

#if 1
        pen.setColor(QColor("gray"));//网格
        pen.setWidth(1);
        p.setPen(pen);

        for(int i=10; i<width(); i+=10)
            p.drawLine(i, 0, i, height()-5);

        for(int j=10;j<height(); j+=10)
           p.drawLine(0, j, width(), j);

        pen.setColor(QColor("red"));
        pen.setWidth(10);

        p.setPen(pen);
        font.setPixelSize(16);
        p.setFont(font);
        p.drawText(QPoint(5, height()/2+15), "0");

        float a= 0.2;
        for(int k= 50;k<width();k+=50)
         {
            pen.setColor(QColor("white"));
            pen.setWidth(3);
            p.setPen(pen);
            p.drawLine(k, 0, k, height()-5);

            QString data = QString("%1").arg(a);
            pen.setColor(QColor("red"));
            pen.setWidth(10);
            p.setPen(pen);
            p.drawText(QPoint(k+5, height()/2+15), data);

            a=a+0.2;//横轴代表时间,每小格0.04s,每大格0.2s
        }

#endif
        p.translate(-fresh, 0);
        pen.setColor(QColor("red"));
        pen.setWidth(penwidth);

        p.setPen(pen);
        p.drawPath(path);//曲线图(波形)

        QPainter set_p(this);
        //QPen set_pen;

        set_p.translate(-set_fresh, 0);
//        set_pen.setColor(QColor("green"));
//        set_pen.setWidth(3);
//        set_p.setPen(set_pen);
//        set_p.drawPath(set_path);//参考线
//set_p.drawLine(QPoint(0, height()-setval), QPoint(width(), height()-setval));

    }

public slots:
    void draw()
    {
        if(statu == 1)
        {
           path.lineTo(QPoint(x+=penwidth, height()/2-vote));//每个数据的纵坐标路径

            if(x > width())//画满
            fresh+=penwidth;

//        set_path.lineTo(QPoint(set_x+=set_penwidth, height()-vote-10));
//        if(set_x > width())//画满
//            set_fresh+=set_penwidth;

            update();自动刷新

        }
    }

    void setvote(float value, int set,int status)//最关键的一个方法!!!要向显示电压信号直接调这个方法就可以了
    {
        vote = value;//传入的数据值
        setval = set;
        statu = status;
        draw();
    }


private:

    QPainterPath path, set_path;
    float fresh, set_fresh;//滚屏
    float penwidth, set_penwidth;//滚屏速度

    float x, set_x;
    int  setval,statu;
    float vote;
};

#endif // WIDGET_H

widget.cpp  
#include "widget.h"

#include <QPalette>

Widget::Widget(QWidget *parent, float pwidth)

    : QWidget(parent),penwidth(pwidth)
{
    QPalette pal(palette());
    pal.setColor(QPalette::Background, Qt::black);
    setAutoFillBackground(true);
    setPalette(pal);
    path.moveTo(QPoint(10, height()-5));
    set_path.moveTo(QPoint(10, height()-5));
    vote = 0;
    setval = height()-10;

    x = 0;
    set_x = 10;
    fresh = 0;
    set_fresh = 0;
    setFixedHeight(300);
}

Widget::~Widget()
{

}

   

三、串口代码就省略了,大家有需要看的可以去看我前面借鉴的大佬的博客

 


四、总结  

    之所以用线程读取数据,是因为一开始主线程读取数据的时候因为程序执行,也或许是画图影响反应事件  

驱动信号的原因,导致接收数据与下位机发送数据不匹配,会丢失一部分数据,也做过算法改进,仍然不行,  

后面采取开辟子线程读取串口,主线程显示,就没有这个问题了。总之在绘图上需要计算频率以及幅值,使图  

形清楚明了。  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QT子线程读取串口数据并传到主线程 的相关文章

  • E95-DTU(4G01-485)数传电台的特点及其应用详解

    1 E95 DTU 4G01 485简介 E95 DTU 4G01 485 是采用 4G CAT1 方案的云数传电台 xff0c 电台支持微信小程序简单配对使用 可以显现一对一 一对多 多对多等复杂应用场景 由于采用了云技术 xff0c 数
  • STM32学习笔记(串口、IAP)

    串口 xff1a 一 USART ITConfig USART1 USART IT TXE ENABLE xff1a 只要发送寄存器为空 xff0c 就会一直有中断 xff0c 因此 xff0c 要是不发送数据时 xff0c 把发送中断关闭
  • C++中容器的优点和缺点

    顺序容器 连续存储 array 优点 随机访问 一步直接得到数据的首地址的访问方式 方便 开销低 速度快 缺点 容量在定义时就确定了 不能够改变 中间删除和插入比较麻烦 需要后面的元素都移动 vector 优点 随机访问方便 可以自动扩容
  • 硬件切换485电路

    485接口具有很好的抗噪音抗干扰 长距离传输和多站能力特性 xff0c 使其为工控行业首选串行接口 485规定的电气特性为2线 xff0c 半双工多点通信 它的电气特性是有线缆两端的电压差来决定的 由于半双工模式 xff0c 通讯时需要切换
  • 802.11 Authentication and Association

    The 802 11 standard provides a method for supplying different levels of access to different nodes in a wireless local ar
  • 串口通信与波特率

    原文出自微信公众号 小小的电子之路 串口是串行接口的简称 xff0c 串行接口是采用串行通信方式的接口 串行通信是一种将需要传输的数据由低位到高位一位一位地在一条传输线上逐个传输的通信方式 一 串行通信的数据格式 首先来了解一下串行通信的数
  • 无人机方向控制pitch yaw roll是什么 .。欧拉角定义

    http blog csdn net yuzhongchun article details 22749521 三维空间的右手笛卡尔坐标如图1所示 图1 在航空中 xff0c pitch yaw roll如图2所示 pitch是围绕X轴旋转
  • Java学习记录

    Java学习记录 第一个Java程序tips Java对象与类变量类型构造方法创建对象源文件声明规则八大基本数据类型引用类型常量类型转换 第一个Java程序 span class token keyword public span span
  • 在Windows上搭建http服务器(lighttpd)------中秋节大礼

    今天中秋节 xff0c 也算忙了一大天了 窗外月圆 xff0c 我是不是也该吟诵 露从今夜白 xff0c 月是故乡明 这样的佳句呢 xff1f 还好 xff0c 过几天国庆就要回家了 今天继续来聊聊http服务器吧 xff01 在前面的文章
  • EPG简介

    一 EPG简介 电子节目指南 Electronic Program Guide xff0c EPG xff0c 是指在符合MPEG 2 13818 1 的TS传输流中插入DVB标准定义的业务信息 Service Information xf
  • ROS学习笔记(五)

    本文是关于第14讲的学习内容总结 所以要完成的目标是 xff0c 用C 43 43 代码编程实现服务端 Server的作用就是给海龟发布指令的 xff0c Client的作用是来控制Server是否要给海龟发布指令 老师的解释是Client
  • 433M数传电台窄带无线通讯技术手册

    一 模块介绍 1 1特点介绍 E3A DTU 500 是 一款 频率 433M 无 线数传电 台 xff08 同时 具有RS232 RS485 接口 xff09 xff0c 透明传输方式 xff0c 工作在 425 450 5MHz 频段
  • [C++]按字节读取文件

    一 背景 本文介绍了如何使用C 43 43 按字节读取 txt文件 本文第二部分为代码实例和对代码的解释 xff0c 第三部分为本文的参考文章 二 代码实例 span class token macro property span clas
  • [STL]priority_queue多种方式自定义排序

    一 背景 在做leetcode题目时很多题都需要使用优先队列 xff08 堆 xff09 xff0c 并需要使用自定义数据类型 自定义有限队列的排序方式 本文对priority queue的自定义排序方式做了总结 本文可能并不能覆盖所有自定
  • [Pyplot] 绘制三维散点图使用颜色表示数值大小

    一 摘要 在进行数据可视化时 xff0c 对于一元函数f x 61 y数据我们可以使用二维平面图显示 xff0c x轴表示自变量 xff0c y轴表示函数值 xff1b 对于二元函数f x y 61 z数据我们也可以使用三维图可视化 xff
  • [C++]<numeric>头文件介绍

    一 摘要 C 43 43 的 lt numeric gt 头文件中包含了一系列可用于操作数值序列 xff08 sequences of numeric value xff09 的函数 xff0c 通过修改函数的参数类型也可以将这些函数应用到
  • [算法] 使用位运算遍历集合的子集

    一 简介 对于使用状态压缩方法表示的集合A xff0c 如何遍历使用位运算遍历集合A的所有子集 二 代码与注释 0 符号假设 假设全集为S S的元素个数为n A为集合S的子集 可以使用状态压缩方法加位运算表示集合A 例如 xff1a S 6
  • [LaTeX|翻译]What are .cls and .sty files? How are they different?

    什么是 cls和 sty文件 xff1f 它们的区别是什么 xff1f What are cls and sty files How are they different 通常来讲 xff0c cls和 sty文件是用于增强LaTeX功能的
  • [Pyplot] 绘制3D曲面+自定义面片颜色

    一 背景 使用python 43 matplotlib实现绘制3D曲面 xff08 由多个小面片组成 xff09 xff0c 支持自定义面片颜色 xff1b 实现效果如图 a b 所示 xff1a a 使用面片法向作为面片颜色 b 使用默认
  • [STL]使用vector::erase对vector遍历删除

    在对vector中的元素进行遍历删除时遇到了一点问题 xff0c 查博客发现博客上并不靠谱 在此记录 xff0c 共同进步 vector循环遍历正确代码 span class token keyword for span span clas

随机推荐

  • 判断一个数是不是质数(素数),3种方式介绍

    本文参考博文判断一个数是不是质数 素数 xff0c 3种方式介绍 xff0c 原文章解释的已经很详细 xff0c 本问增加部分博主自己的理解 一 概念介绍 质数 xff1a 质数是指在大于1的自然数中 xff0c 除了1和它本身以外不再有其
  • Ubuntu/Arm安装Mysql报错:mysql-server 依赖于 mysql-server-5.7;然而:软件包 mysql-server-5.7 尚未配置。

    报错内容如下 xff1a dpkg 依赖关系问题使得 mysql server 的配置工作不能继续 xff1a mysql server 依赖于 mysql server 5 7 xff1b 然而 xff1a 软件包 mysql serve
  • E90-DTU系列无线数传电台网关与节点4gDTU通信教程

    以E90 DTU 400SL22 ETH 与E90 DTU 400SL22 为例实现网关与节点进行数据交换 xff0c 其它频段或功率的网关 节点 xff0c 其操作方式与该视频教程一致 第一步 安装网关 为网关安装天线电源模块 第二步 调
  • STM32实现将printf重定向到串口的3种方法

    STM32实现将printf重定向到串口的3种方法 目录 STM32实现将printf重定向到串口的3种方法一 使用MicroLib重定向printf二 不使用MicroLib重定向printf三 使用标准库自定义printf 函数到串口1
  • 时钟传感器—DS3231

    时钟传感器 DS3231 DS3231概述DS3231引脚DS3231寄存器DS3231 操作 DS3231概述 DS3231是一款高精度I2C实时时钟器件内部带温度补偿 闰年补偿提供两个可编程日历闹钟提供秒 分 时 星期 日期 月 年等信
  • C语言进阶

    C语言进阶 数据操作1 数据修饰 auto static register const volatile2 大端模式 小端模式 内存操作1 动态内存管理 xff08 堆区 heap xff09 malloc calloc realloc f
  • 虚拟机VMware:由于找不到vcruntime140_1.dll,无法继续执行代码

    最近换了台新电脑 xff0c 就开始安装虚拟机VMware xff0c 就发现虚拟机开机的时候 xff0c 弹出了一个错误 xff0c 下图 于是 xff0c 百度了一下缺少vcruntime140 1 dll xff0c 如何解决 解决方
  • Linux 基础

    Linux 基础 进程1 进程查看命令 ps pstree job2 进程的状态3 进程间的关系3 1 父进程与子进程 xff0c frok vfrok 3 2 进程组3 3 会话 4 进程间通信 IPC4 1 管道 pipe4 2 信号
  • STC8A 应用知识归纳

    STC8A 应用知识归纳 串口通信串口寄存器介绍功能 定时器 计数器定时器寄存器介绍 看门狗 xff1a 复位看门狗寄存器操作 外部中断ADCADC寄存器介绍 串口通信 每个串行口有两个数据缓冲器 xff08 SBUF xff09 一个移位
  • LoRa是什么

    LoRa是什么 LoRa是什么LoRa调制LoRa调制参数LoRa WAN 网络LoRa技术框图LoRa WAN网络组成LoRa终端设备划分成A B C三类 LoRa是什么 LoRa 是LPWAN通信技术中的一种 LoRa 是美国Semte
  • LoRa模块(内置MCU),亿百特E22-400T30S,广播监听、定点传输、中继组网

    LoRa模块 xff08 内置MCU xff09 xff0c 亿百特E22 400T30S xff0c 广播监听 定点传输 中继组网 配置说明广播监听 定点传输中继组网 配置说明 工作模式 模式M1 M0模式介绍模式0 传输模式0 0串口打
  • 定位——GNSS

    GNSS GNSS 即全球导航卫星系统 xff08 Global Navigation Satellite System xff09 是所有导航定位卫星的总称 xff0c 凡是可以通过捕获跟踪其卫星信号实现定位的系统 xff0c 均可纳入G
  • 惠普zbook15g2拆机换硅脂

    前几天电脑cpu温度居高不下 xff0c 就寻思着拆机清灰 43 替换硅脂 xff0c 结果网上到处找不到惠普zbook15的完整拆机指导 xff0c 唯一可用的某论坛关于zbook17的拆机分享看着很不舒服 xff0c 于是决定自己成功后
  • Camera-LIDAR 联合标定方法总结

    项目需要融合雷达和相机 xff0c 所以要做联合标定 xff0c 记录下收集的标定方法 一 总体标定步骤 标定就是找到雷达到相机的空间转换关系 xff0c 在不同的坐标系之间转换需要旋转矩阵 R 和平移矩阵 T xff0c 为后续的雷达和相
  • 52条SQL语句性能优化策略

    1 对查询进行优化 xff0c 应尽量避免全表扫描 xff0c 首先应考虑在 WHERE 及 ORDER BY 涉及的列上建立索引 2 应尽量避免在 WHERE 子句中对字段进行 NULL 值判断 xff0c 创建表时 NULL 是默认值
  • TCP/IP四层模型及各层协议首部详述

    1 OSI七层和TCP IP四层的关系 1 1 OSI引入了服务 接口 协议 分层的概念 xff0c TCP IP借鉴了OSI的这些概念建立TCP IP模型 1 2 OSI先有模型 xff0c 后有协议 xff0c 先有标准 xff0c 后
  • 位域的定义和使用

    位域 xff1a 有些信息在存储时 xff0c 并不需要占用一个完整的字节 xff0c 而只需占几个或一个二进制位 例如在存放一个开关量时 xff0c 只有0和1 两种状态 xff0c 用一位二进位即可 为了节省存储空间 xff0c 并使处
  • Makefile 的运行(六)

    一般来说 xff0c 最简单的就是直接在命令行下输入make命令 xff0c make命令会找当前目录的makefile来执行 xff0c 一切都是自动的 但也有时你也许只想让make重编译某些文件 xff0c 而不是整个工程 xff0c
  • FreeRTOS 任务优先级说明

    freeRTOS任务优先级与Unix进程优先级不同 FreeRTOS 任务优先 xff1a 任务优先级数值越小 xff0c 任务优先级越低 Unix 任务优先 xff1a 进程优先级数值越小 xff0c 进程优先级越高 下面对 FreeRT
  • QT子线程读取串口数据并传到主线程

    转载 读取串口部分借鉴于Quartz010的文章 如何在QT中读取串口数据 http blog csdn net zz709196484 article details 66474917 这是博客网址 大致思路就是子线程去读取串口数据并传送