STM32串口通信上位机

2018-06-15
唔,已经很久没有做过一个完整的练习了,这学期也就主要接触了下Qt和复习了下C++,在蓝桥杯中就拿了一个市三,毕竟数据结构没有学好,惭愧。
这次尝试做了一个简易的串口通讯工具,为PID调试打基础。

**[更新20190509]**新的较完整的串口调试工具上传,继承自这个项目,加入了Chart部件

之前用MFC练过一个计算器,

但是做的并不好,表达式计算不成功,还是因为数据结构学的不好。。。而且觉得MFC用起来十分的麻烦,据说Qt简洁一点,遂予以一试,毕竟技术是相通的。
先是明确了自己要做什么,然后本是打算一步一步学Qt(Qt学习之路),但是经验告诉我等我一步一步学完,就毕业了,所以还是走一步学一步。

这篇日志将大体表现最基本的Qt使用步骤,从建立工程到打包exe。

建立工程

建立工程不细说,这个就按照步骤一步一步来就行,我也没出过啥问题,就那个选择基类,这个我选的是mainwindow,好像是默认的吧。

建立工程之后就可以开始进行GUI绘制和代码实现了

GUI绘制

我对QML没有什么了解,所以GUI就直接用layout画的,画起来好像不必MFC简单多少。。。不过感觉排布方式熟悉以后就上手很多。
使用方法就是把左边的控件拖到右边。。。然后右边右键各种控件和状态栏啥的可以设置还有取消状态栏之类的,右边一栏可以看到各个layout的层级关系和控件的图形设置,字体什么的就在里面设置。多试试就知道了,嘿嘿嘿。

因为我的电脑是高分屏,所以很多按照像素设置死的程序显示起来就很难受= =,这种苦大概大家会有感受,那种按钮按不到,文字看不全的难受。
所以我要给这个小小的程序加入自适应窗口大小,以解决自己的苦(毕竟自己的工具不能恶心自己)

Qt的控件可以通过Layout进行分层约束(我是这么理解的),每一层可以用

  • 栅格布局
  • 水平布局
  • 垂直布局

让布局更工整,而且最后在窗体一层,也就是在没有控件的位置右键选择栅格布局,可以将所有的Layout约束,这样整个窗体内就是一个整体,可以根据窗体大小进行伸缩了,然后再根据需要调整每一个控件和layout的尺寸策略,最大最小以及控件的比例等参数使得在伸缩条件下也能保持所需的格式。
这里面有一个蓝色的弹簧,我虽然不知道这玩意是干嘛的,但是尝试中感觉应该是固定控件位置并且不会因放缩而导致错位的占位控件,emmmm个人理解。

组合框


组合框就是这个东西,下拉会有一些选项,这个东西可以双击进入编辑下拉内容,这个以波特率选择为例,加入一些常规波特率备选

布局Layouts


这个就是布局,右键也可以看到,这个就像是CAD里的约束条件,或者就像一个框,按照规则排布。
多个这种布局可以将每一个控件都约束起来,放缩时就不会错位。

GUI画法

其实如果会QML的话可以用类似HTML的方法描述编辑界面,现在这种方法使用Qt的另一种方式绘制界面,每一个控件也对应一个对象,对理解OOP也有一定帮助,如果是没有接触MFC直接学这个也许会有更深的认识。
在右边的界面中可以看到布局层次以及控件的类

串口实现与按钮的信号槽

1
信号槽是Qt框架引以为豪的机制之一

信号槽就像是嵌入式中的中断,当一个事件发生就会发出一个广播的信号,如果有对象对这个信号感兴趣就会使用连接函数,被连接的槽函数会自动被回调。也就是如果发生了某一感兴趣的事件,某一个操作会自动被触发,类似于MCU检测到一个外部中断便调用中断处理函数进行响应,如果没有相应的设置,事件发生便不触发中断。(如果理解有误,欢迎大佬指正)
[更新2019.5.2]其实看了CSAPP里对操作系统的介绍之后感觉这一切都是类似的。
参考链接

1
2
3
4
5
信号是 Unix、类 Unix 以及其他 POSIX 兼容的操作系统中进程间通讯的一种有限制的方式。  
它是一种异步的通知机制,用来提醒进程一个事件已经发生。
当一个信号发送给一个进程,操作系统中断了进程正常的控制流程,此时,任何非原子操作都将被中断。
如果进程定义了信号的处理函数,那么它将被执行,否则就执行默认的处理函数。
这样看来,信号其实是类似于异常和中断的,是由内核(在其他进程的请求下)向当前进程发出的。

