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.mzph.cn/pingmian/53341.shtml

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

相关文章

【信创建设】信息系统信创建设整体技方案(word原件完整版)

信创&#xff0c;即“信息技术应用创新”。我国自主信息产业聚焦信息技术应用创新&#xff0c;旨在通过对IT硬件、软件等各个环节的重构&#xff0c;基于我国自有IT底层架构和标准&#xff0c;形成自有开放生态&#xff0c;从根本上解决本质安全问题&#xff0c;实现信息技术可…

多款式随身WiFi如何挑选,USB随身WiFi、无线电池随身WiFi、充电宝随身WiFi哪个好?优缺点分析!

市面上的随身WiFi款式多样琳琅满目&#xff0c;最具代表性的就是USB插电款、无线款和充电宝款。今天就来用一篇文章分析一下这三种款式的优缺点。 USB插电款 优点&#xff1a;便宜&#xff0c;无需充电&#xff0c;在有电源的地方可以随时随地插电使用&#xff0c;比如中兴的U…

MATLAB基础应用精讲-【数模应用】正交实验

目录 前言 算法原理 什么是正交实验 在测试中的作用 使用正交试验法的原因 什么是正交试验法? 正交实验基本设计思想 正交表 正交实验的操作方法 正交实验结果分析方法 SPSSAU 正交实验案例 1、背景 2、理论 3、操作 5、文字分析 6、剖析 疑难解惑 正交表和…

Spring Boot 部署方案!打包 + Shell 脚本详解

本篇和大家分享的是springboot打包并结合shell脚本命令部署&#xff0c;重点在分享一个shell程序启动工具&#xff0c;希望能便利工作&#xff1b; profiles指定不同环境的配置 maven-assembly-plugin打发布压缩包 分享shenniu_publish.sh程序启动工具 linux上使用shenniu_p…

python进阶篇-day07-高级语法与正则

day07-python其他高级语法 一. with(上下文管理) 介绍 概述 一个类只要实现了__ enter __ () 和 __ exit __ ()方法, 这个类就是一个上下文管理器类, 该类的对象 上下文管理器对象 目的 节约资源, 提高效率, 避免手动释放资源, 且出bug的时候, 也会自动尝试释放资源 特点…

【Centos】绕开报错ModuleNotFoundError: No module named ‘dnf‘

问题原因&#xff1a; 安装python3.9后不能使用yum Traceback (most recent call last):File "/usr/bin/yum", line 57, in <module>from dnf.cli import main ModuleNotFoundError: No module named dnf绕开yum解决方法&#xff1a; 直接下载相关依赖包 htt…

怎样将手机屏幕(远程)投屏到家里的大电视上?

我不住家里&#xff0c;前几次回去都会替老爸老妈清理手机。这两个星期没空回去&#xff0c;老爸吐槽手机用几天就又卡了&#xff0c;其实就是清理一些手机缓存的问题。 我说我远程控制他的手机&#xff0c;给他清理一下。他一听“控制”就不喜欢&#xff0c;说我大了&#xf…

软件测试面试从哪方面面试?

一、面试基础题 简述测试流程: 什么是软件测试&#xff1f;软件测试的目的与原则 问&#xff1a;软件生存周期及其模型是什么&#xff1f; 什么是软件质量&#xff1f; 自动化测试脚本开发的主要步骤: 目前主要的测试用例设计方法是什么&#xff1f; 常见的测试用例设计…

【Python知识宝库】文件操作:读写文件的最佳实践

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 前言一、文件读取1. 使用open函数2. 逐行读取3. 使用readlines和readline 二、文件写入1. 写入文本2. 追加内容3. 写入…

使用shell脚本安装mysql8,进行主从备份配置

思路 在3台主机上安装mysql进行主从备份配置 使用rpm包yum安装mysql 首先&#xff0c;我们要准备好安装文件&#xff0c;首先下载rpm包 wget -P "/opt/" https://repo.mysql.com//mysql80-community-release-el7-3.noarch.rpm 然后执行安装&#xff08;默认已配置…

