大家好,我是小哈哥,今天我们接着上一篇网文的内容,继续完成网友问答。

问题由来

星球网友的提问,有问必答:

今天我们来分享第二个问题的解决方案:

  • 基于Modbus协议将电压数据上传至上位机
  • Qt程序解析Modbus协议,并将解析之后的结果显示在曲线中
  • 将温度数据保存至Excel中

本次分享的实例在 Qt编写Modbus从机程序 的程序基础上完成。

QCustomPlot简介

QCustomPlot是开源的Qt的第三方绘图库,QCustomPlot的源码只有两个文件,可以很方便的添加到自己的工程中。

QCustomPlot库很强大,利用他可以轻松实现柱状图、折线图、多轴、日期轴、金融图等,在其基础上,可以轻松实现曲线的平移、放大、取值、标记等功能,利用其预留的接口,自己可以派生类,随意定制自己的功能。

QCustomPlot库效率高、移植方便,可轻松实现二次开发,推荐使用。

获取源码

QCustomPlot下载地址:

https://www.qcustomplot.com/index.php/download

获取的压缩文件解压之后内容如下:

里面包括文档、示例程序、更改日志、GPL授权及该绘图类的源文件。

添加帮助文档

Qt Creator中有一个很好的功能,如果不知道类或对象有什么函数,选择名称,按 F1 键会直接进入该类的帮助文档,查找文档特别方便。

为了编程的过程中,可以及时查看QCustomPlot类中各个函数的定义,可以把该曲线类的帮助文档也添加到Qt Creator中。

在Qt Creator的菜单:工具–>选项–>帮助–>文档–>添加 qcustomplot\documentation\qcustomplot.qch 文件。

帮助文档添加完毕之后,我们就可以方便的查看各个类、函数的使用方法了。

当QCustomPlot中的哪个类或函数不清楚用法,我们可以将鼠标放到(或悬浮)某个类或函数上面,然后按F1键,就能调出该函数的详细使用说明。

Qt中的其他类或者函数,也可以按F1键获取帮助文档。

添加现有文件

先将“qcustomplot.h”和“qcustomplot.cpp”两个文件拷贝到工程所在目录下,然后用Qt Creator打开工程CommDemo.pro

注意:先打开工程,后拷贝文件亦可。

在工程名称CommDemo上右键弹出菜单中,选择“添加现有文件”,在弹出的对话框中,选择文件“qcustomplot.h”、“qcustomplot.cpp”,点击“打开”按钮,这样,qcustomplot的源文件就被添加到了工程中。

添加必要支持库

因为QCustomPlot中支持打印,所以需要在 .pro 文件中添加 printsupport

引用头文件

mainwindow.h 文件中,引用头文件 #include "qcustomplot.h"

限定曲线显示的区域

设计软件界面的时候,首先要想好我们在哪个位置显示曲线。

具体实现步骤如下:

(1)、进入图形设计界面,添加Widget控件,利用Widget控件对曲线的显示区域进行占位。

(2)、在所添加的Widget区域点击右键,选择“提升为”按钮,提升类名称输入“QCustomPlot”,点击添加。

QCustomPlot是一个绘图板的类,它继承于Widget,界面中的Widget类提升为QCustomPlot才能够绘图。

(3)、去掉原有的TableView,添加一个按钮用于测试,编译并运行,软件界面如下:

至此,QCustomPlot就移植成功了,是不是很简单?!

显示曲线

步骤:

(1)、首先将上面提升为QCustomPlot类的容器界面的对象widget重命名为myCustomPlot ,下面对该曲线控件的操作即对此变量名操作即可。

命名规则:符合自己习惯,方便记忆即可。

