电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
干货|手把手教你写一个串口调试助手
分 享
扫描二维码分享
干货|手把手教你写一个串口调试助手
串口调试助手
上位机
果果小师弟
关注
发布时间: 2021-07-20
丨
阅读: 1166
**摘要**:前段时间发布了一个用QT写的串口调试助手,很多小伙伴在后台留言要源码。其实网上有很多免费开源的用QT的上位机,大家搜一下就能找到,为了大家方便学习QT以及如何写一个上位机,今天推荐一下学习资源,顺带带大家写一个非常简单的串口调试助手。 相信很多小伙伴还没有接触过QT,如果想用QT写一个调试助手,首先是会一点C++语法。了解即可,也就是看得懂C++的代码。只要能看懂简单的C+++语法,就能很快的写一个串口调试助手。 先推荐两个视频教程,感兴趣可以看看! # 1、B站Jomse工 ![B站Jomse工](https://img-blog.csdnimg.cn/2021061820422960.png) 看完你基本知道串口调试助手大概是个啥样了,有了大致的了解然后再去看和修改别人的代码。 # 2、B站lililanglang ![B站lililanglang](https://img-blog.csdnimg.cn/20210618204415507.png) 把这两个视频看完后,基本你就能够自己写一个串口调试助手了,视频很短没有废话,全程都是干货。而且别人也给出了源码。 为了大家方便理解,果子哥还是写一篇手把手教你学QT串口调试助手吧! # 3、新建工程 1、首先你要安装QT的开发工具`Qt Creator`。安装过程我这里就不在重复说了,大家可以看我的`CSDN博客`号前面发的一些文章,有介绍的。 ![ ](https://img-blog.csdnimg.cn/2021021622270636.png) 打开`QtCreator`新建一个项目 ![ ](https://img-blog.csdnimg.cn/20210216223010434.png) 项目名称根据需求自己指定即可,在指定项目的存储路径的时候, 路径中不能包含中文, 不能包含中文, 不能包含中文 ![ ](https://img-blog.csdnimg.cn/2021021622313144.png) 直接写一步 ![ ](https://img-blog.csdnimg.cn/20210216223216362.png) `Class name `可以随便写一个,一般默认不变 `Base name `有`QMainWindow`、`QWidget`、`QDialog`随便选一个即可 ![](https://img-blog.csdnimg.cn/20210216223834946.png) 编译套件用于项目文件的编译, 如果安装了多个编译套件, 在这里选择其中一个就可以了 ![](https://img-blog.csdnimg.cn/20210216224044491.png) 版本控制工具没有的话可以不选,主要用于团队开发,点击完成 ![](https://img-blog.csdnimg.cn/20210216224130846.png) 这样我们就新建好了一个项目工程 ![](https://img-blog.csdnimg.cn/20210220103500272.png) 双击ui文件即可进入设计模式,进入界面设计器`Qt Designer`编辑状态,开始进行设计器( Qt Designer )编程。 ![](https://img-blog.csdnimg.cn/20210220104011464.png) 在这个界面我们可以拖动左边的常用界面的空间到编辑窗口,然后生成可视化的界面。 ![样式1](https://img-blog.csdnimg.cn/20210618213210139.png) ![样式2](https://files.mdnice.com/user/3658/918e8691-89c3-48ec-a2d6-7f6653216c9a.png) 可以看到通过拖动控件与修改控件属性就可以做出上面这样的界面,我个人觉得还是非常的美观nice的。这里只是给大家一个参考的界面和模板,排版和配色大家按照自己喜欢的就可以了! ## 一、导入库 1、在项目.pro文件中加入`serialport` ```cpp QT += core gui QT += serialport ``` 2、引入qt中串口通信需要的头文件 ```cpp #include
#include
``` ## 二、配置串口初始化 ### 1、查找可用的串口。 通过创建一个`comobox`,将可用串口的列表展示出来,并用于配置时选择要连接的串口 ```cpp //查找可用串口,刷新串口信息 void MainWindow::GetAveriablePort() { ui->uartReadPlain->insertPlainText("串口初始化:\r\n"); //先清除所有串口列表 ui->portBox->clear(); foreach(const QSerialPortInfo &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"); } } } ``` ### 2、配置串口。 (1)串口的配置至少应当包含串口号、波特率、数据位、停止位、奇偶校验位、流控,这些都可以通过串口实例调用函数配置。可以加入几个comobox或者文本框来选择,也可以默认初始化时就配好。 ```cpp //配置串口初始化 void MainWindow::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,使其不可修改,关闭时恢复 ```cpp //串口开关按钮 void MainWindow::on_openSerialButton_clicked() { //尝试打开串口 if(ui->openSerialButton->text() == tr("打开串口")) { if(ui->portBox->currentText() == "" ) { QMessageBox::warning(NULL, "警告", "无可开启串口!\r\n\r\n"); return; } serial = new QSerialPort; //设置串口名 serial->setPortName(ui->portBox->currentText()); //打开串口 serial->open(QIODevice::ReadWrite); //设置波特率 serial->setBaudRate(ui->rateBox->currentText().toInt()); //设置数据位 switch (ui->dataBox->currentData().toInt()) { case 8: serial->setDataBits(QSerialPort::Data8); break; case 7: serial->setDataBits(QSerialPort::Data7); break; default: break; } //设置校验位 switch (ui->checkBox->currentIndex()) { case 0: serial->setParity(QSerialPort::NoParity); break; default: break; } //设置停止位 switch(ui->stopBox->currentIndex()) { case 0: serial->setStopBits(QSerialPort::OneStop); break; case 1: 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(); } //释放串口 delete serial; 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,否则可能会导致数据永远得不到处理。 ### 1、初始化定时器 ```cpp //设置uart接收缓冲超时定时器 uartRecDataTimer = new QTimer(this); uartRecDataTimer->stop(); uartRecDataTimer->setInterval(uartRecOvertimeCount*1000); //设置定时周期,单位:毫秒 uartRecDataTimer->setSingleShot(true); //设置为单次触发 connect(uartRecDataTimer,SIGNAL(timeout()),this,SLOT(uartRec_timeout())); //设置槽 ``` ### 2、实现ReadData 在计时器超出一个指定间隔后,强制处理已经接收完的buff缓冲,其余时间则是把数据放进缓冲中,重启定时器 ```cpp //读取串口接收消息 void MainWindow::ReadData() { //串口可读数据长度 int byteLen = 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(); } ``` ### 3、数据内容做填充 定时器接收完成处理(一段时间没有数据接收,定时器超时)根据时间戳是否被选择,将数据内容做填充,插入到存放数据的文本框里。 ```cpp //定时器触发打印串口数据 void MainWindow::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"); } } ``` ### 4、配置超时间隔的选项 (1)初始化时加入一个配置框 ```cpp //设置时间输入框只允许使用数字 ui->overTimeRecEdit->setValidator(new QRegExpValidator(QRegExp("^([0-9]{1,4}(.[0-9]{1,3})?)$"))); ui->overTimeRecEdit->setText(QString::number(uartRecOvertimeCount)); ``` (2)运行中配置超时间隔 ```cpp //超时间隔设置 void MainWindow::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函数就可以了,可以根据自己的实际情况做一些配置或是校验处理。比如加回车换行什么的 ```cpp //发送串口数据 void MainWindow::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()); } ``` 至此,一个最基本的串口调试工具就完成了,下面就是给它添加功能和优化了。你可以加入一些功能比如修改样式、保存数据等等。 ![开源代码](https://img-blog.csdnimg.cn/2021061821583168.png) 最后想说的是用QT写上位机的源码例程很多,初学者可以先借鉴别人的代码参考修改,按照自己的喜好以及编程风格进行排版和布局配色即可! 后台回复:**Qcom**,即可获取串口调试助手源码。 ![](https://img.soogif.com/G11cXIOySCUMPGaHbowAC1aFauahPRiZ.gif?scope=mdnice) ![](https://cf01.ickimg.com/bbsimages/202107/2f82d8d1943d44cd13827a6aa1cae692.png)
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
果果小师弟
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交