页面加载中,请稍候
来源:嵌入式Linux系统开发发布时间:2022-05-082704浏览
询问 AI
摘要:今天推荐一下学习资源,顺带带大家写一个非常简单的串口调试助手。
相信很多小伙伴还没有接触过QT,如果想用QT写一个调试助手,首先是会一点C++语法。了解即可,也就是看得懂C++的代码。只要能看懂简单的C+++语法,就能很快的写一个串口调试助手。
先推荐两个视频教程,感兴趣可以看看!
B站Jomse工看完你基本知道串口调试助手大概是个啥样了,有了大致的了解然后再去看和修改别人的代码。
B站lililanglang把这两个视频看完后,基本你就能够自己写一个串口调试助手了,视频很短没有废话,全程都是干货。而且别人也给出了源码。
手把手教你学QT串口调试助手。
1、首先你要安装QT的开发工具Qt Creator。安装过程参考 CSDN。

打开QtCreator新建一个项目

项目名称根据需求自己指定即可,在指定项目的存储路径的时候, 路径中不能包含中文, 不能包含中文, 不能包含中文

直接写一步

Class name可以随便写一个,一般默认不变
Base name有QMainWindow、QWidget、QDialog随便选一个即可

编译套件用于项目文件的编译, 如果安装了多个编译套件, 在这里选择其中一个就可以了

版本控制工具没有的话可以不选,主要用于团队开发,点击完成

这样我们就新建好了一个项目工程

双击ui文件即可进入设计模式,进入界面设计器Qt Designer编辑状态,开始进行设计器( Qt Designer )编程。

