基于VS2022+Qt5+C++的串口助手开发

news2024/12/23 22:26:29

目录

一、前言 

二、环境准备

三、创建QT串口项目 

​编辑 四、串口项目实现

1.ui界面设计

2.添加QT串口模块

3.功能实现 

①串口扫描

 ②波特率、停止位等设置

③接收数据

④发送数据

五、最终效果

六、总结


一、前言 

如果有人之前看过我文章的话应该知道,我之前用python+pyqt5写过一版串口助手。没看过的也不要紧,我贴在下面,大家可以浅浅看一下。最近由于工作需要,开始接触C++以及QT,就想着能不能用C++和QT重写一下串口助手。于是就有了这篇文章单纯记录一下,接下来听我娓娓道来~

基于Python+Pycharm+PyQt5的串口助手开发_基于python+pyqt5的串口助手-CSDN博客文章浏览阅读2.3k次,点赞43次,收藏30次。本期带来的基于PyQt5的串口助手开发,实现串口通信。_基于python+pyqt5的串口助手https://blog.csdn.net/weixin_44765053/article/details/135347552?spm=1001.2014.3001.5502

二、环境准备

操作系统:win 10

编辑器:VS2022、QT5.14

语言及版本:C++

最终实现的功能:串口选择、串口状态显示、发送数据、接收数据、数据显示(ASCII)

首先假设你已经安装好了VS以及QT(如果不清楚的比较多的话麻烦评论区留言,后续我出一篇文章详细介绍),那么如何在VS里面新建QT项目并编写代码呢?我们需要安装Qt VS Tools插件

①打开Visual Studio点击右上角的扩展,然后点击管理扩展。

 ②搜索并安装"Qt Visual Studio Tools"插件,然后重启Visual Studio。

③重启后依次点击,扩展-->Qt VS Tools-->Qt Versions ④点击path,选择你QT安装时候编译路径,即qmake.exe所在的目录。例如我这边显示D:\QT\5.14.0\msvc2017_64,但其实qmake.exe是在bin文件下面

三、创建QT串口项目 

①打开VS中,选择创建新项目。在搜索框输入Qt Widget Application,选择Qt Widget Application点击下一步。

② 修改项目名称以及项目位置,然后点击创建。

③一直点击默认的next直至以下界面,我们选择QWidget。

 四、串口项目实现

1.ui界面设计

在右侧点击Form Files,然后双击ui文件进行界面设计。这里我们就偷个小懒,直接沿用pyqt项目的ui界面。

PS:如果这里出现无法打开ui文件的,可以《扩展》-> 《Qt vs tools》-> 《options》-> 《Qt》-> 《general》 -> 《Qt Designer》 -> 《run in detached window》 -> true

2.添加QT串口模块

在Qt中,串口通信的核心是QSerialPortQSerialPortInfo这两个类。

  • QSerialPort:这个类提供了与串口进行通信的功能。它可以用于打开、关闭串口,设置串口的参数如波特率、数据位、停止位等,还可以通过这个类发送和接收数据。QSerialPort是串口助手中最关键的类,它让我们能够轻松地与硬件进行数据通信。

  • QSerialPortInfo:这个类用于提供系统中可用的串口信息。通过它,我们可以获取到当前系统中所有可用串口的名称、描述信息等。它主要用于列出可用串口供用户选择。

但是当我们直接#include <QSerialPort>、#include <QSerialPortInfo>时候会报错,需要将其添加到Qt Modules。依次点击,项目-->serial和属性-->Qt Project Settings-->Qt Modules-->添加serial port


 

3.功能实现 

主要功能包括:

  • 串口扫描:定时每秒扫描现存串口列表,并将其添加到ComboBox。
  • 波特率设置:提供一个下拉列表,用户可以选择常用的波特率。
  • 数据接收:接收数据,并以十六进制显示。
  • 数据发送:包括十六进制发送、定时发送数据等待。

①串口扫描

#include "serial2.h"

SerialPortScanner::SerialPortScanner(QComboBox* comboBox) // 构造函数,传入一个QComboBox指针作为参数
    : m_comboBox(comboBox), m_timer(new QTimer(this)) // 初始化成员变量m_comboBox, m_timer
{
    // 创建一个定时器,每1000毫秒(1秒)触发一次
    connect(m_timer, &QTimer::timeout, this, &SerialPortScanner::scanSerialPorts); // 连接定时器的超时信号和scanSerialPorts槽函数
    m_timer->start(1000); // 启动定时器
}

