IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Qt绘制实时曲线展示超声波传感器的数据【串口助手定制版】 -> 正文阅读

[嵌入式]Qt绘制实时曲线展示超声波传感器的数据【串口助手定制版】

一、展示效果

在这里插入图片描述

二、绪论

1.教程背景

因为项目涉及到超声波传感器,想要做一个上位机展示超声波传感器读取到的距离信息,网上很多教程都是关于普通串口助手展示文本数据的,所以在此将串口读取和曲线展示两个功能显示在一起。这个串口助手删减了很多功能,只保留了读取功能,并没有发送功能(用不上),所以实现比较简单。

2.工程架构

在这里插入图片描述
在这里插入图片描述
chart源文件主要用于图标的设置,serial源文件主要用于串口的设置。

3.serial头文件

#ifndef SERIAL_H
#define SERIAL_H

#include <QMainWindow>
#include "ui_serial.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QString>
#include <QDateTime>
#include <QTimer>
#include <qmath.h>
#include <QDebug>
#include <QChartView>
#include <QSplineSeries>
#include <QValueAxis>
#include <QtCharts>
using namespace QtCharts;


QT_BEGIN_NAMESPACE
namespace Ui { class serial; }
QT_END_NAMESPACE

class serial : public QMainWindow
{
    Q_OBJECT

public:
    serial(QWidget *parent = nullptr);
    ~serial();

private slots:  //自定义槽函数
    //检测通讯端口槽函数
    void btn_serial_check(bool);
    //打开选择端口槽函数
    void btn_open_port(bool);
    //关闭选择端口槽函数
    void btn_close_port(bool);
    //接收数据槽函数
    void receive_data(void);
    //清空接收槽函数
    void btn_clear_rev(bool);
    //更新曲线
    void updatechart();

private:
    Ui::serial *ui;
    void ChartInit();  //图表初始化函数
    void system_init();//用户系统初始化
    QSerialPort global_port;//串口全局类声明
    
    QChart *m_chart ;
    QChartView  *m_chartView;//画布
    QValueAxis *axisX;       //坐标轴
    QValueAxis *axisY;
    QSplineSeries *series ; //平滑曲线的集合
    QTimer *m_timer;

};
#endif // SERIAL_H

三、UI界面

在这里插入图片描述

三、曲线的产生

1.Qt Charts组件的使用

在serial.pro加上charts,按Ctril+S进行保存,可能会报错。解决方案:解决思路链接
在这里插入图片描述
在这里插入图片描述
在确认.pro文件中添加了相应语句并保存之后,需要在程序头文件中添加

#include <QtCharts>
using namespace QtCharts;

2.chart源文件

#include "serial.h"

void serial::ChartInit()
{
    m_chart = new QChart();
    m_chartView = new QChartView(m_chart,this);//画布
    m_chart = m_chartView->chart();//画笔
    m_chartView->setRubberBand(QChartView::NoRubberBand);  //矩形缩放
    m_chartView->setRenderHint(QPainter::Antialiasing); //设置抗锯齿

    //设置x轴
    axisX = new QValueAxis;
    axisY = new QValueAxis;
    axisX->setRange(0, 10);         //坐标系区间
    axisY->setRange(-1, 1);
    axisX->setLabelFormat("%d");    //坐标轴下标的数字类型
    axisY->setLabelFormat("%0.2f");
    axisX->setGridLineVisible(true);//是否显示网格
    axisY->setGridLineVisible(true);
    axisX->setTickCount(10+1);       //设置坐标轴区间格数
    axisY->setTickCount(10+1);
    axisX->setMinorTickCount(5);    //小刻度
    axisX->setTitleText("x");       //x轴名称
    axisY->setTitleText("距离cm");

    //设置图表
    m_chart->addAxis(axisX, Qt::AlignBottom);  //将x坐标轴加到chart上,居下
    m_chart->addAxis(axisY, Qt::AlignLeft);    //将y坐标轴加到chart上,居左
    m_chart->setTitle("y = sin(x)");   //设置图表标题
    m_chart->legend()->hide();  //设置图例不可见
    m_chart->legend()->setLayoutDirection(Qt::LeftToRight);
    m_chart->legend()->setAlignment(Qt::AlignLeft);

    //设置曲线
    series = new QSplineSeries(this);   //平滑曲线的集合
    series->setName(QString("y=sinx")); //设置曲线对应的名字,用于图例显示
    m_chart->addSeries(series);         //将曲线增入chart中
    series->attachAxis(axisX);          //将曲线与轴对应起来
    series->attachAxis(axisY);

    //将图表添加进控件
    ui->verticalLayout_2->addWidget(m_chartView);

    //以定时器推动
    m_timer = new QTimer(this);
    m_timer->start(100);
    connect(m_timer,SIGNAL(timeout()),this,SLOT(updatechart()));
}


