概要
本人也是借鉴其他人的思路,并按照自己的想法加以改进。我采用的Qt环境是6.2.4MinGW 64-bit,需要事先安装好Qt Serial Port串口模块,Qt Charts图表模块,
如果没有配置好,跟着下面的操作就行
在QT安装路径下找到MaintenanceTool.exe双击进去
进入到这个界面
本人用的是qt6.2.4版本的,需要在6.2.4里找到Qt Serial Port和Qt Charst这两个模块,打勾后,就可以选择下一步了,然后等待更新完成后即可 (切记,版本的模块要对应版本的编译器)
安装完串口模块后就点击工程里的.pro文件 在里面添加QT += serialport 和Qt +=charts 然后点那个小锤子编译不运行,告诉编译器你要添加这个模块
环境配置好以后,先说一下思路,先写好串口的代码,然后在用QChart这个类,根据串口传来的数据来画图。
串口的基本属性有 端口号、波特率、停止位,校验位,流控(一般设置为无),用下拉框来选择串口的属性。
首先打开软件后,软件会先检测一下是否有串口设备接入,将接入设备的串口号显示在下拉框,定义一个字节数组来存放串口传过来的数据,并选择以文本还是16进制显示。
#include <QSerialPort> //提供访问串口的功能
#include <QSerialPortInfo> //提供系统中存在的串口的信息
//打开软件后,获取串口的端口号
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comboBox->addItem(info.portName()); //保存在下拉框里
}
//连接,接收串口的数据
QObject::connect(&serial, &QSerialPort::readyRead, this,&MainWindow::serialPort_readyRead);
//将串口的数据存放在字符数组里面
QByteArray buffer = serial.readAll();
//让数据以文本还是16进制显示
if(ui->comboBox_6->currentText()=="文本模式")
{
recv = ui->textEdit->toPlainText();
recv += QString(buffer);
//清空以前的显示
ui->textEdit->clear();
//重新显示
ui->textEdit->append(recv);
}else
{
// 16进制显示,并转换为大写
// 添加空格
QString str2; //转换成HEX的数据
for(int i = 0; i<str1.length (); i+=2)
{
str2 += str1.mid (i,2);
str2 += " ";
}
//清空以前的显示
ui->textEdit->clear();
//重新显示
ui->textEdit->append(str2);
}
下面是配置串口属性的代码,根据下拉框配置串口属性
if(ui->pushButton_4->text()==QString("打开串口"))
{
//设置串口名
serial.setPortName(ui->comboBox->currentText());
//设置波特率
serial.setBaudRate(ui->comboBox_2->currentText().toInt());
//设置数据位数
switch(ui->comboBox_3->currentIndex())
{
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: break;
}
//设置奇偶校验
QSerialPort::Parity checkBits;
if(ui->comboBox_5->currentText()=="无")
{
checkBits=QSerialPort::NoParity;
}else if(ui->comboBox_5->currentText()== "奇校验")
{
checkBits=QSerialPort::OddParity;
}else {
checkBits=QSerialPort::EvenParity;
}
serial.setParity(checkBits);
//设置停止位
switch(ui->comboBox_4->currentIndex())
{
case 1: serial.setStopBits(QSerialPort::OneStop); break;
case 2: serial.setStopBits(QSerialPort::TwoStop); break;
default: serial.setStopBits(QSerialPort::OneAndHalfStop);break;
}
//设置流控制
serial.setFlowControl(QSerialPort::NoFlowControl);
//打开串口
if(!serial.open(QIODevice::ReadWrite))
{
QMessageBox::about(NULL,"提示","无法打开串口!");
return;
}
//下拉菜单控件失能
ui->comboBox->setEnabled(true);
ui->comboBox_2->setEnabled(false);
ui->comboBox_3->setEnabled(false);
ui->comboBox_4->setEnabled(false);
ui->comboBox_5->setEnabled(false);
ui->pushButton_4->setText(QString("关闭串口"));
ui->pushButton_2->setEnabled(true);
//发送按键使能
ui->pushButton_2->setEnabled(true);
}
else
{
//关闭串口
serial.close();
//下拉菜单控件使能
ui->comboBox->setEnabled(true);
ui->comboBox_2->setEnabled(true);
ui->comboBox_3->setEnabled(true);
ui->comboBox_4->setEnabled(true);
ui->comboBox_5->setEnabled(true);
ui->pushButton_4->setText(QString("打开串口"));
//发送按键失能
ui->pushButton_2->setEnabled(false);
}
串口发送代码 (可以选择是文本数据发送还是字节数据发送)
//发送数据
void MainWindow::on_pushButton_3_clicked()
{
QByteArray data;
if(ui->comboBox_8->currentText()=="文本模式"){
//array = QString2Hex(data); //HEX 16进制
data = ui->textEdit_2->toPlainText().toUtf8();
}else{
//array = data.toLatin1(); //ASCII
data = ui->textEdit_2->toPlainText().toLocal8Bit();
}
//获取界面上的数据并转换成utf8格式的字节流
// QByteArray data = ui->textEdit_2->toPlainText().toUtf8();
// QByteArray data = ui->textEdit_2->toPlainText().;
}
这样就差不多了,就串口发送数据,接收数据,串口配置,数据显示就完了。
串口配置好以后,就来配置曲线显示 有以下配置:先配置曲线对象,然后Charts绑定曲线,(我个人的理解是Charts相当于一个容器,我们要把曲线给添加进去),然后给配置容器配置,有无网格、多少个间隔,范围。
#include <QScatterSeries> //画点状曲线头文件
#include <QtCharts/QLineSeries> //画线曲线头文件
#include <QtCharts/QValueAxis> //画坐标轴头文件
#include <QtCharts/QChartView> //画绘图区域头文件
#include <QtCore/QTimer> //时间定时器头文件
#include <QtWidgets/QGesture> //手势头文件(鼠标动作)
#include <QtWidgets/QGraphicsScene> //绘图屏幕参数头文件
#include <QtCharts>
//创建曲线对象
QLineSeries *serices0; //曲线一
QLineSeries *serices1; //曲线二
QLineSeries *serices2; //曲线三
qint32 X_Rang; //X轴的范围
qint32 Y_Rang; //Y轴的范围
double fenbianlv; //X轴的分辨率
ui->ChartView->setChart(chart);
QMargins mgs(1,1,1,1);
chart->setMargins(mgs);
//创建折线序列
serices0->setName("曲线一");
serices1->setName("曲线二");
serices2->setName("曲线三");
chart->addSeries(serices0);
chart->addSeries(serices1);
chart->addSeries(serices2);
//创建坐标轴
axisX->setRange(0,5); //设置X轴的范围
axisX->setTitleText("time(secs)"); //X轴的标签
axisX->setTickCount(20); //设置20个间隔
axisX->setMinorTickCount(5); //设置每个间隔里有多少个网格
axisY->setRange(-100,100); //设置y的范围
axisY->setTitleText("Value"); //设置标题
axisY->setTickCount(7);
axisY->setMinorTickCount(4); //设置每个间隔里有多少个网格
//绑定X,Y轴的数据
//曲线一
chart->setAxisX(axisX,serices0);
chart->setAxisY(axisY,serices0);
//曲线二
chart->setAxisX(axisX,serices1);
chart->setAxisY(axisY,serices1);
//曲线三
chart->setAxisX(axisX,serices2);
chart->setAxisY(axisY,serices2);
设置曲线的x轴,y轴的数据。x轴我们设置成时间,y轴可以设置成串口接收的数据。代码如下
一般我们把x轴设置成时间,y轴数据随着x轴时间变化而变化,下面这两句是时间以多少步长增长
fenbianlv=ui->doubleSpinBox->value();
t += fenbianlv;
//下面是一条曲线的配置
要想让曲线有流动的效果,x的范围随着x轴时间的增加而增加。y轴的范围增加而增加
if(ui->quxian1->isChecked()==true)
{
//serices0->show();
serices0->show();
if(t>X_Rang)
// axisX->setRange(t-2,t+0.5);
axisX->setRange(t-X_Rang,t+(0.5+X_Rang/10));
if(listvalue.size()<=50)
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-Y_Rang,maxvalue+Y_Rang);
}
下面是对串口接收的数据经行差分,因为要想实现多条曲线的显示,数据是 一帧一帧的,我们要从一帧一帧的数据里拆分,我是用@来区分数据的,只需要让串口传过来的数据是以@data1@data2@data3 分别拆分@后面的数据
receiveBytes += receiveBuff.length(); //计算接收到的字节长度
//曲线显示
//前面我们已经把串口接收的数据存入Buff里,接下我们数据经行处理
//该条语句的意思是如果遇见第一个@,就将它后面的数据存放在quxian1里面
quxian1=QString(buffer).section("@",1,1).toDouble();
//该条语句的意思是如果遇见第二个@,就将它后面的数据存放在quxian2里面
quxian2= QString(buffer).section("@",2,2).toDouble();
//该条语句的意思是如果遇见第一个@,就将它后面的数据存放在quxian1里面
quxian3= QString(buffer).section("@",3,3).toDouble();
qreal value = quxian1;
qreal value1 = quxian2;
qreal value2 = quxian3;
X_Rang=ui->X_Rang->value();
Y_Rang=ui->Y_Rang->value();
serices0->append(t,value); //将接收的数据追加到曲线的
serices1->append(t,value1); // append( , ); 第一个填的是x轴的数据,第二个填y轴的数据
serices2->append(t,value2);
本文只讲解了部分代码,需要完整工程的,可以私信我。
算了,反正没人看表情🤡