Qt 线程串口

文章目录

  • ui设置
  • 创建线程函数
  • 初始串口
  • run函数接收发送数据
    • 读取数据
    • 处理读取的数据
    • 写入数据
    • 写入启动的命令
  • 主线程

在这里插入图片描述

ui设置

在这里插入图片描述

创建线程函数

#include <QObject>
#include <QThread>
#include <QSerialPort>
#include <QSerialPortInfo>

class SerialPort : public QThread
{
    Q_OBJECT
public:
    SerialPort();
    ~SerialPort();

public:
    void InitPort(QString PortName);
    void wirteData();//写入数据
    void ProcessReceivedData(QByteArray);//处理数据
    quint8  CalculateChecksum(const QByteArray& data);//计算校验和
signals:
    void SendData(float m_fVol[10]);//发送数据

protected:
    void run();

public slots:
    void readData();
    void handleBytesWritten(quint64 bytes);

public:
    QSerialPort* port;
    QStringList serialPortNameList;//串口列表
    float m_fVol[10];//电压
    QByteArray m_receivedBuffer[4096];
    QByteArray receivedData;//接收到的数据
};

初始串口

void SerialPort::InitPort(QString PortName)
{
    // 查询所有串口设备
//    QList<QSerialPortInfo> serialList = QSerialPortInfo::availablePorts();

//    foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
//    {
//        serialPortNameList << info.portName();
//        qDebug()<<"serialPortName: "<<info.portName();
//    }


    //qDebug()<<PortName;
    port->setPortName(PortName);
    port->setBaudRate(19200, QSerialPort::AllDirections);//波特率
    port->setDataBits(QSerialPort::Data8);             // 数据位为8位
    port->setFlowControl(QSerialPort::NoFlowControl);  // 无流控制
    port->setParity(QSerialPort::NoParity);            // 无校验位
    port->setStopBits(QSerialPort::OneStop);           // 一位停止位

    if (port->open(QIODevice::ReadWrite))
    {
        qDebug() << "Port have been opened";
        wirteData();
    }
    else
    {
        qDebug() << "open it failed";

        return;
    }
}

run函数接收发送数据

void SerialPort::run()
{
    connect(port, &QSerialPort::bytesWritten, this, &SerialPort::handleBytesWritten);//向串口写数据
    connect(port, &QSerialPort::readyRead, this, &SerialPort::readData);//向串口读数据
    exec();
}

读取数据

void SerialPort::readData()
{
    if (port->bytesAvailable() > 0)
        {
            qint64 nReadSize = 4096;
            if(port->isOpen())
            {
                QByteArray receivedData = port->read(nReadSize);

                //qDebug()<<receivedData.size();
                if (receivedData.size() >= 26)
                {
                    ProcessReceivedData(receivedData); // 处理接收到的数据
                }
            }
        }
}

处理读取的数据

void SerialPort::ProcessReceivedData(QByteArray receivedData)
{
    //qDebug()<<receivedData;
    //qDebug()<<receivedData.size();

    if(receivedData.size() >= 26)
    {
        if (receivedData.at(0) == 'U' && receivedData.at(receivedData.length() - 1) == '\xAA')
        {
            // 检验校验和
            //qDebug()<<receivedData;
            QByteArray dataContent = receivedData.mid(1, 23);

            quint8 receivedChecksum = static_cast<quint8>(receivedData.at(24)); // 获取接收到的校验和
            quint8 calculatedChecksum = CalculateChecksum(dataContent); // 计算校验和

            if(receivedChecksum ==calculatedChecksum )//数据正确
            {
                quint16 wT;
                for (int j = 0; j < 10; ++j)
                {
                    wT = static_cast<quint8>(receivedData[j*2+2]);
                    wT <<= 8;
                    wT += static_cast<quint8>(receivedData[j*2+1]);
                    m_fVol[j] = wT * 5000.0f / 1024;
                    emit SendData(m_fVol);
                }

            }


        }
        else
        {
            receivedData.remove(0, 1);
        }

    }

}

quint8 SerialPort::CalculateChecksum(const QByteArray &data)
{
    quint8 checksum = 0;

    for (int i = 0; i < data.size(); ++i)
    {
        checksum += static_cast<quint8>(data.at(i));
    }

    return checksum;
}

写入数据

void SerialPort::handleBytesWritten(quint64 bytes)
{
    if (bytes > 0)
    {
        // 数据写入成功
        //qDebug()<<bytes;
        connect(port, &QSerialPort::readyRead, this, &SerialPort::readData);//向串口读数据
    } else {
        // 数据写入失败
        wirteData();//再次写入
    }
}

写入启动的命令

