百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

如何使用QT编写自己的串口调试助手软件

bigegpt 2024-08-30 12:54 5 浏览

最近在学习qt,边学边写,最近自己写了个串口调试助手和网络调试助手,在此做个串口调试助手开发的分享和记录。


QT 串口调试助手

主要功能:串口数据收发、显示,定时发送,接收数据保存、文件发送,定时更新串口列表和异常检测,不同编码、进制转换等。

1 环境与工具

  • PC Windows10
  • QT 5.12.0

2 设计过程

QT实现串口通信主要是利用QT自带的串口类和函数,在.pro文件中添加"QT += serialport",然后在项目文件中包含头文件(#include QSerialport),我们就可以在项目中使用QSerialPort来读取和发送串口数据了。

主要过程:实例化串口——>搜索可用串口——>打开串口——>设置串口参数——>读取数据或发送数据。

2.1 新建项目与界面布局

新建串口调试助手的项目,由于QT还没玩熟,这里就直接使用QT Designer进行ui界面的绘制和布局。布局过程不再赘述,根据自己的需要放置适当的控件即可,最好对控件对象也重命名一下,完成布局后的最终效果如图:

2.2 程序设计

下面对主要的几个过程和程序做个说明,具体过程就不再贴出来了,了解大概过程后就可以根据个人需要来新增其他功能了。
1、 首先对界面的按钮、组合选择框等控件进行一些初始化(更改背景、颜色这些也可以直接通过QT Designer ui界面右键点击控件,通过“改变样式表”等来设置)。
2、实例化对象,关联一些信号和槽信号。在这里,我们使用foreach函数来搜索和解析目前该PC上可用的端口信息,然后把解析出来的端口添加到组合选择框里面,后面就可以去从下拉框选择要打开的串口了。主要代码如下:

     //查找可用的串口
foreach(const QSerialPortInfo &info,     QSerialPortInfo::availablePorts())
    {
        QSerialPort SerialPort;
        SerialPort.setPort(info);   //解析串口信息
        if (SerialPort.open(QIODevice::ReadWrite))
        {
            SerialPortName.push_back(SerialPort.portName());
            SerialPort.close();
        }
    }
    
    //把端口添加到组合框
 for (int i = 0; i < SerialPortName.size(); ++i)
 {
   ui->SelectCOM_comboBox>addItem(SerialPortName.at(i)); 
 }

3、打开和设置串口
在这里,我使用点击按钮来触发打开串口事件,在打开按钮的槽函数中进行串口打开就可以。打开以后进行串口参数的设置,如波特率、校验位、停止位等。这些参数从界面的设置读取,这里给出主要代码,参数直接指定,从窗口获取参数也是同理,只是需要从ui界面获取参数。

** 这里要注意:务必要先打开串口,然后在进行参数设置,否则很有可能出现读取不到数据的情况。(很明显的特征就是,串口设备拔掉插上,打开串口也读不到数据或者乱码,拿其他软件打开读一下数据,再切回自己的程序也就可以读到数据)。**

 SerialPort->setPortName(SelectCOM_comboBox->currentText()); //获取串口端口号
   if(!(SerialPort->isOpen())) //串口没有打开
   {
    if (!SerialPort->open(QIODevice::ReadWrite))
    {
        QMessageBox::information(this, "提示", "串口连接失败,请检查设备是否正确连接");
    }
    else
    {
        //QMessageBox::information(this, "提示", SelectCOM_comboBox->currentText() + tr("连接成功"));
        SerialPort->setBaudRate(115200);  //设置波特率115200
        SerialPort->setDataBits(QSerialPort::Data8);   //8位数据位
        SerialPort->setParity(QSerialPort::NoParity);  //无校验位
        SerialPort->setStopBits(QSerialPort::OneStop);  //1位停止位
        SerialPort->setFlowControl(QSerialPort::NoFlowControl); //默认无流控

        SerialPort->clearError();
        SerialPort->clear();
       
        //关联串口数据读取槽函数
        connect(SerialPort, &QSerialPort::readyRead, this, &setDialog::slot_serialReadData); 
        //关联串口连接异常处理槽函数
        connect(SerialPort, static_cast<void (QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),  this, &setDialog::handleSerialError);
    }
   }

4 、读取数据
串口有数据发过来时会触发串口读信号(readyRead),所以读数据就要将readyRead绑定到读取槽函数,然后直接使用串口的readAll()或者readData()等函数来读取串口数据就可以,读到的数据根据需要进行转码,然后进行显示、保存等操作。主要代码如下:
绑定信号和槽:connect(SerialPort, &QSerialPort::readyRead, this, &setDialog::slot_serialReadData);

QByteArray receiveDate;
    QTextCodec *tc = QTextCodec::codecForName("GBK");  //编码转换,必须转换编码,否则乱码

    while(!SerialPort->atEnd()){
        receiveDate = SerialPort->readAll();
    }

    if (!receiveDate.isEmpty())
    {
        QString strBuf=tc->toUnicode(receiveDate);         //编码转换,必须转换编码,否则乱码
        COMRXtextBrowser->append(strBuf);
    }
    receiveDate.clear();

5、发送数据

要发送串口数据也很简单,使用write()函数即可,前提是串口要先打开和设置好参数。下面是主要代码:

    QTextCodec *gbk = QTextCodec::codecForName("GBK");  
    //从Ui文本输入框读取数据
    QString strSendMessage = ui->Send_textEdit->toPlainText(); 

    if(ui->TXHex_checkBox->isChecked())
     {
        strSendMessage=hexToString(strSendMessage); //hex格式转化为Qstring
     }

    if(ui->TXEnter_checkBox->isChecked()) //添加换行/回车
     {
        strSendMessage+="\r\n";
     }

    QByteArray sendBytes;
    sendBytes.append(gbk->fromUnicode(strSendMessage)); //编码转换,必须转换编码,否则乱码
    if(SerialPort->isWritable())
    {
        SerialPort->write(sendBytes);
        TXCounter+=sendBytes.size();
        ui->TXCountlabel->setText(tr("TX:%1").arg(TXCounter));
    }
    else{
        QMessageBox::information(this,"Tip","串口未打开!");
    }

6、 关闭串口

关闭串口可以手动通过点击按钮关闭或者在窗口关闭时去关闭串口,为避免出现异常,窗口关闭时把串口也关闭了。关闭串口也很简单,使用close()函数就可以。代码如下:

    if(SerialPort->isOpen())
    {
        SerialPort->close();
        ui->SeralOperat_pushButton->setText(tr("打开串口"));
        QMessageBox::information(this,"提示","串口连接断开");
    }

7、其他

串口还有很多功能,这里就不一一列举,需要可以去QT助手搜索有哪些方法,如何使用等。
最终实现效果如图:

3 注意事项和说明

1、在工程文件.pro中要添加QT += serialport,否则编译会报错
2、串口要先打开,然后进行参数设置,否则容易出现读取不到数据的情况
3、 串口数据读取的数据需要进行转码(尤其是和硬件平台通信时),否则中文字符会乱码
4、在对ui控件进行操作前,务必要先执行设置ui函数(ui->setupUi(this)),否则执行会出错。

写的调试软件还有定时更新串口列表,保存接收数据,发送文件,定时发送等功能,在此不一一详述了。我把完整源码奉上,需要参考的伙伴可以直接下载源码,注释写的也很清楚。
源码请在资源页下载:

https://mp-new.csdn.net/mp_download/manage/download/UpDetailed

关于如何把自己写的程序打包成软件,请参考:

https://mp-new.csdn.net/mp_blog/creation/editor/116641563

本人也是刚学习QT,欢迎大家交流、留下宝贵意见。

相关推荐

Java 泛型大揭秘:类型参数、通配符与最佳实践

引言在编程世界中,代码的可重用性和可维护性是至关重要的。为了实现这些目标,Java5引入了一种名为泛型(Generics)的强大功能。本文将详细介绍Java泛型的概念、优势和局限性,以及如何在...

K8s 的标签与选择器:流畅运维的秘诀

在Kubernetes的世界里,**标签(Label)和选择器(Selector)**并不是最炫酷的技术,但却是贯穿整个集群管理与运维流程的核心机制。正是它们让复杂的资源调度、查询、自动化运维变得...

哈希Hash算法:原理、应用(哈希算法 知乎)

原作者:Linux教程,原文地址:「链接」什么是哈希算法?哈希算法(HashAlgorithm),又称为散列算法或杂凑算法,是一种将任意长度的数据输入转换为固定长度输出值的数学函数。其输出结果通常被...

C#学习:基于LLM的简历评估程序(c# 简历)

前言在pocketflow的例子中看到了一个基于LLM的简历评估程序的例子,感觉还挺好玩的,为了练习一下C#,我最近使用C#重写了一个。准备不同的简历:image-20250528183949844查...

55顺位,砍41+14+3!季后赛也成得分王,难道他也是一名球星?

雷霆队最不可思议的新星:一个55号秀的疯狂逆袭!你是不是也觉得NBA最底层的55号秀,就只能当饮水机管理员?今年的55号秀阿龙·威金斯恐怕要打破你的认知了!常规赛阶段,这位二轮秀就像开了窍的天才,直接...

5分钟读懂C#字典对象(c# 字典获取值)

什么是字典对象在C#中,使用Dictionary类来管理由键值对组成的集合,这类集合被称为字典。字典最大的特点就是能够根据键来快速查找集合中的值,其键的定义不能重复,具有唯一性,相当于数组索引值,字典...

c#窗体传值(c# 跨窗体传递数据)

在WinForm编程中我们经常需要进行俩个窗体间的传值。下面我给出了两种方法,来实现传值一、在输入数据的界面中定义一个属性,供接受数据的窗体使用1、子窗体usingSystem;usingSyst...

C#入门篇章—委托(c#委托的理解)

C#委托1.委托的定义和使用委托的作用:如果要把方法作为函数来进行传递的话,就要用到委托。委托是一个类型,这个类型可以赋值一个方法的引用。C#的委托通过delegate关键字来声明。声明委托的...

C#.NET in、out、ref详解(c#.net framework)

简介在C#中,in、ref和out是用于修改方法参数传递方式的关键字,它们决定了参数是按值传递还是按引用传递,以及参数是否必须在传递前初始化。基本语义对比修饰符传递方式可读写性必须初始化调用...

C#广义表(广义表headtail)

在C#中,广义表(GeneralizedList)是一种特殊的数据结构,它是线性表的推广。广义表可以包含单个元素(称为原子),也可以包含另一个广义表(称为子表)。以下是一个简单的C#广义表示例代...

「C#.NET 拾遗补漏」04:你必须知道的反射

阅读本文大概需要3分钟。通常,反射用于动态获取对象的类型、属性和方法等信息。今天带你玩转反射,来汇总一下反射的各种常见操作,捡漏看看有没有你不知道的。获取类型的成员Type类的GetMembe...

C#启动外部程序的问题(c#怎么启动)

IT&OT的深度融合是智能制造的基石。本公众号将聚焦于PLC编程与上位机开发。除理论知识外,也会结合我们团队在开发过程中遇到的具体问题介绍一些项目经验。在使用C#开发上位机时,有时会需要启动外部的一些...

全网最狠C#面试拷问:这20道题没答出来,别说你懂.NET!

在竞争激烈的C#开发岗位求职过程中,面试是必经的一道关卡。而一场高质量的面试,不仅能筛选出真正掌握C#和.NET技术精髓的人才,也能让求职者对自身技术水平有更清晰的认知。今天,就为大家精心准备了20道...

C#匿名方法(c#匿名方法与匿名类)

C#中的匿名方法是一种没有名称只有主体的方法,它提供了一种传递代码块作为委托参数的技术。以下是关于C#匿名方法的一些重要特点和用法:特点省略参数列表:使用匿名方法可省略参数列表,这意味着匿名方法...

C# Windows窗体(.Net Framework)知识总结

Windows窗体可大致分为Form窗体和MDI窗体,Form窗体没什么好细说的,知识点总结都在思维导图里面了,下文将围绕MDI窗体来讲述。MDI(MultipleDocumentInterfac...