摘要:今天我要分享一个基于QT设计的串口调试工具,源码可以在Gitee上找到,代码简单且易于操作!
https://gitee.com/ErichMoonan/serial-master
1、概述
在开始设计这个小软件之前,让我们先简略地分析一下它需要包含的主要内容。我们认为这个软件需要涵盖以下几个方面的内容:
-
串口参数配置:我们希望能够自动搜索可用的串口号,并能够选择相应的配置参数。 -
发送数据输入:作为调试工具,我们需要能够输入相应的数据来实现命令和消息的发送。因此,我们需要设计一个输入区域和相应的发送按钮。 -
接收信息显示:作为调试工具,我们当然希望能够清晰地看到目标设备发送过来的消息。因此,我们需要一个显示区域来展示接收到的信息。 -
运行状态显示:我们希望能够通过界面显示操作的状态,以指示操作的执行情况。因此,我们需要一个状态栏来实现这一需求。 -
其他辅助功能:有时候,我们可能还需要发送计数、接收计数和数据存储等功能。因此,我们需要考虑这些辅助功能。
其实,在网上已经有许多串口工具可供使用。为什么我们要自己实现这样一个串口调试工具呢?主要有两个原因。首先,我们在网上找到的某些工具并不能完全满足我们的需求,因此我们根据自己的需求设计这个工具,以更好地满足我们的串口调试需求。其次,通过实现这样一个工具,我们能够更深入地理解串口通信相关知识。
2、界面设计
根据前面分析的需求,我们首先来设计软件的界面。我们使用QT中的QMainWindow类来生成一个操作界面,该界面包括菜单栏、工具栏和状态栏,以满足在需求中对状态显示和操作命令的要求。
在中间的显示区域,我们将其分为3行2列。在左侧的一列从上到下分别设置了:串口配置操作区域、接收配置区域以及发送配置区域。在右侧的一列从上到下分别设置了:动态曲线显示区域、信息接收显示区域以及信息发送输入区域。具体的界面设置如下图所示:
![image-20240108184454890](https://lxlinux.superbed.verylink.top/item/659bd275871b83018ac4873d.png)
完成如上图的布局后,我们可以选择在属性中配置空间的参数,也可以在代码中添加相关的参数,本人习惯于在代码中完成。完成整个布局后我们先试着运行程序,正常运行则出现如下的界面:
![image-20240108184500686](https://lxlinux.superbed.verylink.top/item/659bd275871b83018ac48704.png)
上图就是完成布局后的运行界面,不过我们还没有实现相应的编码,所以目前还不能实现我们第一节中所提出来的功能。
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(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(sender()))
{
QString senderName;
int sn=0;
senderName = btn->objectName();
sn = senderName.replace("pushButtonSend", "").toInt();
if((0
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 = ""+context+"";
ui->textBrowser->append(content);
receivedBytes=receivedBytes+rxDatas.size();
ui->lcdNumberRecieve->display(receivedBytes);
ui->statusbar->showMessage(tr("成功读取%1字节数据").arg(rxDatas.size()));
}
rxDatas.clear();
}
4、小结
完成了编码调试后,我们来对开发的这一工具进行一些测试。首先我们安装一个虚拟串口软件用以虚拟我们用于测试的串口。如果有硬件接口最好,但是在我的电脑上没有串口,所以我们使用虚拟串口来模拟一对串口。具体的配置如下图所示:
我们使用另一个串口工具来实现与我们开发的这一工具实现通讯验证。我们使用以前写得一个串口工具来实现与这一工具的通讯。一个使用使用COM1,一个使用使用COM2。具体的配置如下图所示:
注:使用虚拟串口波特率可以
![image-20240108184509955](https://lxlinux.superbed.verylink.top/item/659bd275871b83018ac48739.png)
以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !