Qt/C++ 个人开源项目#串口助手(源码与发布链接)

一、项目概述

该串口助手工具基于Qt/C++开发,专为简化串口通信调试与开发而设计,适合新手快速上手。工具具有直观的用户界面和丰富的功能,旨在帮助用户与串口设备建立可靠通信,便于调试、数据传输和分析。

二、主要功能

波特率:支持常见波特率(如9600、115200等),并支持自定义。

数据位:提供从5到8位的选择。

校验位:支持无校验、奇校验、偶校验等。

停止位:提供1位或2位选择。

接收数据:支持实时显示从串口设备接收的数据,用户可以选择显示格式(如十六进制、ASCII等)。

发送数据:用户可以通过界面输入并发送数据,支持单次发送和定时发送,便于测试连续传输。

  1. 串口自动检测与连接串口助手具备自动检测功能,可以自动识别当前系统中的串口设备。用户通过界面选择设备并一键连接,简化了配置流程。

  2. 串口参数配置用户可以根据实际需求设置以下参数:

  3. 数据收发

三、软件安装与使用

1. 使用

该串口助手提供了编译好的发布包,用户可以自行下载可以直接启动应用。在应用界面中,选择要连接的串口设备,配置相关串口参数,点击“连接”即可开始数据通信。数据收发、等功能可以根据需求自由选择和配置。

四、下载链接

发布包下载链接:串口调试助手.zip

https://pan.baidu.com/s/12RQ_fxREV7zOH-MwqIUzlQ?pwd=cedu

五、源码分享