void SerialPort::wirteData()
{
    if (port->isOpen())
    {
        QByteArray data;
        data.append(char(0x55)); // 添加数据 0x55 到数组
        data.append(char(0x01)); // 添加数据 0x01 到数组
        data.append(char(0x01)); // 添加数据 0x01 到数组
        data.append(char(0x00)); // 添加数据 0x00 到数组
        data.append(char(0x00)); // 添加数据 0x00 到数组
        data.append(char(0x00)); // 添加数据 0x00 到数组
        data.append(char(0x02)); // 添加数据 0x02 到数组
        data.append(char(0xAA)); // 添加数据 0xAA 到数组
        //qDebug()<<char(0x55);
        port->clear(QSerialPort::Output); // 清除输出缓冲区
        port->write(data);                // 写入数据到串口
    }
}

主线程

#include <QWidget>
#include "serialport.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

public slots:
    void ReadData(float m_fVol[10]);


public:
    SerialPort* m_Port;

private slots:
    void on_pushButton_clicked();
};
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    m_Port =new SerialPort();
    ui->comboBox->addItem("COM1");
    ui->comboBox->addItem("COM2");
    ui->comboBox->addItem("COM3");
    ui->comboBox->addItem("COM4");
    ui->comboBox->addItem("COM5");
    ui->comboBox->addItem("COM6");
    ui->comboBox->addItem("COM7");
    ui->comboBox->addItem("COM8");


}

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

void Widget::ReadData(float m_fVol[10])
{

    QTextCursor tc = ui->textBrowser->textCursor();
    tc.movePosition(QTextCursor::End);
    //qDebug()<<m_fovl;
    for(int i=0;i<10;i++)
    {
         tc.insertText(QString::number(m_fVol[i])+"mv\n");
         tc.insertText("\n");
    }

    tc.insertText("----------\n");


    ui->textBrowser->moveCursor(QTextCursor::End);
}