void SerialPortScanner::scanSerialPorts()
{
    QList<QString> m_newports;  // 新的串口列表
    // 获取可用的串口列表
    QList<QSerialPortInfo> portList = QSerialPortInfo::availablePorts();

    // 遍历串口列表,将每个串口的名称添加到QComboBox中
    for (const QSerialPortInfo& portInfo : portList) {
        m_newports.append(portInfo.portName());  // 将串口名称添加到列表中
    }
    if (m_newports != m_portNames) {
        m_portNames = m_newports; // 更新旧的串口列表
        m_comboBox->clear(); // 清空QComboBox
        m_comboBox->addItems(m_portNames); // 将新的串口列表添加到QComboBox中

    }
}

效果如下:

 

 ②波特率、停止位等设置

#include "serial2.h"

SerialPortSet::SerialPortSet(Ui::serial2Class* ui, QObject* parent)  // 构造函数
    : QObject(parent),
    serialPort(new QSerialPort(this)),
    m_ui(ui)
{

}

// 获取波特率
QSerialPort::BaudRate SerialPortSet::getBaudRate(const QString& baudRateStr) {  
    static const QMap<QString, QSerialPort::BaudRate> baudRateMap = {  
        {"1200", QSerialPort::Baud1200},  // 1200
        {"2400", QSerialPort::Baud2400},  // 2400
        {"4800", QSerialPort::Baud4800},  // 4800
        {"9600", QSerialPort::Baud9600},  // 9600
        {"19200", QSerialPort::Baud19200},  // 19200
        {"38400", QSerialPort::Baud38400}, // 38400
    };
    return baudRateMap.value(baudRateStr, QSerialPort::Baud9600); // 返回对应的波特率
}
// 获取数据位
QSerialPort::DataBits SerialPortSet::getDataBits(const QString& dataBitsStr) {
    static const QMap<QString, QSerialPort::DataBits> dataBitsMap = {
        {"5", QSerialPort::Data5},  // 5
        {"6", QSerialPort::Data6},  // 6
        {"7", QSerialPort::Data7}, // 7
        {"8", QSerialPort::Data8}  // 8
    };
    return dataBitsMap.value(dataBitsStr, QSerialPort::Data8);  // 返回对应的数据位
}

// 获取停止位
QSerialPort::StopBits SerialPortSet::getStopBits(const QString& stopBitsStr) {
    static const QMap<QString, QSerialPort::StopBits> stopBitsMap = {
        {"1", QSerialPort::OneStop},  // 1
        {"1.5", QSerialPort::OneAndHalfStop},  // 1.5
        {"2", QSerialPort::TwoStop}  // 2
    };
    return stopBitsMap.value(stopBitsStr, QSerialPort::OneStop);  // 返回对应的停止位
}

// 获取奇偶校验位
QSerialPort::Parity SerialPortSet::getParityBits(const QString& parityStr) {
    static const QMap<QString, QSerialPort::Parity> parityMap = {
        {"NONE", QSerialPort::NoParity},  // 无
        {"ODD", QSerialPort::OddParity},  // 奇
        {"EVEN", QSerialPort::EvenParity}  // 偶
    };
    return parityMap.value(parityStr, QSerialPort::NoParity); // 返回对应的奇偶校验位
}


void SerialPortSet::open_Port()
{
   
        // 获取各项设置
        QSerialPort::BaudRate baudRate = getBaudRate(m_ui->comboBox_Baud->currentText());  // 获取波特率
        QSerialPort::DataBits dataBits = getDataBits(m_ui->comboBox_Data->currentText());  // 获取数据位
        QSerialPort::StopBits stopBits = getStopBits(m_ui->comboBox_Stop->currentText());  // 获取停止位
        QSerialPort::Parity parity = getParityBits(m_ui->comboBox_Check->currentText());  // 获取校验位

        // 设置串口参数
        serialPort->setPortName(m_ui->comboBox_COM->currentText());  // 设置串口名称
        serialPort->setBaudRate(baudRate);  // 设置波特率
        serialPort->setDataBits(dataBits);  // 设置数据位
        serialPort->setStopBits(stopBits);  // 设置停止位
        serialPort->setParity(parity);  // 设置校验位

        if (serialPort->open(QIODevice::ReadWrite)) {  // 尝试打开串口
            m_ui->pushButton_Open->setText("关闭串口");  // 更新按钮文本

        }
        else {
            // 如果无法打开串口,弹出错误信息
            QMessageBox::warning(m_ui->label, "错误", "无法打开串口: " + serialPort->errorString());  // 弹出警告框
        }
    }
}

效果如下: 

 

③接收数据