void serial::updatechart()
{
    axisX->setRange(0,points*0.1);
    series->append(points*0.1,sin(points*0.1));
    points++;
}

  • QSplineSeries: 用于创建有由一系列数据组成的曲线.类似的还有QPieSeries(饼图数据). QLineSeries(折线数据)。
  • QChart: 图表界面,用来管理图表内容,颜色,大小等。
  • QChartView: 负责显示QChart。

通过对应的函数设置坐标轴参数、图标参数、曲线参数。
在这里插入图片描述
通过上述代码将图表添加到控件,这个控件对应的位置如下图箭头所示,就是个layout控件。
在这里插入图片描述
到了这一步还没开始通过串口读取数据,所以自己用定时器先产生数据模拟串口数据,通过updatechart函数不断更新数据。
在这里插入图片描述
通过setRange函数不断拓宽x轴范围,通过appedf函数给曲线增加新的点。

3. 初步实现效果

在这里插入图片描述
下一步完成串口的设置,并将串口读取的数据显示出来。

四、串口设置

1.准备工作

在pro文件添加serialport。
在这里插入图片描述
添加对应头文件,在上面可以复制。
在这里插入图片描述
对象初始化函数包含一个串口初始化函数,一个图标初始化函数。

serial::serial(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::serial)
{
    ui->setupUi(this);

    //串口初始化
    system_init();

    //图表初始化
    ChartInit();

}

2.用户系统初始化函数

//用户系统初始化
void serial::system_init()
{
    //清空端口所有选项
    ui->cmd_port_name->clear();

    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        //将可用串口添加到端口显示框
        ui->cmd_port_name->addItem(info.portName());
    }

    //设置串口状态标签为红色 表示未连接状态
    ui->lab_status->setStyleSheet("color:red");

    //check port 检测通讯端口
    connect(ui->btn_serial,&QPushButton::clicked,this,&serial::btn_serial_check);
    //open port 打开选择端口
    connect(ui->btn_open,&QPushButton::clicked,this,&serial::btn_open_port);

    //receive data 串口数据接收完触发对应槽函数
    connect(&global_port,&QSerialPort::readyRead,this,&serial::receive_data);

    //clear recevie 清除接收文本框的内容
    connect(ui->btn_clear,&QPushButton::clicked,this,&serial::btn_clear_rev);

}

在标准C++中,并没有foreach关键字。但是在QT中,可以使用这一个关键字,其主要原因是QT自己增加了这一个关键字,就像slots和signals、emit等一样。增加的foreach关键字在编译时会进行预处理。
其用法为:foreach (varItem , Items) // foreach(variable ,container)

availablePorts函数:,以QList数据类型返回系统可用的串口清单。
addItem函数:是组合框QComboBox类的函数,将函数带着的文本增加至组合框内的选项中。
setStyleSheet函数:设置指定样式。

利用connect函数,将【检测通讯端口】【打开】【清除】按键的clicked信号与对应的槽函数连接在一起。

3.检测通讯端口槽函数

和系统初始化函数里面的操作是一样的,就是更新端口。