#ifndef SERIALWORKER_H
#define SERIALWORKER_H#include <QThread>
#include <QSerialPort>
#include <QQueue>
#include <QMutex>
#include <QWaitCondition>
#include <QString>#define tc(a) QString::fromLocal8Bit(a)class SerialWorker : public QThread
{Q_OBJECTpublic:SerialWorker();~SerialWorker();void setupPort(const QString &portName, qint32 baudRate, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, QSerialPort::Parity parity);void addDataToSend(const QByteArray &data);inline void unpackData(const QByteArray& receivedData);public slots:void startWorker(); // 用于替代start(),因为start()是QThread的成员函数void stop();signals:void dataReceived(const QByteArray &data);void errorOccurred(const QString &error);// 新增信号void informations(int index, const QString &msg); // 用于发送一般信息void warnings(int index, const QString &msg);     // 用于发送警告信息void errors(int index, const QString &msg);       // 用于发送错误信息void connected(int index, bool success);          // 用于发送连接状态protected:void run() override;private:QSerialPort *serialPort;QQueue<QByteArray> sendQueue;QMutex mutex;QWaitCondition waitCondition;bool running;// 串口参数QString portName;qint32 baudRate;QSerialPort::DataBits dataBits;QSerialPort::StopBits stopBits;QSerialPort::Parity parity;
};#endif // SERIALWORKER_H
#include "serialworker.h"
#include <QDebug>
#include <QEventLoop>
#include <QTimer>
SerialWorker::SerialWorker(): serialPort(nullptr), running(false)
{
}SerialWorker::~SerialWorker()
{stop();if (serialPort && serialPort->isOpen()) {serialPort->close();}delete serialPort;
}void SerialWorker::setupPort(const QString &portName, qint32 baudRate, QSerialPort::DataBits dataBits, QSerialPort::StopBits stopBits, QSerialPort::Parity parity)
{this->portName = portName;this->baudRate = baudRate;this->dataBits = dataBits;this->stopBits = stopBits;this->parity = parity;
}void SerialWorker::addDataToSend(const QByteArray &data)
{QMutexLocker locker(&mutex);sendQueue.enqueue(data);waitCondition.wakeOne();
}void SerialWorker::unpackData(const QByteArray &receivedData)
{emit dataReceived(receivedData);
}void SerialWorker::startWorker()
{if(!isRunning())start();}void SerialWorker::stop()
{QMutexLocker locker(&mutex);running = false;waitCondition.wakeAll();
}void SerialWorker::run()
{serialPort = new QSerialPort();// 设置串口参数serialPort->setPortName(portName);serialPort->setBaudRate(baudRate);serialPort->setDataBits(dataBits);serialPort->setStopBits(stopBits);serialPort->setParity(parity);int index = 0;  // 可以根据需要设置适当的索引值if (!serialPort->open(QIODevice::ReadWrite)) {emit errors(index, serialPort->errorString());emit connected(index, false);delete serialPort;serialPort = nullptr;running=false;return;}running=true;emit connected(index, true);  // 成功连接emit informations(index, tc("串口已打开"));QEventLoop eventLoop;QTimer timer;timer.setInterval(10); // 设置定时器的间隔,控制事件循环的频率connect(&timer, &QTimer::timeout, &eventLoop, &QEventLoop::quit);timer.start();while (running){QByteArray data;{QMutexLocker locker(&mutex);if (!sendQueue.isEmpty()) {data = sendQueue.dequeue();}}if (!data.isEmpty()){serialPort->write(data);if (!serialPort->waitForBytesWritten()) {emit errors(index, serialPort->errorString());} else {emit informations(index, tc("数据已发送[%1]").arg(QString::fromUtf8(data)));}}if (serialPort->waitForReadyRead(10)) { // 使用一个小的超时时间QByteArray receivedData = serialPort->readAll();emit dataReceived(receivedData);}// 处理事件循环,避免阻塞信号槽机制eventLoop.exec();}serialPort->close();emit informations(index, tc("串口已关闭"));emit connected(index, false);  // 断开连接delete serialPort;serialPort = nullptr;
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "serialworker.h"
namespace Ui {
class MainWindow;
}
enum RunTimeStatus
{Error,            ///< 错误信息Warning,          ///< 警告信息Information,     ///< 常规信息
};
class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();void writeRunTimeMsgs(const QString&msg,const int level);void createSendLinEdit();// 创建配置文件的函数,如果文件不存在则创建void createConfigFile(const QString &fileName, const QStringList &values);// 读取配置文件的函数QStringList readConfigFile(const QString &fileName);private slots:void on_openButton_clicked();void on_closeButton_clicked();void onDataReceived(const QByteArray &data);void onRespondNormalMessage(const int index,const QString&msg);void onRespondWarningMessage(const int index,const QString&msg);void onRespondErrorMessage(const int index,const QString&msg);void onRespondSerialConnectState(const int index,const bool state);void on_clearRecvButton_clicked();private:Ui::MainWindow *ui;SerialWorker *serialwork;
};#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSerialPortInfo>
#include <QDateTime>
#include <QDebug>
#include <QSettings>
#include <QFile>
#include <QTextCodec>
#include "timesendwidget.h"
# define tc(a) QString::fromLocal8Bit(a)
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow), serialwork(new SerialWorker())
{ui->setupUi(this);// 示例值列表QStringList values;values << tc("极客晨风") << tc("1327666247@qq.com")  << tc("微信公众号:码上Qt")<<tc("欢迎关注") ;createConfigFile("config.ini",values);//绘制发送界面createSendLinEdit();// 填充串口选项// 遍历当前系统可用的所有串口,并将它们的名字添加到端口名的QComboBox中foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {ui->portNameComboBox->addItem(info.portName());}// 填充波特率选项// 将常用的波特率值添加到波特率的QComboBox中,数据以“字符串-枚举值”形式存储ui->baudRateComboBox->addItem("9600", QSerialPort::Baud9600);        // 波特率9600ui->baudRateComboBox->addItem("19200", QSerialPort::Baud19200);      // 波特率19200ui->baudRateComboBox->addItem("38400", QSerialPort::Baud38400);      // 波特率38400ui->baudRateComboBox->addItem("115200", QSerialPort::Baud115200);    // 波特率115200ui->baudRateComboBox->setCurrentIndex(0);  // 设置默认选项为第一个(9600)// 填充数据位选项// 将串口通信中常用的数据位数添加到数据位的QComboBox中,数据以“字符串-枚举值”形式存储ui->dataBitsComboBox->addItem("5", QSerialPort::Data5);   // 5个数据位ui->dataBitsComboBox->addItem("6", QSerialPort::Data6);   // 6个数据位ui->dataBitsComboBox->addItem("7", QSerialPort::Data7);   // 7个数据位ui->dataBitsComboBox->addItem("8", QSerialPort::Data8);   // 8个数据位(通常最常用)ui->dataBitsComboBox->setCurrentIndex(3);  // 设置默认选项为8个数据位(索引3)// 填充停止位选项// 将串口通信中常用的停止位添加到停止位的QComboBox中,数据以“字符串-枚举值”形式存储ui->stopBitsComboBox->addItem("1", QSerialPort::OneStop);            // 1个停止位ui->stopBitsComboBox->addItem("1.5", QSerialPort::OneAndHalfStop);   // 1.5个停止位(较少使用)ui->stopBitsComboBox->addItem("2", QSerialPort::TwoStop);            // 2个停止位ui->stopBitsComboBox->setCurrentIndex(0);  // 设置默认选项为1个停止位// 填充奇偶校验选项// 将串口通信中常用的奇偶校验方式添加到奇偶校验的QComboBox中,数据以“字符串-枚举值”形式存储ui->parityComboBox->addItem("None", QSerialPort::NoParity);          // 无校验(最常用)ui->parityComboBox->addItem("Even", QSerialPort::EvenParity);        // 偶校验ui->parityComboBox->addItem("Odd", QSerialPort::OddParity);          // 奇校验ui->parityComboBox->addItem("Mark", QSerialPort::MarkParity);        // 标志位校验(较少使用)ui->parityComboBox->addItem("Space", QSerialPort::SpaceParity);      // 空格位校验(较少使用)ui->parityComboBox->setCurrentIndex(0);  // 设置默认选项为无校验connect(serialwork, &SerialWorker::dataReceived, this, &MainWindow::onDataReceived);// 连接信号与槽connect(serialwork, &SerialWorker::informations, this, &MainWindow::onRespondNormalMessage);connect(serialwork, &SerialWorker::warnings, this, &MainWindow::onRespondWarningMessage);connect(serialwork, &SerialWorker::errors, this, &MainWindow::onRespondErrorMessage);connect(serialwork, &SerialWorker::connected, this, &MainWindow::onRespondSerialConnectState);}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::writeRunTimeMsgs(const QString &msg, const int level )
{QString Level;switch (level) {case Error:      Level=tc("[ ***错误信息*** ]");break;case Warning:    Level=tc("[ ***警报信息*** ]");break;case Information:Level=tc("[ ***正常信息*** ]");break;}ui->statusBar->showMessage(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss ") +Level+msg );
}void MainWindow::createSendLinEdit()
{for(auto val:readConfigFile("config.ini")){TimeSendWidget *sendWidget=new TimeSendWidget;sendWidget->setLinText(val);connect(sendWidget,&TimeSendWidget::sendLineData,[=](const QByteArray &data ){if(ui->openButton->isEnabled()){writeRunTimeMsgs(tc("串口未打开,无法发送"),Error);return ;}if(data.isEmpty()){writeRunTimeMsgs(tc("信息为空,拒绝发送"),Warning);return ;}//主界面显示if(ui->isShowSendButton->isChecked()){QString msg;if(ui->isShowTimeButton->isChecked())msg.append(QDateTime::currentDateTime().toString("hh:mm:ss.(zzz)  "));msg.append(tc("发送  "));msg.append(ui->isShowHexButton->isChecked()? data.toHex(' ').toUpper():QString::fromLocal8Bit(data));ui->receiveTextEdit->append(msg);}//更新显示信息ui->sendByte->setValue(ui->sendByte->value()+data.size());ui->sendFram->setValue(ui->sendFram->value()+1);serialwork->addDataToSend(data);});ui->sendGroup->layout()->addWidget(sendWidget);}}void MainWindow::createConfigFile(const QString &fileName, const QStringList &values)
{// 检查文件是否存在QFile file(fileName);if (file.exists())return;QSettings settings(fileName, QSettings::IniFormat);settings.setIniCodec(QTextCodec::codecForName("UTF-8"));// 根据传入的值动态创建组和键值对int groupIndex = 1;for (const QString &value : values){QString groupName = QString("%1").arg(groupIndex);settings.beginGroup(groupName);settings.setValue(QString("%1").arg(groupIndex), value);settings.endGroup();groupIndex++;}}QStringList MainWindow::readConfigFile(const QString &fileName)
{QStringList iniinfors;QSettings settings(fileName, QSettings::IniFormat);settings.setIniCodec(QTextCodec::codecForName("UTF-8"));// 获取所有组并排序QStringList groups = settings.childGroups();groups.sort();for (const QString &group : groups){settings.beginGroup(group);QStringList keys = settings.childKeys();for (const QString &key : keys)iniinfors<< settings.value(key).toString();settings.endGroup();}return  iniinfors;
}
void MainWindow::on_openButton_clicked()
{QString portName = ui->portNameComboBox->currentText();qint32 baudRate = ui->baudRateComboBox->currentData().toInt();QSerialPort::DataBits dataBits = static_cast<QSerialPort::DataBits>(ui->dataBitsComboBox->currentData().toInt());QSerialPort::StopBits stopBits = static_cast<QSerialPort::StopBits>(ui->stopBitsComboBox->currentData().toInt());QSerialPort::Parity parity = static_cast<QSerialPort::Parity>(ui->parityComboBox->currentData().toInt());serialwork->setupPort(portName, baudRate, dataBits, stopBits, parity);serialwork->startWorker();
}void MainWindow::on_closeButton_clicked()
{serialwork->stop();}void MainWindow::onDataReceived(const QByteArray &data)
{if(ui->isShowRecvButton->isChecked()){QString msg;if(ui->isShowTimeButton->isChecked())msg.append(QDateTime::currentDateTime().toString("hh:mm:ss.(zzz)  "));msg.append(tc("接收  "));msg.append(ui->isShowHexButton->isChecked()? data.toHex(' ').toUpper():QString::fromLocal8Bit(data));ui->receiveTextEdit->append(msg);}//更新显示信息ui->recvByte->setValue(ui->recvByte->value()+data.size());ui->recvFram->setValue(ui->recvFram->value()+1);}void MainWindow::onRespondNormalMessage(const int , const QString &msg)
{writeRunTimeMsgs(msg,Information);
}void MainWindow::onRespondWarningMessage(const int , const QString &msg)
{writeRunTimeMsgs(msg,Warning);
}void MainWindow::onRespondErrorMessage(const int , const QString &msg)
{writeRunTimeMsgs(msg,Error);
}void MainWindow::onRespondSerialConnectState(const int , const bool state)
{ui->openButton->setEnabled(!state);ui->closeButton->setEnabled(state);}void MainWindow::on_clearRecvButton_clicked()
{ui->recvByte->setValue(0);ui->recvFram->setValue(0);ui->sendByte->setValue(0);ui->sendFram->setValue(0);ui->receiveTextEdit->clear();
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Hadoop|MapReduce篇】MapReduce概述

1. MapReduce定义 MapReduce是一个分布式运算程序的编程框架&#xff0c;是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在一个Hadoop集群上。 2. Map…

视频汇聚平台LntonAIServer视频质量诊断功能--偏色检测与噪声检测

随着视频监控技术的不断进步&#xff0c;视频质量成为了决定监控系统性能的关键因素之一。LntonAIServer新增的视频质量诊断功能&#xff0c;特别是偏色检测和噪声检测&#xff0c;进一步强化了视频监控系统的可靠性和实用性。下面我们将详细介绍这两项功能的技术细节、应用场景…

2158. 直播获奖(live)

代码 #include<bits/stdc.h> using namespace std; int main() {int n,w,a[100000],cnt[601]{0},i,j,s;cin>>n>>w;for(i0;i<n;i){scanf("%d",&a[i]);cnt[a[i]];int x(i1)*w/100;if(!x) x1;for(j600,s0;j>0;j--){scnt[j];if(s>x){cou…

linux编译器——gcc/g++

1.gcc linux上先要安装&#xff0c; sudo yum install gcc gcc --version 可以查看当前的版本 &#xff0c;我们默认安装的是4.8.5的版本&#xff0c;比较低&#xff0c; gcc test.c -stdc99 可以使他支持更高版本的c标准 -o 可以殖指明生成文件的名字&#xff0c;可以自己…

重启顺风车的背后,是高德难掩的“野心”

以史鉴今&#xff0c;我们往往可以从今天的事情中&#xff0c;看到古人的智慧&#xff0c;也看到时代的进步。就如西汉后期文学家恒宽曾说的&#xff0c;“明者因时而变&#xff0c;知者随事而制”。 图源来自高德官方 近日&#xff0c;高德就展现了这样的智慧。在网约车市场陷…

电子电气架构---私有总线通信和诊断规则

电子电气架构—私有总线通信和诊断规则 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自…

ROS 工具箱系统要求

ROS 工具箱系统要求 要为 ROS 或 ROS 2 生成自定义消息&#xff0c;或从 MATLAB 或 Simulink 软件中部署 ROS 或 ROS 2 节点&#xff0c;您必须构建必要的 ROS 或 ROS 2 软件包。要构建这些软件包&#xff0c;您必须具备 Python 软件、CMake 软件以及适用于您的平台的 C 编译器…

文件操作与隐写

一、文件类型的识别 1、文件头完好情况&#xff1a; &#xff08;1&#xff09;file命令 使用file命令识别&#xff1a;识别出file.doc为jpg类型 &#xff08;2&#xff09;winhex 通过winhex工具查看文件头类型&#xff0c;根据文件头部内容去判断文件的类型 eg:JPG类型 &a…

3DMax基础- 创建基础模型

目录 零.软件简介 一. 标准基本型 长方体 圆锥体 球体 圆柱体 管状体 圆环 四棱锥 茶壶 平面​编辑 加强型文本 二. 扩展基本体 三.复合对象 变形 散布 一致 连接 图形合并 布尔 并集 合并 交集 差集 四.门和窗 门 窗 植物,栏杆,墙 零.软件简介 3…

JdK版本介绍

JDK&#xff08;Java Development Kit&#xff09;是Java开发的核心工具包&#xff0c;它包含了Java运行时环境&#xff08;JRE&#xff09;以及Java开发工具&#xff08;如编译器、调试器等&#xff09;。JDK的版本更新不断&#xff0c;每个版本都带来了新特性、性能改进和安全…

FreeRTOS 优先级翻转以及互斥信号量

优先级翻转&#xff1a; 高优先级的任务反而慢执行&#xff0c;低优先级的任务反而优先执行 优先级翻转在抢占式内核中是非常常见的&#xff0c;但是在实时操作系统中是不允许出现优先级翻转的&#xff0c;因为优先级翻转会破坏任务的预期顺序&#xff0c;可能会导致未知的严重…

OPenCV结构分析与形状描述符(2)计算轮廓周长的函数arcLength()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算轮廓的周长或曲线的长度。 该函数计算曲线的长度或闭合轮廓的周长。 如果曲线是闭合的&#xff08;即首尾相连&#xff09;&#xff0c;则计…

【数据结构】单链表的应用

1.移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 思路&#xff1a; 创建新链表&#xff0c;找值不为val的节点&#xff0c;尾插到新链表中 /*** Definition for singly-li…

OpenAI发布GPT-4o mini,3.5从此退出历史舞台?

随着OpenAI在2024年7月18日正式发布GPT-4o Mini&#xff0c;无疑在科技界引发了一场新的风暴。这一创新不仅标志着GPT-3.5模型正式退出历史舞台&#xff0c;更预示着人工智能在自然语言处理领域迈入了一个全新的时代。 之前速度最快的模型一直是GPT3.5&#xff0c;随着后来的GP…

基于大数据的科研热点分析与挖掘系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 科研活动的快速发展产生了大量的学术文献&#xff0c;如何从这些文献中提炼出有价值的科研热点和趋势成为了一个重要的问题。本项目旨在开发一个基于大数据的科研热点分析可视化系统&#xff0c;采…

python tkinter 文本类组件

Label组件 Label(win,text文本,justifycenter) win指定Label组件的父容器&#xff1b;text指定标签中的文本&#xff1b;justify指定标签中拥有多行文本时&#xff0c;最后一行文本的对齐方式。 from tkinter import * from PIL import Image,ImageTkroot Tk() root.title(…

水晶连连看 - 无限版软件操作说明书

水晶连连看 – 无限版游戏软件使用说明书 文章目录 水晶连连看 – 无限版游戏软件使用说明书1 引言1.1 编写目的1.2 项目名称1.3 项目背景1.4 项目开发环境 2 概述2.1 目标2.2 功能2.3 性能 3 运行环境3.1 硬件3.2 软件 4 使用说明4.1 游戏开始界面4.2 游戏设定4.2.1 游戏帮助4…

「大数据分析」图形可视化,如何选择大数据可视化图形?

​图形可视化技术&#xff0c;在大数据分析中&#xff0c;是一个非常重要的关键部分。我们前期通过数据获取&#xff0c;数据处理&#xff0c;数据分析&#xff0c;得出结果&#xff0c;这些过程都是比较抽象的。如果是非数据分析专业人员&#xff0c;很难清楚我们这些工作&…

前端常用工具网站分享:MemFire Cloud,懒人开发者的福音

你是否曾梦想过&#xff0c;有那么一款工具&#xff0c;能够让你像变魔术一样快速搭建起一个应用&#xff0c;而无需深陷复杂的后端搭建和接口开发的泥潭&#xff1f;今天&#xff0c;我要为你介绍的&#xff0c;就是这样一个神奇的存在——MemFire Cloud&#xff0c;一款专为懒…

13款常用AI编程工具

AI编程工具的选择和使用&#xff0c;主要取决于具体的项目需求、编程语言、以及AI任务的类型&#xff08;如机器学习、自然语言处理、计算机视觉等&#xff09;。下面是一些广泛使用的AI编程工具合集&#xff0c;涵盖了从开发、训练、到部署的各个环节&#xff1a; Jupyter Not…