(2)、在主窗口MainWindow构造函数中添加如下代码,即可定义一条曲线。

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//原有的串口初始化代码,略//...//添加一条曲线//向绘图区域QCustomPlot(从widget提升来的)添加一条曲线ui->myCustomPlot->addGraph();//设置画笔ui->myCustomPlot->graph(0)->setPen(QPen(Qt::blue));//设置画刷,曲线和X轴围成面积的颜色ui->myCustomPlot->graph(0)->setBrush(QBrush(QColor(255,255,0)));//设置右上角图形标注名称ui->myCustomPlot->graph(0)->setName("曲线");//设置坐标轴标签名称ui->myCustomPlot->xAxis->setLabel("x");ui->myCustomPlot->yAxis->setLabel("y");//设置坐标轴显示范围,否则我们只能看到默认的范围ui->myCustomPlot->xAxis->setRange(0,60);ui->myCustomPlot->yAxis->setRange(0,5000);
}

QCustomPlot中的每一个曲线是一个Graph对象,要显示曲线,首先要添加一条曲线: ui->myCustomPlot->addGraph();

凡是跟显示数据有关的就对Graph进行操作或调用Graph对象提供的方法。

朋友们,思考一下,为什么Y轴的上限我初始化为5000?大家可以在留言区说出你的想法哈。

(3)、在头文件mainwindow.h中定义两个QVector数组,用于存放横轴和纵轴的数据。

QVector<double> arrX;
QVector<double> arrY;

(4)、每执行一次测试按钮的槽函数,就会向曲线中添加一个虚拟点,具体实现如下代码所示:

void MainWindow::on_btnTest_clicked()
{//生成模拟数据arrX.append(arrX.count());arrY.append(qrand()%4096);//传入数据,setData的两个参数类型为doubleui->myCustomPlot->graph(0)->setData(arrX,arrY);//曲线重绘ui->myCustomPlot->replot();
}

到目前为止,即实现了曲线的显示和向曲线中添加数据点的操作,具体效果演示如下:

下面我们要做的就是利用串口通信,获取声音传感器的数据,然后将声音的强度保存到数组arrY中,随后调用 ui->myCustomPlot->replot(); 语句完成重绘曲线。

发送串口数据

根据上一篇网文,我们知道我们今天要编写的Qt软件,相当于上一篇网文中的ModScan32软件。

我们要想获取声音传感器的值,只需要上位机以十六进制的方式发送数据帧:01 04 00 00 00 01 31 CA

STM32端收到串口指令之后,解析此数据帧,将当前的声音传感器的值封装数据帧之后,发送给上位机。

先用串口助手验证一下,确保硬件没有问题:

发送数据:01 04 00 00 00 01 31 CA ,STM32端能够返回预期的数据帧: 01 04 02 XX XX XX XX ,证明STM32端是没有问题的,下面我们来修改CommDemo这个例程,让其可以正确的发送、接收和解析串口数据。

由于串口发送、接收功能,之前我们已经实现了,我们先测试一下,看看发送对应的串口数据,我们是否可以接收到正确的数据帧。

由上图我们可以看出来,数据:01 04 00 00 00 01 31 CA 发送之后,收到了满足预期的数据帧: 01 04 02 00 15 78 FF ,证明串口通信部分代码是没问题的。

注意

  • 发送数据之前要先打开串口,并且串口的波特率要跟硬件STM32的串口波特率一致,即115200。
  • 为了方便查看,记得勾选Hex发送Hex显示

解析串口数据

解析STM32发送过来的结果数据。