void serial::btn_serial_check(bool)
{
    ui->cmd_port_name->clear();
    //通过QSerialPortInfo查找可用串口
    foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        //将可用串口添加到端口显示框
        ui->cmd_port_name->addItem(info.portName());
    }
}

4.打开选择端口槽函数

void serial::btn_open_port(bool)
{
    //port name 设置端口
    global_port.setPortName(ui->cmd_port_name->currentText());
    //baud rate 设置波特率为115200
   global_port.setBaudRate(QSerialPort::Baud115200);
    //parity 设置无校验位
    global_port.setParity(QSerialPort::NoParity);
    //data bits 设置数据位8位
    global_port.setDataBits(QSerialPort::Data8);
    //stop bits 设置停止位1位
    global_port.setStopBits(QSerialPort::OneStop);

    //port open 打开选择端口
    bool ret = global_port.open(QIODevice::ReadWrite);

    if(ret){
        //打开成功更新状态
        ui->lab_status->setText("Connected");
        //设置串口状态标签为绿色 表示已连接状态
        ui->lab_status->setStyleSheet("color:green");
    }
}

cmd_port_name是选择端口号那个组合框,currentText表示当前端口号的名称。

因为应用场景固定,所以直接给定了串口的格式要求,而通过组合框不需要选择。通过QSerialPort类的函数进行波特率、校验位、数据位、停止位的设定。

open函数:通过固定模式打开串口,成功返回true,否则返回false。模式必须是 QIODevice::ReadOnly, QIODevice::WriteOnly, or QIODevice::ReadWrite.,其他模式不支持。这里我们选择是读写模式。

最后对返回值ret进行判断,连接成功则将状态栏文本改为“Connected”,颜色也改为绿色。

5.关闭选择端口槽函数

void serial::btn_close_port(bool)
{

    global_port.close();

    //关闭端口后显示状态
    ui->lab_status->setText("DisConnected");
    ui->lab_status->setStyleSheet("color:red");
}

colse函数和open函数是对应的,一个打开,一个关闭。

6.数据更新函数和清除文本函数

//接收数据槽函数,显示对应曲线
float max=0;
void serial::receive_data(void)
{
    QByteArray array = global_port.readAll();
    QString str_rev;


    //更新曲线显示
    if(array.toFloat()>max) //寻找Y轴最大值
        max=array.toFloat();
    axisY->setRange(0,max+2);
    axisX->setRange(0,points);
    series->append(points,array.toFloat());
    points++;
    //qDebug() << array.toFloat();


    //文本框显示
    if(ui->chk_rev_time->checkState() == Qt::Checked) //是否显示时间
    {
        //获取当前系统时间
        QDateTime nowtime = QDateTime::currentDateTime();
        //时间转换为字符串格式
        str_rev = "[" + nowtime.toString("yyyy-MM-dd hh:mm:ss") + "] ";
        //加上接收数据 转换为16进制并空格分开 接收数据换行
        str_rev += QString(array).append("\r\n");
    }
    else
    {
        str_rev += QString(array).append("\r\n");
    }
    ui->pte_rcv->insertPlainText(str_rev);  //将字符串添加到显示文本框

}

//清空接收文本框槽函数
void serial::btn_clear_rev(bool)
{
    ui->pte_rcv->clear();
}

通过QByteArray数据类型承接串口数据,然后通过toFloat函数转换为float数据类型的数值,通过append函数添加到曲线当中去。

文本方面通过insertPlainText函数添加字符串,通过clear函数删除字符串。

pte_ecv控件就是那个多行编辑框控件,如下图。
在这里插入图片描述

7.其他修正

在这里插入图片描述
测试用的定时器可以注释或删除,更新函数updatechart也可以删除。
在这里插入图片描述
将设置坐标轴范围的代码注释,因为这是y=sinx曲线的范围,对应超声波显示已经不适用了。
在这里插入图片描述
通过单片机printf函数随机发送float数据类型数据。

QT中foreach的使用
Qt绘制实时曲线图形简单例程 - Qt实时绘图

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:33:50  更:2021-11-10 12:34:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 8:49:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码