void Widget::on_pushButton_clicked()
{
    if(ui->pushButton->text() == "连接")
    {
        m_Port->InitPort(ui->comboBox->currentText());
        connect(m_Port,&SerialPort::SendData,this,&Widget::ReadData);
        m_Port->start();
        ui->pushButton->setText("断开连接");
    }
    else {
        m_Port->port->close();
        disconnect(m_Port, &SerialPort::SendData, this, &Widget::ReadData); // 断开连接
        ui->pushButton->setText("连接");
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/139226.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode刷题详解——解数独

1. 题目链接&#xff1a;37. 解数独 2. 题目描述&#xff1a; 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能…

微信小程序_02

能够使用WXML模版语法渲染页面结构 数据绑定 1、数据绑定的基本原则 在data中定义数据在WXML中使用数据 2、在data中定义页面的数据 ​ 在页面对应的.js文件中&#xff0c;把数据定义到data对象中即可&#xff1a; Page({data:{//字符串类型的数据info:init data,//数组类…

【python自动化】Playwright基础教程(七)Keyboard键盘

【python自动化】Playwright基础教程(七)Keyboard键盘 playwright模拟键盘操作 键盘事件提供了用于管理虚拟键盘的API&#xff0c;高级API是keyboard.type()&#xff0c;它使用的是原始字符再页面上生成对应的keydown 、 keypress / input 和 keyup 事件。 模拟真实键盘操作进行…

【网络奇幻之旅】那年我与大数据的邂逅

&#x1f33a;个人主页&#xff1a;Dawn黎明开始 &#x1f380;系列专栏&#xff1a;网络奇幻之旅 ⭐每日一句&#xff1a;循梦而行&#xff0c;向阳而生 &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️ 文章目录 &#x1f4…

Python GUI - Tkinter 添加应用程序图标(程序左上角)

将ico图标文件放在py文件同级目录&#xff0c;然后加上以下代码 root.iconbitmap("./test.ico")

Linux centos安装SQL Server数据库,结合cpolar内网穿透实现公网访问

文章目录 前言1. 安装sql server2. 局域网测试连接3. 安装cpolar内网穿透4. 将sqlserver映射到公网5. 公网远程连接6.固定连接公网地址7.使用固定公网地址连接 前言 简单几步实现在Linux centos环境下安装部署sql server数据库&#xff0c;并结合cpolar内网穿透工具&#xff0…

西部数码的域名如何实现DDNS功能

功能简介&#xff1a; 动态域名解析&#xff08;Dynamic DNS&#xff0c;简称DDNS&#xff09;可以让用户使用固定的域名来访问动态IP地址&#xff0c;解决因IP地址变化造成服务无法访问的情况。 本文将介绍如何使用西部数码的API实现DDNS功能&#xff0c;使您的域名始终指向您…

MySQL索引优化

EXPLAIN详解 优先了解EXPLAIN&#xff0c;文章链接在下面。 EXPLAIN详解&#xff08;MySQL&#xff09; 索引数据结构 MySQL主要有两种结构&#xff1a;hash索引和BTree索引&#xff0c;InnoDB引擎默认是BTree索引。 索引分类 聚簇索引&#xff1a; 指索引的键值的逻辑顺…

乡镇村污水处理智慧水务智能监管平台,助力污水监管智慧化、高效化

一、背景与需求 随着城市化进程的加速&#xff0c;排放的污水量也日益增加&#xff0c;导致水污染严重。深入打好污染防治攻坚战的重要抓手&#xff0c;对于改善城镇人居环境&#xff0c;推进城市治理体系和治理能力现代化&#xff0c;加快生态文明建设&#xff0c;推动高质量…

Facebook个人主页和公共主页的区别

Facebook个人主页和公共主页是两种不同类型的页面&#xff0c;它们在功能、用途和管理方面上都是存在着一些明显的区别。本文小编则对他们的区别介绍一下。 首先&#xff0c;个人主页是供普通用户使用的&#xff0c;用于展示个人信息和与朋友、家人保持联系。个人主页通常包括…

阿里云国际站:专有网络vpc

文章目录 一、阿里云专有网络的概念 二、专有网络的组成部分 三、专有网络的优势 一、阿里云专有网络的概念 专有网络VPC是阿里云用户在云上创建的私有网络&#xff0c;用户自己掌控&#xff0c;可以自定义IP地址段、创建交换机、配置路由表和网关等操作。用户可以在自己的专…

VR建筑仿真场景编辑软件有助于激发创作者的灵感和创造力

随着VR虚拟现实技术的不断发展和普及&#xff0c;VR虚拟场景编辑器逐渐成为了VR场景开发重要工具。它对于丰富和完善VR虚拟现实内容的创建和呈现具有重要的意义&#xff0c;为我们的工作和教学带来了许多变化和可能性。 首先&#xff0c;VR虚拟场景编辑器对于提升用户体验具有重…

ChatGPT重磅升级 奢侈品VERTU推出双模型AI手机

2023年11月7日,OpenAI举办了首届开发者大会,CEO Sam Altman(山姆奥尔特曼)展示了号称“史上最强”AI的GPT-4 Turbo。它支持长达约10万汉字的输入,具备前所未有的长文本处理能力,使更复杂的互动成为可能。此外,GPT-4 Turbo还引入了跨模态API支持,可以同时处理图片、视频和声音,从…

springboot运维篇--springboot项目打包

1.springboot项目jar方式部署 直接使用idea 直接使用命令 跳过测试用例快速打包 mvn clean -D skipTests package将这个应用打成jar包&#xff0c;直接使用java-jar的命令执行 需要注意的是&#xff0c;需要 jar 命令行启动需要依赖 Maven 插件的支持&#xff0c;必须确认在…

软考网络工程师知识点总结(三)

目录 41、特殊地址 42、子网划分 43、CIDR路由汇聚 44、IP数据报 45、ARP协议 46、ICMP协议 47、IPv6地址表示及类型 48、IPv6地址前缀 49、IPv4过渡IPv6 50、UDP传输层协议 51、TCP传输层协议 52、TCP头部中常见字段的含义&#xff1a; 53、TCP的流量控制和拥塞控…

浏览器插件实现国税网自动登录,以及解决浏览器记住密码会自动填充表单无法修改的问题

公司的做账系统&#xff0c;用户在系统里设置保存了国税网的账号密码以后&#xff0c;下次点击进入国税网&#xff0c;能够直接进入国税系统。 之前的解决方案是pupptteer模拟登录一遍拿到cookie等登录凭证后&#xff0c;保存到数据库&#xff0c;然后插件请求接口拿到cookie&…

Illumination Adaptive Transformer

Abstract. 现实世界中具有挑战性的照明条件&#xff08;低光、曝光不足和曝光过度&#xff09;不仅会产生令人不快的视觉外观&#xff0c;还会影响计算机视觉任务。现有的光自适应方法通常单独处理每种情况。更重要的是&#xff0c;它们中的大多数经常在 RAW 图像上运行或过度…

Linux进程地址空间

文章目录 1.程序地址空间回顾2.进程地址空间 1.程序地址空间回顾 我们在讲C语言的时候&#xff0c;老师给大家画过这样的空间布局图 可是我们对他并不理解&#xff01; 来段代码感受一下: #include <stdio.h> #include <unistd.h> #include <stdlib.h> in…

麒麟KYLINOS中使用备份还原系统

原文链接&#xff1a;麒麟KYLINOS中使用备份还原系统 hello&#xff0c;大家好啊&#xff0c;今天给大家带来麒麟KYLINOS备份还原的第二篇文章&#xff0c;使用备份还原系统&#xff0c;主要通过麒麟KYLINOS系统自带的备份还原工具&#xff0c;将之前备份的系统文件进行还原&am…

SecureCRT 超时自动断开连接问题解决方法

很多人在使用SecureCRT时&#xff0c;会遇到这种情况&#xff1a;SecureCRT 超时自动断开连接&#xff0c;这种情况会给工作带来很多不便&#xff0c; 比如在做数据库还原操作时&#xff0c;连接突然断掉了&#xff0c;会导致还原操作失败&#xff0c;很是令人困扰。 那么我们…