void MainWindow::receiveInfo()
{QByteArray info = m_serialPort->readAll();QString strReceiveData = "";if(ui->checkBoxHexReceive->isChecked()){QByteArray hexData = info.toHex();strReceiveData = hexData.toUpper();for(int i=0; i<strReceiveData.size(); i+=2+1)strReceiveData.insert(i, QLatin1String(" "));strReceiveData.remove(0, 1);ui->txtReceiveData->append(strReceiveData);//解析接收到的串口数据uint8_t pCharData[15] = { 0x00 };uint8_t crc16Low, crc16High;for (int i=0;i<info.size();i++){pCharData[i] = static_cast<uint8_t>(info.at(i));}uint16_t crc16 = chkcrc(pCharData, 5);crc16Low = static_cast<uint8_t>(crc16 & 0xff);             //校验位低8位crc16High = static_cast<uint8_t>((crc16 >> 8) & 0xff);     //校验位高8位if(crc16High == static_cast<uint8_t>(info.at(5)) && crc16Low == static_cast<uint8_t>(info.at(6)))   //(1){if(static_cast<uint8_t>(info.at(0)) == 0x01 && static_cast<uint8_t>(info.at(1) == 0x04))    //(2){//将声音传感器的数据添加至曲线中uint16_t nSoundIntensity = static_cast<uint8_t>(info.at(3))*256 + static_cast<uint8_t>(info.at(4)); //(3)arrX.append(arrX.count());arrY.append(nSoundIntensity);//传入数据,setData的两个参数类型为doubleui->myCustomPlot->graph(0)->setData(arrX,arrY);//曲线重绘ui->myCustomPlot->replot();}}}else{strReceiveData = info;//避免中文乱码QTextCodec *tc = QTextCodec::codecForName("GBK");QString tmpQStr = tc->toUnicode(info);ui->txtReceiveData->append(tmpQStr);}
}

解析

(1)、首先要对接收到的一帧数据进行CRC校验,然后将计算出来的校验位和收到数据的校验位比对,一致则说明数据接收正确。

(2)、判断接收到的数据帧的地址位和功能码是否满足预期。

(3)、接收数据帧的第4、第5两个字节为数据位,按自定义协议对这两个字节进行组合,进而求得声音传感器的强度值。

注意:上面解析中(1)、(2)、(3)条说明,跟上面代码中的注释中的(1)、(2)、(3)所在行的代码相对应。

结果测试

在声音传感器旁播放音乐(目的:制造点声音),点击一次发送按钮,将获得一次声音强度的数据,将解析后的声音强度添加至曲线中,绘制的曲线如下图所示:

好了,今天的分享就到这里,曲线的绘制,从0到1已经分享过了,后面曲线的平移、放大、缩小、复原、曲线上点的显示、辅助线的绘制等内容,各位根据需要自行添加哈。

欢迎关注

关注公众号:嵌入式从0到1,第一时间获取技术干货,玩模块、学硬件,带你从0走到1,欢迎关注!

公众号内容包括但不限于STM32、单片机、物联网、鸿蒙、Qt、小程序,欢迎感兴趣的朋友,持续关注。

想加技术交流群的,可以加我微信[chengxuyuanxiaoha],让我拉你进群,与更多同道中人一起成长。

参考阅读

土壤湿度传感器,出远门再也不怕花没人浇水了

STM32F103 串口的使用方法

[网友问答2]上位机如何与STM32进行串口通信

干货 | Modbus协议调试分享

Qt编写Modbus从机程序

上位机如何获得环境声音强度的大小

源码获取

公众号后台回复:QCustomPlot ,获取本文测试工程源码。

欢迎关注

小伙伴们可加微信[chengxuyuanxiaoha]进技术交流群,与更多同道中人一起成长。

分享一个非常强大且好用的绘图控件QCustomPlot相关推荐

  1. android tv 开发布局,Android TV开发总结(七)构建一个TV app中的剧集列表控件

    前言:剧集类控件,在TV app中非常常见,今天将介绍构建一个TV app中的剧集列表控件,此控件上传到我的Github:https://github.com/hejunlin2013/Episode ...

  2. 新发现的一个pyqt5的绘图控件QCustomPlot2

    今天发现了一个新的绘图控件QCustomPlot2,据说性能也非常不错,这个图表库原生支持很多种图表类型,这点比pyqtgraph要好点,pyqtgraph本身支持的图表种类不是特别全,但是也算够用吧 ...

  3. android组合控件的焦点,撸一个简单的TV版焦点控制的日历控件

    1.效果 最近需求要一个遥控控制的日历控件,找了半天没找到轮子,就自己撸一个,先看效果图: 效果图.gif 2.XML属性,所有属性默认为效果图 calender_textSize:星期和日期的字体大 ...

  4. 100% .NET Control_使用CurrencyManager 创建一个导航条来控制DatagGrid的XNavBar控件(VB.NET)....

    Begin MSDN: 要使 Windows 窗体数据绑定成为可能,必须有数据提供程序和使用者. 从提供程序这一方最容易接近 Windows 窗体数据绑定的结构. 绑定一个 Windows 窗体及其控 ...

  5. android 分组柱状图_整理了一个 android 上的波形图及柱状图绘制控件

    SimpleWaveform [说明:以前画过波形图,最近又需要画,略不同,但还得重复写.在网上搜了一下,只找到一个复杂的框架,而我们往往只需要画简单的波形或柱状图.所以我整理提取了过去的代码,有了这 ...

  6. 一个有意思的CStatic和combobox以及Cedit控件结合使用

    如图..源代码下载地址 http://download.csdn.net/detail/hemmingway/4187082 这是编辑字符串... 这是用组合框选择字符串.... 使用方法是托一个St ...

  7. 过年回家,走之前留一个用GDI+实现的略缩图控件

    这是一个加载文件夹图片略缩图的控件,支持多种图片格式~~用法也比较简单 (1).源代码 //头文件ListImageCtrl.h #pragma once #include <vector> ...

  8. 一个Demo学会用Android兼容包新控件

    2019独角兽企业重金招聘Python工程师标准>>> 前言 伟大的Google为Android推出了一系列的兼容包,最新的就是Design Support Library了,这里我 ...

  9. 一个简单的自定义多附件上传控件

    在网上提供的都是生成多个上传控件的代码,但大家可以看看21cn,163那里的多附件上传是不是比那些只是生成多个上传控件的界面美观很多呢??      现在就开始做一个类似21CN那样的上传的.先看看我 ...

  10. 求一个类似win优化大师左边菜单框的控件。

    好象不该发到提问区的,但是不知道发哪了,就先在这呆着吧. 我想要一个上面windows优化大师这样的控件,本来想在google上搜的,可能是关键字不对,没找着. 所以只好又来麻烦各位老大了. 谁有的, ...

最新文章

  1. SAP HUM 嵌套HU初探 III
  2. 关于android开发环境中sdk和adt更新到22.6之后多了appcompat_v7
  3. 应用系统日志采集解决方案
  4. 前端学习(2473):创建页面组件
  5. 项目Beta冲刺 随笔集合
  6. SpringCloud学习笔记012---CentOs7搭建高速缓存NoSql Redis单机服务_redis_4.0.1_或者redis_6.0.x_可自定义版本
  7. 系统变量之System.getenv()和System.getProperty()
  8. 解决:modal中datePicker 选中时,会触发modal的hidden.bs.modal事件
  9. 可视化技巧:DataFrame画图并利用matplotlib保存(pandas)
  10. 小程序block标签配合if和else 和 动态修改标题栏
  11. 大数据真实电商数据仓库全流程开发详解
  12. 台式计算机投网设备,台式机无线投屏 4台电脑一起投屏
  13. 内存带宽测试与AVX指令集读写内存
  14. 为什么计算机没有桌面显示不出来,我的电脑桌面不显示“我的电脑”了,请问怎么调出来?谢谢...
  15. 又一“P8”栽了,约炮成瘾出轨多人,阿里:已劝退!
  16. 如何将鼠标和键盘连接到PlayStation 4
  17. 创新业务中真需求和伪需求的思考
  18. 用TW8836驱动ST7701S TTL屏调试记录
  19. Appium+Pytest+Allure集成PO项目管理模式实现自动化测试
  20. 史玉柱: 我的成功不是偶然

热门文章

  1. 2021-11-03
  2. qt android编程,Qt for Android开发实例教程
  3. Android改包1
  4. 2 Features Engineering for Machine Learning中文翻译系列(二)
  5. win10无法安装网卡驱动
  6. 软件体系结构期末复习(快速入门考试)
  7. 国家统计局 省市区 数据爬取
  8. 4.14 在数字的左侧进行补零 [原创Excel教程]
  9. 笔记本无线网卡资源管理器服务器,笔记本无线网卡怎么打开 笔记本无线上网卡找不到网络解决方法...
  10. android QQ好友分享