软件设计开发笔记2:基于QT设计串口调试工具
串口通信是我们经常会遇到的问题。很多时候当我们设计一个串口应用时,我们希望有一个简便的、可视的方式来验证它。这一篇中我们就来基于QT设计一个串口调试工具。
1、概述
在开始软件设计之前,我们来简略地分析一下这样一个小软件其要包含的主要内容有哪些。我们认为软件需要如下几个方面的内容:
- 串口参数的配置,我们希望串口号能够自动搜索,而相应的配置参数我们可以选择。
- 发送数据的输入,对于本软件我们需要输入相应的数据以实现命令及消息的发送,所以我们需要设计数据的输入区域以及发送交互按钮等。
- 接收信息的显示,作为调试工具,我们肯定希望能够一目了然地看到接收到目标设备发送过来的消息,所以我们需要一个显示区域来对接收的区域进行显示。
- 运行状态的显示, 我们希望对操作的状态进行反馈以指示操作的动作是否执行,所以我们需要状态栏来实现这一需求。
- 其它辅助功能, 还有如发送计数、接收计数、数据存储等功能有时候也是需要的,所以我们一并考虑。
对于串口工具其实网上就有不少,我们之所以要自己实现这么一个串口调试工具,主要的原因有两点。一是,网上找到的相应工具某一个单独的工具有时候不能完全满足我们的需求,所以我们根据自己的需求设计这个工具能更好的满足我们串口调试的需要。二是,通过这样一个工具的实现,我们能够加深对串口通讯相关知识的理解。
2、界面设计
根据上一节中分析的需求,我们先来设计软件的界面。我们在QT中基于QMainWindow类生成一个操作界面,包括菜单栏、工具栏和状态栏以满足需求中对状态显示及操作命令的要求。
而在中间显示区域,我们将其划分为3行2列。在左边的一列从上到下设置:串口配置操作区域、接收配置区域以及发送配置区域。在右侧的一列从上到下设置:动态曲线显示区域、信息接收显示区域以及信息发送输入区域。具体的界面设置如下图所示:
完成如上图的布局后,我们可以选择在属性中配置空间的参数,也可以在代码中添加相关的参数,本人习惯于在代码中完成。完成整个布局后我们先试着运行程序,正常运行则出现如下的界面:
上图就是完成布局后的运行界面,不过我们还没有实现相应的编码,所以目前还不能实现我们第一节中所提出来的功能。
3、编码实现
接下来这一小节,我们将来编码实现相应的功能。我们主要将功能分为参数设置与操作功能、数据的输入与发送功能以及数据的接收与显示功能三个部分来实现。
3.1、参数设置与操作功能
对于参数的配置除了串口号以外都可以直接使用ComboBox控件的相应函数添加。串口号这块,我们希望搜索电脑安装的串口并添加到控件中。具体的实现方式如下:
//搜索可用的串口,并添加到串口组合框
void MainWindow::SearchSerialPorts()
{ui->comboBoxPort->clear();foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()){ui->comboBoxPort->addItem(info.portName());}
}
配置好串口参数后,我们可以打开串口以建立连接。需要说明的是我们打开串口间离连接时,我们需要将该串口的数据接收与我们的数据接收和处理函数建立信号槽连接。具体实现如下:
//打开串口
void MainWindow::on_actionConnect_triggered()
{serialPort->setPortName(ui->comboBoxPort->currentText());if(serialPort->open(QIODevice::ReadWrite)) //打开串口成功{serialPort->setBaudRate(ui->comboBoxBaud->currentText().toInt()); //设置波特率switch(ui->comboBoxData->currentIndex()) //设置数据位数{case 1:serialPort->setDataBits(QSerialPort::Data8);break;default: break;}switch(ui->comboBoxParity->currentIndex()) //设置奇偶校验{case 0: serialPort->setParity(QSerialPort::NoParity);break;default: break;}switch(ui->comboBoxStop->currentIndex()) //设置停止位{case 1: serialPort->setStopBits(QSerialPort::OneStop);break;case 2: serialPort->setStopBits(QSerialPort::TwoStop);break;default: break;}serialPort->setFlowControl(QSerialPort::NoFlowControl); //设置流控制//连接槽函数QObject::connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::ReadSerialData);// 设置控件可否使用ui->actionConnect->setEnabled(false);ui->actionClose->setEnabled(true);ui->actionRefresh->setEnabled(false);}else //打开失败提示{QMessageBox::information(this,tr("错误"),tr("打开串口失败!"),QMessageBox::Ok);}
}
同样的,我们除了要打开串口建立连接外,还需要关闭串口断开连接,具体的代码如下:
//关闭串口
void MainWindow::on_actionClose_triggered()
{serialPort->clear();serialPort->close();// 设置控件可否使用ui->actionConnect->setEnabled(true);ui->actionClose->setEnabled(false);ui->actionRefresh->setEnabled(true);
}
3.2、数据的输入与发送功能
数据的输入与发送,我们设计了5条命令,每条命令可以通过后面的按钮手动发送,也可以自动循环发送。自动循环发送时,将对每条选中的命令以设定的时间间隔轮询发送。
首先我们来看看定时周期发送的过程。我们定义了一个计时器,以我们设定的时间周期触发发送命令,每次发送复选框被选中的命令一条,依次循环直到人为停止循环发送为止。具体的代码如下:
//定时周期发送
void MainWindow::CycleSendData()
{QCheckBox* cbSend;while(true){snIndex=snIndex>=6?1:snIndex;cbSend=ui->groupBoxMessage->findChild<QCheckBox*>(QString("checkBoxSendEnable%1").arg(QString::number(snIndex)));if(cbSend->isChecked()){WriteSerialData(snIndex);snIndex++;break;}snIndex++;}
}
手动单次发送则判断是哪一个按钮触发的动作则操作对应的数据输入框,将其中的内容以指定的格式发送出去。具体的操作代码如下:
//按钮触发发送
void MainWindow::SingleSendData()
{// 判断如果Sender是QPushButton就执行if (QPushButton* btn = dynamic_cast<QPushButton*>(sender())){QString senderName;int sn=0;senderName = btn->objectName();sn = senderName.replace("pushButtonSend", "").toInt();if((0<sn) && (sn<6)){WriteSerialData(sn);}}
}
3.3、数据的接收与现实功能
在我们的设计中,数据的接收相对要简单一些。当串口接收到数据后就会触发我们的接收数据处理函数,并将以我们设定的格式显示出来,具体的实现代码如下:
//从串口接收数据
void MainWindow::ReadSerialData()
{QByteArray rxDatas;QString context;rxDatas=serialPort->readAll();if(!rxDatas.isNull()){if(ui->checkBoxRecieve->isChecked()) //十六进制显示{context = rxDatas.toHex(' ');context=context.toUpper();}else //ASCII显示{context = rxDatas;}QString timeStrLine="["+QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")+"][接收]: ";context = timeStrLine+context+"\n\r";QString content = "<span style=\" color:blue;\">"+context+"</span>";ui->textBrowser->append(content);receivedBytes=receivedBytes+rxDatas.size();ui->lcdNumberRecieve->display(receivedBytes);ui->statusbar->showMessage(tr("成功读取%1字节数据").arg(rxDatas.size()));}rxDatas.clear();
}
4、小结
完成了编码调试后,我们来对开发的这一工具进行一些测试。首先我们安装一个虚拟串口软件用以虚拟我们用于测试的串口。如果有硬件接口最好,但是在我的电脑上没有串口,所以我们使用虚拟串口来模拟一对串口。具体的配置如下图所示:
我们使用另一个串口工具来实现与我们开发的这一工具实现通讯验证。我们使用access port来实现与这一工具的通讯。access port使用COM12,SerialMaster使用COM12,相应的串口参数配置为一致。具体的配置如下图所示:
我们使用access port发送数据,SerialMaster接收到并在显示区显示为蓝色字符。同样我们通过SerialMaster手动发送一条信息,可以在access port看到相应的数据并且在SerialMaster的显示区域显示为红色字符。如下图所示:
接着我们试验自动循环发送。我们将发送取得三条命令输入,并将对应的复选框选择为选中。并将自动发送复选框选中,就会按设定的时间间隔发送相应的命令。如下图所示:
到这里我们想要的串口调试工具就基本实现了,当然,后续我们还可以更具需要修改或添加一些功能以适应不同的应用寻求,甚至可以嵌入到一些应用中以实现必要的测试功能。我们将代码发布到Gitee,欢迎下载和交流。
完整代码下载地址:https://gitee.com/ErichMoonan/serial-master
欢迎关注:
软件设计开发笔记2:基于QT设计串口调试工具相关推荐
- 一个基于QT设计串口调试工具
关注.星标公众号,直达精彩内容 来源:木南创智 整理:李肖遥 摘要:今天再次分享一个基于QT设计串口调试工具,源码在Gitee,代码简单,可操作性强! https://gitee.com/ErichM ...
- 【QT学习笔记】基于QT的天气预报
[QT学习笔记]基于QT的天气预报 前言 那就开始吧! 先看一下效果 颜面最重要,画个UI 构造实现 怎么开始? 开始解析数据 关于城市切换 ok 最后源码献上 感谢 前言 学习qt已经有一段时间了, ...
- 软件设计开发笔记3:基于QT的Modbus RTU主站
Modbus是一种常见的工业系统通讯协议.在我们的设计开发工作中经常使用到它.在这一篇中我们将简单实现一个基于QT的Modbus RTU主站上位工具. 1.概述 Modbus RTU主站应用很 ...
- 基于STM32的自动量程转换数字电压表设计--开发笔记
提示:本文仅阐述了关于嵌入式项目开发的学习思路,用于记录项目经历和分享学习,不涉及具体实现!学习思路仅供参考学习. 一.选题 老师给了5个题目,选题阶段大概有一个月的时间.选取题目时一定要根据自身基础 ...
- 基于Qt设计的人脸识别门禁系统(录入、识别、对比、删除)
一.前言 随着现代科技的不断发展,现在的中国已经迈入5G时代,人工智能技术也正逐步广泛运用到了各行各业中,尤其人脸识别技术,已在各大行业中广泛使用.人脸识别门禁系统,可以防止陌生人尾随进入园区,大大降 ...
- 8266串口调试助手_开源软件分享-基于WPF的串口调试工具
最近同事在调试硬件的串口通讯功能,由于PLC暂时还没到,所以准备用USB转串口线连接在终端上,通过电脑USB口模拟串口收发功能.一开始同事下载了一款串口调试工具,发现没有自定义功能,比如通讯串口收到终 ...
- 软件设计开发笔记1:基于状态机的程序设计
在编码实现的过程中,我们会经常使用到条件判断结构,而且使用起来很方便.但是在需要转移的状态比较多,或是条件比较复杂时,我们就可能需要很长的条件判断结构来处理.不过,过于复杂的条件判断结构会给代码的 ...
- 云炬Android开发笔记 12基于WebView的混合App框架设计(包含浏览器与原生请求Cookie的处理)
阅读目录 1.WebView高可扩展性封装 1.1 发现模块的框架搭建 1.2 webView的基类 1.3 对webview基类的实现 1.4 setInitializer的方法的实现 1.5 we ...
- 云炬Android开发笔记 1项目架构设计与模块分解
一.项目架构设计与模块分解 ② ③ ④ ⑤ ⑥ 2. ② 注: 1.WeakHashMap的键值对在内存需要的时候可以被回收 2.static final定义的变量名需要大写,并且用下划线进行分隔.如 ...
- 张飞硬件设计开发笔记(第一部)
第一部主要是学习点亮一个LED灯 首先电压源为交流16V LED灯点亮电压为3.3V 电流为2-10mA,我们需要反推,怎么将交流16V变成直流3.3V且通过LED的电流不能超过10mA,否则LED会 ...
最新文章
- 一分钟AI | 特斯拉发布电动卡车,扫地机器人被曝窥探个人隐私
- 如何合理地估算线程池大小?
- 【“零起点”--百度地图手机SDK】如何添加地图图层+按钮事件+水平垂直布局?...
- go语言之进阶篇http客户端编程
- python中引入sql的优点_SQL Server 2017中的Python:增强的数据库内机器学习
- 效能改进之项目例会导入实践
- pigeon hole
- c++使用netsh命令_渗透常用命令IPC$内网(一)
- html5文章页面,文章页面的设计《 HTML5 与 Bootstrap 应用实例 》
- PHP未来码支付V1.3网站源码开源版
- java se 8 新特性_javase8-sample
- php缩略图代码,php 缩略图实现函数代码_php
- 7z替换exe文件内容不能替换文件_windows/system32文件夹权限问题
- python lambda函数 与 函数式编程
- 高德地图API-获取位置信息的经纬度
- 【砸壳STEP2】使用cycript查看并修改微信UI界面
- 【软件测试】如何定位web前后台的BUG
- codemirror 只读模式(vue)
- idea配置翻译插件(google翻译插件)
- 互联网摸鱼日报(2023-01-11)
热门文章
- Android适配64位TBS X5内核
- 深入浅出Python——Python高级语法之异常、模块、包
- Kepware AB驱动 · 秒懂百科
- Java毕业设计-医院药品管理系统
- [Android ] 进度条组件ProgressBar
- VS MFC checkbox 控件默认选中
- amd显卡测试帧数显示软件,AMD最新科技让帧数翻倍?FidelityFX超分辨率FSR帧数画面实测...
- linux默认提供几个虚拟桌面 如何,消防车按功能用途可分为灭火消防车、专勤消防车、举高消防车和后援消防车。...
- TransCoder介绍
- oracle触发器 菜鸟教程,PostgreSQL 触发器