void SerialPortCommunication::readData()  // 当有数据可读时,读取数据
{
	if (m_serialPort->isOpen())
	{  // 如果串口打开,则读取数据
		QByteArray data = m_serialPort->readAll();  // 读取数据
	
		m_ui->textEdit_receive->insertPlainText(QString::fromUtf8(data));  // 将数据插入到文本框中

	}
	m_ui->textEdit_receive->moveCursor(QTextCursor::End);
}

④发送数据

void SerialPortCommunication::sendData()  // 发送数据函数
{
    QString inputData = m_ui->textEdit_Send->toPlainText();  // 获取发送数据
    if (m_serialPort->isOpen() && !inputData.isEmpty()) {  // 如果串口打开且发送数据不为空,则发送数据
	    QByteArray byteArray;  // 创建字节数组
        byteArray = inputData.toUtf8();
        m_serialPort->write(byteArray);  // 发送数据
}

由于篇幅有限,以上只贴了主要功能实现代码。

五、最终效果

 老样子,我们来看看最终与其他串口通信效果。

QT串口助手

 

六、总结

通过本文的详细讲解,我们完成了一个基于VS2022和Qt5的串口助手的开发。该串口助手实现了串口扫描、开关串口、数据接收和数据发送等核心功能,能够帮助用户方便地与串口设备进行通信和调试。

在开发过程中,我们深入了解了QSerialPortQSerialPortInfo类的应用,通过它们轻松实现了串口的操作和管理。同时,本文还详细介绍了如何在Qt中设计用户界面,使我们的工具不仅功能完善,而且使用起来简洁直观。

希望通过这篇文章,你能够更好地掌握Qt开发与串口通信相关的知识,并将这些技能应用到实际项目中。如果你在开发过程中遇到任何问题,欢迎在评论区交流讨论。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# 窗体通过调用webapi往U9C系统创建请购单

C# 窗体通过调用webapi往U9C系统创建请购单 窗体图片 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System…

Java面试题———分布式篇

目录 1、什么是分布式事务 2、什么是CAP理论 3、为什么分布式系统中无法同时AC 4、什么是BASE理论 5、分布式事务的解决方案有哪些 6、Seata的架构是什么 7、XA模式的工作流程是什么 8、AT模型的工作原理是什么 9、TCC模型的工作原理是什么 1、什么是分布式事务 在分…

Aix 清理 iscsi 残留盘

目录 一、前提概要 二、解决方法 一、前提概要 Aix 环境下挂载 ISCSI 盘&#xff0c;需要结合 LVM 进行挂盘。这个过程比较复杂&#xff0c;在使用过程中极易出现残留。 本篇博客介绍的就是如何清理 Aix 下 ISCSI 的残留。 二、解决方法 主要步骤和需要执行的命令如下面的流…

ModuleNotFoundError: No module named ‘pywin32_bootstrap

ModuleNotFoundError: No module named ‘pywin32_bootstrap 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发者社…

Prompt Engineering 完整指南

Prompt Engineering 完整指南 Prompt Engineering 是与 AI 模型进行交互的关键技术&#xff0c;通过精心设计的指令&#xff08;prompt&#xff09;引导模型生成高质量的输出。本文将详细介绍 prompt 设计的最佳实践、基本原则以及高级技巧&#xff0c;帮助你在实际应用中最大化…

vscode添加宏定义

1 起因 在用vscode看项目代码时&#xff0c;如果源文件中的代码块被某个宏定义给包裹住了&#xff0c;则在vscode的默认配置下&#xff0c;不会高亮显示这块被包裹住的代码&#xff0c;如下图中229行开始的代码被STM32F40_41xxx所控制&#xff0c;没有高亮显示。 由于STM32F4…

SSH升级至9.8p1

此前写过一个有关升级ssh的帖子&#xff0c;当时的情况是ssh5.3p1 升级到 ssh8.0 p1 下面是链接&#xff1a;https://blog.csdn.net/zhurobert/article/details/103193205?spm1001.2014.3001.5501 此次升级的环境是CentOS-7.6.1810 ssh版本7.4p1 准备好升级包后上传至/home…

Ubuntu 下 NFS服务开启

NFS&#xff08;Network File System&#xff0c;网络文件系统&#xff09;是一种基于TCP/IP传输的网络文件系统协议&#xff0c;它允许网络中的计算机之间通过TCP/IP网络共享资源。简单来说NFS就是一个文件传输的协议&#xff0c;可以用来传输文件。 使用如下命令安装 NFS 服务…

怎样选择开放式耳机好?精选五大实力出众爆款安利!

开放式耳机通过空气传导技术传递声音&#xff0c;不需要插入耳道&#xff0c;这种设计不仅保护了耳朵&#xff0c;还确保了佩戴的稳定性和舒适性。与传统的入耳式耳机相比&#xff0c;开放式耳机有助于保持耳道清洁&#xff0c;并允许用户在享受音乐的同时保持对周围环境的警觉…

Ps:首选项 - 增效工具

Ps菜单&#xff1a;编辑/首选项 Edit/Preferences 快捷键&#xff1a;Ctrl K Photoshop 首选项中的“增效工具” Plugins选项卡允许用户管理 Photoshop 中的插件和扩展功能&#xff0c;通过调整这些设置&#xff0c;用户可以根据自己的需求来扩展 Photoshop 的功能&#xff0c…

前端post传入拿到数据,后端报null,并且能够添加或者编辑成功

检查conterller层注解接到实体类的注解是不是没加&#xff08; RequestBody &#xff09; 后端&#xff1a; 前端&#xff1a; 那么就看注解&#xff0c;因为contrller层有个接值注解&#xff08; RequestBody &#xff09;

Why Does ChatGPT Fall Short in Providing Truthful Answers?

文章目录 题目摘要简介相关工作模型和数据集结果事实性背后的能力提高 QA 的事实性结论 题目 为什么 ChatGPT 无法提供真实的答案&#xff1f; 论文地址:https://arxiv.org/abs/2304.10513 摘要 ChatGPT 等大型语言模型的最新进展已显示出影响人类生活各个方面的巨大潜力。然而…

18.token刷新拦截器

问题 上一篇博客中提到使用redis来存用户的登录信息&#xff0c;解决了session不共享问题。 在拦截器中&#xff0c;重新设置了用户信息的有效期&#xff0c;保证只要用户一直请求就永不过期。但是并不是每个请求都会经过拦截器的&#xff08;因为登录拦截器&#xff0c;不是…

多个文件上传

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

【书生大模型实战营】LMDeploy 量化部署进阶实践

LMDeploy 量化部署进阶实践 【书生大模型实战营】LMDeploy 量化部署进阶实践任务环境将大模型封装为API接口服务以命令行形式连接API服务器以Gradio网页形式连接API服务器 LMDeploy Lite和InternLMkv cacheW4A16 模型量化和部署W4A16 量化 KV cacheKV cache 量化 LMDeploy与Int…

【JavaEE】MyBatis 实战指南:从 JDBC 到高效数据库操作的进阶教程

目录 MyBatis 操作数据库JDBC 操作⽰例回顾什么是MyBatis?MyBatis⼊⻔1. 准备⼯作2. 配置数据库连接字符串3. 写持久层代码4. 单元测试使用MyBatis可能遇到的问题 MyBatis的基础操作打印⽇志参数传递增(Insert)返回主键 删(Delete)改(Update)查(Select)起别名结果映射开启驼峰…

vue使用高德获取当前地区天气

1、收件箱 | 高德控制台 (amap.com) 首先打开高德开放平台注册一下 2、创建一个应用获取到key后面获取天气的时候 请求接口的时候会用到key 2.1.1 创建应用的时候注意类型选成天气 2.1.2 创建完成之后就点添加key 然后选择web服务就行 3、可以调取天气接口 天气查询-基础 API…

https握手过程详解

https握手过程详解 上一篇《HTTPS通讯全过程》中https握手过程实际上还有更多的细节&#xff0c;为什么会这样设计呢&#xff1f;是因为一开始将握手过程时&#xff0c;吧步骤说的太详细会导致更难理解惹。所以我就先在上一篇把部分细节忽略&#xff0c;把原来几步的过程先简化…

洛杉物理服务器怎么样?

洛杉矶作为美国科技和互联网的重要中心&#xff0c;物理服务器的质量通常非常高&#xff0c;可以提供卓越的性能、强大的安全性、多样的配置选项和专业的服务支持。以下是对洛杉物理服务器的详细介绍。 1. 优质的性能 稳定的网络连接&#xff1a;洛杉矶物理服务器位于先进的数据…

CASS11时空版 全新升级支持多版本CAD软件下载License使用

南方数码地形地籍成图软件CASS&#xff0c;经过二十余年的发展&#xff0c;市场和技术积累丰厚&#xff0c;用户遍及国内外测绘地理信息相关行业。软件销量和市场占有率持续领先&#xff0c;是业内应用广&#xff0c;服务优的软件品牌。 南方数码深刻理解信息化测绘的内…