HMI设计:嵌入式设备和电脑的差异化,工控领域首选。

嵌入式设备属于专机专用&#xff0c;电脑是通用&#xff0c;从性能、用途、特殊能力、成本、通信上嵌入式设备完全优于电脑&#xff0c;是工控领域的首选。 嵌入式设备和电脑在很多方面有着显著的差异&#xff0c;主要体现在以下几个方面&#xff1a; 1. 设计用途&#xff1a…

go 开发小技巧

一、简介 本篇文章会介绍go 开发小技巧。 二、go 开发技巧 2.1 Semaphore type Semaphore chan struct{}func NewSemaphore(maxCount int) Semaphore {return make(chan struct{}, maxCount) }func (s Semaphore) Acquire() {s <- struct{}{} }func (s Semaphore) tryAcq…

在js渲染的dom中的事件中传递对象

在某些情况下&#xff0c;可能需要将整个对象或部分对象嵌入到 HTML 元素的属性中&#xff0c;可以将对象数据序列化为 JSON 字符串&#xff0c;存储在 data-* 自定义属性中。这样可以在事件中取出并解析对象数据&#xff1a; <!DOCTYPE html> <html lang"en&qu…

linux高级学习9

24.9.6学习目录 一.共享内存1.共享内存的API 一.共享内存 特点&#xff1a; 其在进程间共享数据的方法中是最快的要注意对给定存储区访问时进行互斥 1.共享内存的API &#xff08;1&#xff09;获取共享内存标识符 在shell中使用 ipcs -m进行查看共享内存 ipcrm -m shmid删…

P1546 [USACO3.1] 最短网络 Agri-Net

[题目通道]([USACO3.1] 最短网络 Agri-Net - 洛谷) #include<bits/stdc.h> #define int long long using namespace std; const int N1e6100; struct edge{int u,v,w; }e[N*30]; bool cmp(edge a,edge b){return a.w<b.w; } int a,b,c,n,m,fa[N],cnt0,ans0; int fin…

目标检测-YOLOv10

YOLOv10 是 YOLO 系列的最新版本&#xff0c;进一步推动了目标检测技术的发展。它在前代&#xff08;YOLOv9&#xff09;的基础上进行了更多优化和改进&#xff0c;使得模型在复杂场景、实时性以及精度方面取得了更高的突破。YOLOv10 将高效的架构设计与新颖的技术结合&#xf…

C++万字解读类和对象(上)

1.类的定义 class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{}中为类的主体&#xff0c;注意类定义结束时后面分号不能省略。类体中内容称为类的成员&#xff1a;类中的变量称为类的属性或成员变量; 类中的函数称为类的方法或者成员函数。 为了区分成员变量&…

[QT] QT事件与事件重写

一.事件 事件(event)是由系统或者 Qt本身在不同的场景下发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口关闭等都会发出一个相应的事件。 一些事件在用户操作时发出(如鼠标/键盘事件); 另一些事件则是由系统自动发出(如计时器事件)。 Qt窗口中对于产生的一系列事件都…

MarkdownEditor 配置以及使用

MarkdownEditor 配置以及使用 MarkdownEditor是一款基于浏览器的 Markdown 编辑器&#xff0c;虽然他是独立软件&#xff0c;但该软件内嵌一个浏览器。功能非常简单实用、反应速度很快&#xff0c;号称是Markdown领域的NotePad&#xff08;记事本&#xff09;。 MarkdownEdit…

PHP与Nginx配置优化:深入探讨Socket通信

在现代Web开发中&#xff0c;PHP和Nginx的组合是一种常见且高效的服务器配置。本文将深入探讨PHP-FPM&#xff08;FastCGI进程管理器&#xff09;与Nginx的配置&#xff0c;特别是关于它们之间的通信方式——Unix Domain Socket和TCP Socket的选择与优化。 PHP-FPM配置解析 首…