在这个界面我们可以拖动左边的常用界面的空间到编辑窗口,然后生成可视化的界面。
样式1
样式2可以看到通过拖动控件与修改控件属性就可以做出上面这样的界面,我个人觉得还是非常的美观nice的。这里只是给大家一个参考的界面和模板,排版和配色大家按照自己喜欢的就可以了!
1、在项目.pro文件中加入serialport
QT += core gui
QT += serialport
2、引入qt中串口通信需要的头文件
#include<QtSerialPort/QSerialPort>
#include<QtSerialPort/QSerialPortInfo>
通过创建一个comobox,将可用串口的列表展示出来,并用于配置时选择要连接的串口
//查找可用串口,刷新串口信息
voidMainWindow::GetAveriablePort()
{
ui->uartReadPlain->insertPlainText("串口初始化:\r\n");
//先清除所有串口列表
ui->portBox->clear();
foreach(constQSerialPortInfo &info,QSerialPortInfo::availablePorts())
{
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
ui->uartReadPlain->insertPlainText("可用:"+serial.portName()+"\r\n");
ui->portBox->addItem(serial.portName());
serial.close();
}
else
{
ui->uartReadPlain->insertPlainText("不可用:"+serial.portName()+"\r\n");
}
}
}
(1)串口的配置至少应当包含串口号、波特率、数据位、停止位、奇偶校验位、流控,这些都可以通过串口实例调用函数配置。可以加入几个comobox或者文本框来选择,也可以默认初始化时就配好。
//配置串口初始化
voidMainWindow::PortConfigureInit()
{
//填入串口选项
ui->rateBox->addItem("115200","115200");
ui->rateBox->addItem("38400","38400");
ui->rateBox->addItem("19200","19200");
ui->rateBox->addItem("9600","9600");
ui->dataBox->addItem("8",8);
ui->dataBox->addItem("7",7);
ui->checkBox->addItem("无校验",0);
ui->stopBox->addItem("1位",1);
ui->stopBox->addItem("2位",2);
}
(2)加入一个打开关闭串口的按钮,文本显示“打开串口”时,点击可以关闭串口。文本显示“关闭串口“则相反。
(3)打开串口时,把配置的项的box都disable,使其不可修改,关闭时恢复
//串口开关按钮
voidMainWindow::on_openSerialButton_clicked()
{
//尝试打开串口
if(ui->openSerialButton->text() == tr("打开串口"))
{
if(ui->portBox->currentText() =="")
{
QMessageBox::warning(NULL,"警告","无可开启串口!\r\n\r\n");
return;
}
serial =newQSerialPort;
//设置串口名
serial->setPortName(ui->portBox->currentText());
//打开串口
serial->open(QIODevice::ReadWrite);
//设置波特率
serial->setBaudRate(ui->rateBox->currentText().toInt());
//设置数据位
switch(ui->dataBox->currentData().toInt())
{
case8:
serial->setDataBits(QSerialPort::Data8);
break;
case7:
serial->setDataBits(QSerialPort::Data7);
break;
default:
break;
}
//设置校验位
switch(ui->checkBox->currentIndex())
{
case0:
serial->setParity(QSerialPort::NoParity);
break;
default:
break;
}
//设置停止位
switch(ui->stopBox->currentIndex())
{
case0:
serial->setStopBits(QSerialPort::OneStop);
break;
case1:
serial->setStopBits(QSerialPort::TwoStop);
break;
default:
break;
}
//设置流控制
serial->setFlowControl(QSerialPort::NoFlowControl);//设置为无流控制
//关闭设置菜单使能
ui->portBox->setEnabled(false);
ui->dataBox->setEnabled(false);
ui->checkBox->setEnabled(false);
ui->stopBox->setEnabled(false);
ui->rateBox->setEnabled(false);
ui->openSerialButton->setText("关闭串口");
fTimeCounter.restart();//计时器重新计数
//连接信号和槽函数,串口有数据可读时,调用ReadData()函数读取数据并处理。
QObject::connect(serial,&QSerialPort::readyRead,this,&MainWindow::ReadData);
}
else
{
uartRecDataTimer->stop () ;//定时器停止
if(serial->isOpen())//原先串口打开,则关闭串口
{
serial->close();
}
//释放串口
deleteserial;
serial =NULL;
//恢复使能
ui->portBox->setEnabled(true);
ui->rateBox->setEnabled(true);
ui->dataBox->setEnabled(true);
ui->checkBox->setEnabled(true);
ui->stopBox->setEnabled(true);
ui->openSerialButton->setText("打开串口");
}
}
1、为了读取数据,要创建一个定时器和一个计时器。因为要解决2个问题,一是我们需要一个超时间隔,用于在串口一定时间收不到数据时,判断一次接收完成,处理数据并清空buff。二是需要一个计数,统计串口已经连续接收了多久,即使数据一直不断,我们也要在一个固定时时间点强制判断一次接收完成,处理数据并清空buff,否则可能会导致数据永远得不到处理。
//设置uart接收缓冲超时定时器
uartRecDataTimer =newQTimer(this);
uartRecDataTimer->stop();
uartRecDataTimer->setInterval(uartRecOvertimeCount*1000);//设置定时周期,单位:毫秒
uartRecDataTimer->setSingleShot(true);//设置为单次触发
connect(uartRecDataTimer,SIGNAL(timeout()),this,SLOT(uartRec_timeout()));//设置槽
在计时器超出一个指定间隔后,强制处理已经接收完的buff缓冲,其余时间则是把数据放进缓冲中,重启定时器
//读取串口接收消息
voidMainWindow::ReadData()
{
//串口可读数据长度
intbyteLen = serial->bytesAvailable();
if(byteLen <0)
{
return;
}
rec_buf_len += byteLen;
uart_rec_ss.append(serial->readAll());//读取数据
//计时器超过最大间隔仍未填入数据,强制填入
if(fTimeCounter.elapsed() >2000&& uart_rec_ss.size()>0)
{
ui->uartReadPlain->moveCursor(QTextCursor::End);//光标移动到结尾
ui->uartReadPlain->insertPlainText(uart_rec_ss);
ui->uartReadPlain->moveCursor(QTextCursor::End);//光标移动到结尾
uart_rec_ss.clear();
}
//定时器开始工作、定时器重启
uartRecDataTimer->start();
}
定时器接收完成处理(一段时间没有数据接收,定时器超时)根据时间戳是否被选择,将数据内容做填充,插入到存放数据的文本框里。
//定时器触发打印串口数据
voidMainWindow::uartRec_timeout()
{
if(!uart_rec_ss.isEmpty())
{
curDateTime = QDateTime::currentDateTime();
ui->uartReadPlain->moveCursor(QTextCursor::End);//光标移动到结尾
if(ui->timeZoneCheckBox->isChecked())
{
ui->uartReadPlain->insertPlainText("\r\n"+curDateTime.toString("[yyyy-MM-dd hh:mm:ss]")+"R:");
ui->uartReadPlain->moveCursor(QTextCursor::End);//光标移动到结尾
ui->uartReadPlain->insertPlainText(uart_rec_ss);
}
else
{
ui->uartReadPlain->insertPlainText(uart_rec_ss);
}
ui->uartReadPlain->moveCursor(QTextCursor::End);//光标移动到结尾
uart_rec_ss.clear();
fTimeCounter.restart();
ui->RXLenLabel->setText(QString::number(rec_buf_len)+"bytes");
}
}
(1)初始化时加入一个配置框
//设置时间输入框只允许使用数字
ui->overTimeRecEdit->setValidator(newQRegExpValidator(QRegExp("^([0-9]{1,4}(.[0-9]{1,3})?)$")));
ui->overTimeRecEdit->setText(QString::number(uartRecOvertimeCount));
(2)运行中配置超时间隔
//超时间隔设置
voidMainWindow::on_overTimeRecEdit_returnPressed()
{
if(ui->overTimeRecEdit->text().toFloat()>60)
{
QMessageBox::warning(NULL,"警告","超时时间不要超过1分钟");
ui->overTimeRecEdit->setText("0.1");
return;
}
uartRecOvertimeCount = ui->overTimeRecEdit->text().toFloat();
ui->uartReadPlain->insertPlainText("设置超时时间为:"+QString::number(uartRecOvertimeCount*1000)+"ms");
uartRecDataTimer->setInterval(uartRecOvertimeCount*1000);//设置定时周期,单位:毫秒
fTimeCounter.restart();
uartRecDataTimer->start();
}
简单的发送数据没有什么要额外配置的,调用write函数就可以了,可以根据自己的实际情况做一些配置或是校验处理。比如加回车换行什么的
//发送串口数据
voidMainWindow::on_sendDataButton_clicked()
{
//未打开串口则不准发送
if(ui->openSerialButton->text() =="打开串口")
{
QMessageBox::warning(NULL,"警告","未打开可用串口,无法发送数据!\r\n\r\n");
return;
}
//获取发送的命令,并选择在结尾加上换行,AT的命令结尾必须有回车换行
QString command = ui->uartWritePlain->toPlainText();
if(ui->changeLineCheckBox->isChecked())
{
command +="\r\n";
}
if(ui->timeZoneCheckBox->isChecked())
{
curDateTime = QDateTime::currentDateTime();
ui->uartReadPlain->insertPlainText("\r\n"+curDateTime.toString("[yyyy-MM-dd hh:mm:ss]")+"SEND:"+command);
}
send_buf_len += command.length();
ui->TXLenLabel->setText(QString::number(send_buf_len)+"bytes");
serial->write(command.toLatin1());
}
至此,一个最基本的串口调试工具就完成了,下面就是给它添加功能和优化了。你可以加入一些功能比如修改样式、保存数据等等。
开源代码最后想说的是用QT写上位机的源码例程很多,初学者可以先借鉴别人的代码参考修改,按照自己的喜好以及编程风格进行排版和布局配色即可!
新闻来源:嵌入式Linux系统开发,文中所述为作者独立观点,不代表icspec立场。更多精彩资讯请下载icspec App。如对本稿件有异议,请联系微信客服specltkj。
暂无评论哦,快来评论一下吧!

2026-07-02

2026-07-09

2026-07-22