jsp商业网站开发,网站建设外包,网站建设工具有哪些品牌,WordPress论坛用哪些**使用QT在串口调试助手基础上实现波形显示#xff08;含源码#xff09;
评论比较多留言需要源码的#xff0c;逐个发邮箱比较麻烦也不能及时回复#xff0c;现将源码上传至链接#xff08;无需积分下载#xff09;https://download.csdn.net/download/m0_51294753/877…**使用QT在串口调试助手基础上实现波形显示含源码
评论比较多留言需要源码的逐个发邮箱比较麻烦也不能及时回复现将源码上传至链接无需积分下载https://download.csdn.net/download/m0_51294753/87743394下载不下来可以私信我留邮箱。
一、前言
背景使用ADS1255对模拟信号进行采样并将转换的数据通过串口发送给电脑使用QT编写上位机软件接收串口数据并实现采样波形的显示。因为没有具体的需求只是进行简单测试程序不尽完善简单记录一下过程方便刚接触的同伴一起学习。
二、测试效果
界面是在串口助手基础上改的具有串口调试助手的基本功能加了一个折线图显示但是重新整理了上次串口的程序显示效果如下 20230302_104834 采样的板子设计的不太好模拟输入端开路时本底噪声基本在0.6mV左右设计输入电压是±2.5V。采用的串口输入波特率为1500000输入的数据具有固定的格式数据输入形式如下 三、实现过程遇到的问题
使用QT的serialport 和 charts库简单过程不再说明源程序在文末给出下面简述一下我在实现中遇到的问题
1.串口的定时扫描和串口名更新
原本只在程序开始时进行串口扫描但随后发现如果设备在程序运行后就检测不到串口串口如果被占用也得不到更新。通过定时器和关联槽函数来定时500ms扫描串口但是串口禁用那行代码还没整明白是怎么回事有知道的欢迎在评论区告诉我具体实现看源代码。
for(int i 0;iportStringList.size();i)
{serial-setPortName(portStringList[i]);if(serial-open(QIODevice::ReadWrite))ui-comboSerialPort-addItem(portStringList.at(i));else{ui-comboSerialPort-addItem(portStringList.at(i) (不可用));ui-comboSerialPort-setItemData(i,(QVariant)0,Qt::UserRole-1); //串口禁用}serial-close();
}2.图表显示的内容需要移动类似示波器的显示波形
对于横坐标我是通过固定横坐标时间的宽度改变横坐标的坐标范围来实现的比如数据输出速率为10固定横坐标只显示50个点则设置横坐标宽度为5。 t 0.1;qreal value valueStr.toDouble();serices0-append(t,value);if(t50)axisX-setRange(t-50,t);对于纵坐标通过一个链表把图表显示的50个数据存储起来再用类似队列的方式先入先出的方式更新队列找出队列的最大值和最小值更新纵坐标的坐标范围 if(listvalue.size()500)listvalue.push_front(value);else{listvalue.pop_back();listvalue.push_front(value);}qreal minvalue *std::min_element(listvalue.begin(),listvalue.end());qreal maxvalue *std::max_element(listvalue.begin(),listvalue.end());axisY-setRange(minvalue-0.00001,maxvalue0.00001);3.把数据从发送的字符串中截取出来显示
没想到太好的办法目前是需要注意发送字符串的形式按着字符串形式更改程序比如下位机发送的类型是value0.0000000V可以利用字符串截取函数把中间的数据单独拿出来因为我下位机发送的数据宽度固定所以我是使用mid函数直接截取如果长度 不一致也可以用split函数将数据与文本割裂开。 receiveBuff serial-readAll();receiveBytes receiveBuff.length();QByteArray valueStr;valueStr receiveBuff.mid(QString(value:).size(),QString(-0.000000).size());4.设置坐标轴的问题
给图表中序列赋坐标轴的时候常用到这样一段代码
chart-setAxisX(axisX,serices0);
chart-setAxisY(axisY,serices0);但一般都会警告该代码已过时推荐使用addAxis函数替代于是改成
chart-addAxis((QAbstractAxis*)axisX,Qt::AlignBottom); chart-addAxis((QAbstractAxis*)axisY,Qt::AlignLeft);
黄色警告消失了编译也没有错误但是运行起来坐标轴有些许问题还没明白怎么回事。
四、程序代码
1.pro项目文件主要是添加两行核心库和资源文件
QT core gui
QT serialport
QT chartsgreaterThan(QT_MAJOR_VERSION, 4): QT widgetsCONFIG c11# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES QT_DISABLE_DEPRECATED_BEFORE0x060000 # disables all the APIs deprecated before Qt 6.0.0SOURCES \main.cpp \mainwindow.cppHEADERS \mainwindow.hFORMS \mainwindow.ui# Default rules for deployment.
qnx: target.path /tmp/$${TARGET}/bin
else: unix:!android: target.path /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS targetRESOURCES \res.qrc
2.ui设计文件按照自己需求布局给控件命名 3.h文件一些变量和函数声明
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include QMainWindow
#include QtCharts
#include QSerialPort
#include QSerialPortInfo
#include QStringList
#include QMessageBox
#include QFileDialog
#include QListusing namespace QtCharts;QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow();private:Ui::MainWindow *ui;private:qreal t;QChart *chart;QLineSeries *serices0;QValueAxis *axisX,*axisY;QSerialPort *serial; //串口端口QStringList portStringList; //端口链表QTimer *timer; //定时器QByteArray sendBuff,receiveBuff; //发送、接收缓存区long int sendBytes,receiveBytes; //发送、接收字节数QList qreal listvalue;void InitSerialPort();void InitChart();private slots:void serialPort_readyRead();void portTimerEvent();void on_btnOpenSerial_clicked();void on_btnSend_clicked();void on_btnClearRevBuff_clicked();void on_btnSaveFile_clicked();void on_btnOpenFile_clicked();void on_btnClearSendBuff_clicked();void on_btnResetCount_clicked();void on_chkFixedSend_clicked();void on_lineEditTime_editingFinished();void on_textEditRev_textChanged();
};
#endif // MAINWINDOW_H
4.c文件函数功能实现
#include mainwindow.h
#include ui_mainwindow.hMainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui-setupUi(this);t 0;sendBytes 0;receiveBytes 0;chart new QChart();serices0 new QLineSeries();axisX new QValueAxis();axisY new QValueAxis();timer new QTimer();serial new QSerialPort(this);QTimer *portTimer new QTimer(this);connect(portTimer,SIGNAL(timeout()),this,SLOT(portTimerEvent()));connect(serial,SIGNAL(readyRead()),this,SLOT(serialPort_readyRead()));InitSerialPort();InitChart();portTimer-start(500);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::InitSerialPort()
{ui-comboSerialPort-clear();portStringList.clear();foreach(const QSerialPortInfo info, QSerialPortInfo::availablePorts())portStringList info.portName();for(int i 0;iportStringList.size();i){serial-setPortName(portStringList[i]);if(serial-open(QIODevice::ReadWrite))ui-comboSerialPort-addItem(portStringList.at(i));else{ui-comboSerialPort-addItem(portStringList.at(i) (不可用));ui-comboSerialPort-setItemData(i,(QVariant)0,Qt::UserRole-1); //串口禁用}serial-close();}ui-comboBaudRate-setCurrentIndex(5);ui-comboDataBits-setCurrentIndex(3);ui-comboParity-setCurrentIndex(2);ui-comboStop-setCurrentIndex(0);ui-btnSend-setEnabled(false);ui-chkFixedSend-setEnabled(false);ui-lineEditTime-setEnabled(false);ui-lineEditTime-setText(1000);ui-radioTextReceive-setChecked(Qt::Checked);ui-radioTextSend-setChecked(Qt::Checked);
}void MainWindow::InitChart()
{ui-chartView-setChart(chart);QMargins mgs(5,5,5,5);chart-setMargins(mgs);chart-setTitle(数据曲线);//创建折线序列serices0-setName(时间-电压曲线);chart-addSeries(serices0);//创建坐标轴axisX-setRange(0,5);axisX-setTitleText(time(secs));axisY-setRange(-2,2);axisY-setTitleText(value);chart-setAxisX(axisX,serices0);chart-setAxisY(axisY,serices0);//chart-addAxis((QAbstractAxis*)axisX,Qt::AlignBottom);//chart-addAxis((QAbstractAxis*)axisY,Qt::AlignLeft);
}void MainWindow::serialPort_readyRead()
{QByteArray lastStr;if(!ui-radioStopReceive-isChecked()){lastStr ui-textEditRev-toPlainText().toUtf8();receiveBuff serial-readAll();receiveBytes receiveBuff.length();QByteArray valueStr;valueStr receiveBuff.mid(QString(value:).size(),QString(-0.000000).size());t 0.1;qreal value valueStr.toDouble();serices0-append(t,value);if(t50)axisX-setRange(t-50,t);if(listvalue.size()500)listvalue.push_front(value);else{listvalue.pop_back();listvalue.push_front(value);}qreal minvalue *std::min_element(listvalue.begin(),listvalue.end());qreal maxvalue *std::max_element(listvalue.begin(),listvalue.end());axisY-setRange(minvalue-0.00001,maxvalue0.00001);ui-labRevBytesCount-setText(QString::number(receiveBytes));if(ui-radioHexReceive-isChecked()){receiveBuff receiveBuff.toHex().toUpper();int length receiveBuff.length();for(int i 0;ilength/2;i)receiveBuff.insert((23*i), QByteArray( ));}lastStr lastStr.append(receiveBuff);ui-textEditRev-setText(lastStr);}elseserial-clear(QSerialPort::Input);
}void MainWindow::portTimerEvent()
{QStringList newPortStringList;newPortStringList.clear();foreach(const QSerialPortInfo info,QSerialPortInfo::availablePorts())newPortStringList info.portName();if(newPortStringList.size() ! portStringList.size()){portStringList newPortStringList;ui-comboSerialPort-clear();ui-comboSerialPort-addItems(portStringList);}
}void MainWindow::on_btnOpenSerial_clicked()
{if(ui-btnOpenSerial-text() QString(打开串口)){//串口设置serial-setPortName(ui-comboSerialPort-currentText());serial-setBaudRate(ui-comboBaudRate-currentText().toInt());switch(ui-comboDataBits-currentText().toInt()){case 5: serial-setDataBits(QSerialPort::Data5);break;case 6: serial-setDataBits(QSerialPort::Data6);break;case 7: serial-setDataBits(QSerialPort::Data7);break;case 8: serial-setDataBits(QSerialPort::Data8);break;default: serial-setDataBits(QSerialPort::UnknownDataBits);}switch(ui-comboParity-currentIndex()){case 0: serial-setParity(QSerialPort::EvenParity);break;case 1: serial-setParity(QSerialPort::MarkParity);break;case 2: serial-setParity(QSerialPort::NoParity);break;case 3: serial-setParity(QSerialPort::OddParity);break;default: serial-setParity(QSerialPort::UnknownParity);}switch (ui-comboStop-currentIndex()){case 0: serial-setStopBits(QSerialPort::OneStop);break;case 1: serial-setStopBits(QSerialPort::OneAndHalfStop);break;case 2: serial-setStopBits(QSerialPort::TwoStop);break;default: serial-setStopBits(QSerialPort::UnknownStopBits);}serial-setFlowControl(QSerialPort::NoFlowControl);if(!serial-open(QIODevice::ReadWrite)){QMessageBox::warning(this,提示,无法打开串口,QMessageBox::Ok);return;}ui-comboSerialPort-setEnabled(false);ui-comboBaudRate-setEnabled(false);ui-comboDataBits-setEnabled(false);ui-comboParity-setEnabled(false);ui-comboStop-setEnabled(false);ui-btnSend-setEnabled(true);ui-chkFixedSend-setEnabled(true);ui-lineEditTime-setEnabled(true);ui-btnOpenSerial-setText(关闭串口);}else{serial-close();ui-comboSerialPort-setEnabled(true);ui-comboBaudRate-setEnabled(true);ui-comboDataBits-setEnabled(true);ui-comboParity-setEnabled(true);ui-comboStop-setEnabled(true);ui-btnSend-setEnabled(false);ui-chkFixedSend-setEnabled(false);ui-lineEditTime-setEnabled(false);ui-btnOpenSerial-setText(打开串口);}
}void MainWindow::on_btnSend_clicked()
{sendBuff ui-textEditSend-toPlainText().toUtf8();if(ui-radioHexSend-isChecked())sendBuff QByteArray::fromHex(sendBuff);if(ui-chkLineFeed-isChecked())sendBuff \n;serial-write(sendBuff);sendBytes sendBuff.length();ui-labSendBytesCount-setText(QString::number(sendBytes));ui-textEditSend-moveCursor(QTextCursor::End);
}void MainWindow::on_btnClearRevBuff_clicked()
{ui-textEditRev-clear();
}void MainWindow::on_btnSaveFile_clicked()
{QString curPath QDir::currentPath();QString dlgTilte 保存文件;QString filter 文本文件(*.txt);;所有文件(*.*);QString fileName QFileDialog::getSaveFileName(this,dlgTilte,curPath,filter);if(fileName.isEmpty())return;QFile file(fileName);if(!file.open(QIODevice::ReadWrite | QIODevice::Text))QMessageBox::warning(this,文档编辑器,tr(无法写入文件 %1:\n%2).arg(fileName,file.errorString()));QTextStream stream(file);stream.setAutoDetectUnicode(true);streamui-textEditRev-toPlainText().toUtf8();file.close();
}void MainWindow::on_btnOpenFile_clicked()
{QString curPath QDir::currentPath();QString dlgTilte 打开文件;QString filter 文本文件(*.txt);;所有文件(*.*);QString fileName QFileDialog::getOpenFileName(this,dlgTilte,curPath,filter);if(fileName.isEmpty())return;QFile file(fileName);if(!file.open(QIODevice::ReadWrite | QIODevice::Text))QMessageBox::warning(this,文档编辑器,tr(无法读取文件 %1:\n%2).arg(fileName,file.errorString()));ui-textEditSend-setText(file.readAll());file.close();
}void MainWindow::on_btnClearSendBuff_clicked()
{ui-textEditSend-clear();
}void MainWindow::on_btnResetCount_clicked()
{receiveBytes 0;sendBytes 0;ui-labRevBytesCount-setText(QString::number(receiveBytes));ui-labSendBytesCount-setText(QString::number(sendBytes));
}void MainWindow::on_chkFixedSend_clicked()
{if(ui-chkFixedSend-isChecked()){int fixedTime ui-lineEditTime-text().toInt();timer-start(fixedTime);connect(timer,SIGNAL(timeout()),this,SLOT(on_btnSend_clicked()));}else{timer-stop();}
}void MainWindow::on_lineEditTime_editingFinished()
{on_chkFixedSend_clicked();
}void MainWindow::on_textEditRev_textChanged()
{ui-textEditRev-moveCursor(QTextCursor::End);
}
程序基本框架和上一篇发文的基于QT5实现串口调试助手没太大区别只是修改了一下控件的命名便于理解把上次冗余的部分代码变简洁一下加入了图表。程序需要自行理解修改一下才能运行否则下位机发来的数据与此次字符串格式不一致会使程序发生错误或强制退出。刚入门还存在诸多问题请各位见谅。