串口的设置

因此要实现按钮的功能就要对按钮进行信号槽连接,不过首先让我们对串口这一特殊环境进行一下设置。
在学习嵌入式时,串口上位机必不可少,Qt5自带QSerialPort类,使用时需要在.pro文件中添加一行说明。
.pro文件大概就像项目的属性描述之类的。
在好看的位置添加一行

1
QT += serialport


就像这样,然后在.h文件中直接引用头文件就行了

1
2
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
  • QSerialPort: 提供访问串口功能
  • QSerialPortInfo:提供系统中存在的串口信息

接下来就要创建一个QSerialPort的对象,对串口的名称、波特率、数据位、校验位、停止位等参数进行设置,然后才能进行串口读写操作。

按钮的信号槽

在UI界面右键控件可以看到“转到槽”这一选项,这就是为按钮添加处理信号的函数,然后选择点击按钮触发。
然后针对每一个按钮在.cpp文件中设置每一个函数,处理这个处理函数要处理的信号,是框里的文字还是鼠标的操作,一步一步设置。
connect函数可以连接信号槽,虽然我也不知道咋用的,只是跟着教程一步步做。
还有一个有趣的设置是可以设置按钮的可用性,比如未开启串口时有些按钮不可用,而开启以后就可用了。


保存数据的文本文件

以前做了那么多文件操作的练习,这回上手也不慢,虽然框架不一样但是感觉真的很像。

1
2
3
#include <QFile>
#include <QTextStream>
#include <QDataStream>

这几个库必不可少,第一个是文件操作的头文件,后两个是针对文本和二进制文件流的库

1
2
3
4
5
6
7
8
9
10
11
12
void MainWindow::on_saveButton_clicked()
{
QFile file("./data-s.txt");
if(file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QTextStream out(&file);

out<<ui->recievetext->toPlainText()<<endl;

file.close();
}
}

这些函数看起来是不是和标准库很像,就是那个recievetext的内容部分出了点差错,没有后面那个toPlainText()函数处理的话保存的文本里是一个十六进制数开头的数串,还不知道啥意思,不过这个函数看起来是将文本框中的文字转换格式用的,在读取数据的函数中也用过。

程序的标题与图标

程序做的差不多了(很多细节被略去,自己摸索的),该做一下美化了。
电力特色嘛,我选了皮卡丘的图标做程序icon,看起来比较萌。
标题和图标可用框架自带的窗口和应用的函数处理

1
2
QString strpath = QApplication::applicationDirPath();
strpath += "/icon.ico";
1
2
w.setWindowTitle(QStringLiteral("萌新的串口调试工具"));
a.setWindowIcon(QIcon(strpath));

要注意这两个针对的对象是不一样的:

  • QApplication a(argc, argv);
  • MainWindow w;
    w是窗口对象,而a是应用对象,这一点一开始坑了我。。。
    并且icon选择的问题,最好使用特别制作的icon,标准格式的那种,直接改格式或是暴力手段出来的可能会出现编译错误(MSVC编译,Error 1),当时上网查来着。
    修改图标一定要加图标的库
    1
    #include <QIcon>

打包

那么现在程序完成了,就差打包和发布了,发布要用release生成并且运行,然后再进行打包。
打开release的文件夹,将exe文件拷出到一个文件夹中
完成以后打开Qt的命令行工具,对软件进行封装

进入exe所在的文件夹,输入

1
cd /d (youraddress)


然后输入

1
windeployqt yourexename.exe

然后就能在文件夹中看到连接好的各种文件,如果不知道是什么就不要乱删。
最后使用打包软件进行打包,我使用的是enigma virtual box,是免费的一个软件,不过不知道是Qt的愿意还是enigma的原因,我一个小串口软件居然有20M大小??!!
enigma的打包就不演示了,根据提示操作然后改改设置就行,多试试就行。
最后就可以出现打开即用的串口程序啦~~~

结束


嗒啦嗒,这就是完成的串口程序,后面还有对数据加工的部分,而数据采集部分就做到这里了

最后贴一下GitHub的项目连接:串口练习
还有软件下载的百度云:萌萌的串口练习
密码:t4i7

Enjoy~~~如果有帮助希望能够资瓷一下哦~