【Qt学习笔记】(三)--编写上位机软件(ui设置、样式表serialport串口接收数据、Qchart显示波形)

声明:本人水平有限,博客可能存在部分错误的地方,请广大读者谅解并向本人反馈错误。
   这段时间大部分都是在学Qt,前面想着跟着书一章章的学,但是发现这个效率极低,所以就改变了学习的方法,那就是:根据我需要的功能,直接用Qt去做,一边做一边学,于是这篇博客就这样写出来了...

往期回顾:

【Qt学习笔记】(一)--Qt creator软件学习
【Qt学习笔记】(二)--第一个程序"Hello World"(学习Qt中程序的运行、发布、编译过程)

一、需求描述

首先给大家上个目前的效果图(后面还会继续针对这个上位机继续该专栏博客):

1.1 基础功能

① 串口接收数据(使用简单的通信协议);
  ② 保存数据至excel表格;
  ③ 实时显示传感器以及解算的姿态角度;
  ④ 实时显示数据波形图(可以选择要显示的数据);
  ⑤ 实时对传感器数据进行校准并可以利用3D图形显示出来;
  ⑥ 可以使用Allan方差(或者动态Allan方法)对加速度计或陀螺仪进行误差分析;
  ⑦ 可以使用某些算法(自适应扩展卡尔曼滤波、互补滤波、互相关检测等)对传感器的数据进行处理并进行姿态结算;
  目前已经实现的功能为①、③、④,其他功能会在后面逐步实现。
  下面会直接通过代码的分析对已经实现的功能进行分析。

二、Ui文件的设置

2.1 自适应显示器分辨率

之前在做的时候,一直想着可以让窗口自适应显示器的分辨率,但是总是做不出来,最后通过这几天的摸索,终于知道如何去做了,下面整理一下方法:
  首先,一定要利用好水平布局和垂直布局,当然还有格子布局,不过我个人还是比较习惯常用水平和垂直布局,那么接下来一起看看上面上位机的布局如何:
  首先是centerwidget设置为垂直布局,它包含下面两个部分:

  然后再把①部分继续细分布局下去,它里面是一个垂直布局,在垂直布局里放置三个Group Box:

  然后呢,继续细分,把①和③再细说一下,②就是放一个垂直布局,再在垂直布局里放四个按钮即可。
  好了,说回①:它是一个垂直布局,在垂直布局里按顺序放置一个水平布局(串口号+Comb Box)+按钮(搜索串口)+水平布局(波特率、停止位等)+按钮(打开串口):

  再回到前面的③,它其实是一个水平布局,在水平布局里面放置两个垂直布局,再在每个垂直布局各放置12个label:

  这些看似麻烦,其实熟练了感觉就像剥洋葱一样,一层层的剥开就会发现这很简单...
  其实最重要的还是MainWindow的设置:

  同时还要右键MainWindow,选择"布局"中的一个布局方式,我个人常用水平或者垂直(两个都一样,因为它里面只有一个组件):

2.2 添加Chart

这个其实就是Graphic View,把它拖进去之后,右键它,选择"提升为"QChartview:

  下面是代码部分:首先在.pro文件添加下面一行代码:

QT += charts

cpp 复制代码
// 下面三个新建的class要放在.h文件的public部分
    QChart *chart = new QChart();
    QValueAxis *axisX = new QValueAxis;
    QValueAxis *axisY = new QValueAxis;
    
	//创建图表的各个部件
    chart->setTitle("数据波形显示");
    // MainWindow::ui
    ui->serialCurveChart->setChart(chart);
    ui->serialCurveChart->setRenderHint(QPainter::Antialiasing);


    QLineSeries *series0 = new QLineSeries ();
    QLineSeries *series1 = new QLineSeries ();
    QLineSeries *series2 = new QLineSeries ();
    QLineSeries *series3 = new QLineSeries ();
    QLineSeries *series4 = new QLineSeries ();
    QLineSeries *series5 = new QLineSeries ();
    QLineSeries *series6 = new QLineSeries ();
    QLineSeries *series7 = new QLineSeries ();
    QLineSeries *series8 = new QLineSeries ();
    QLineSeries *series9 = new QLineSeries ();
    QLineSeries *series10 = new QLineSeries ();
    QLineSeries *series11 = new QLineSeries ();

    series0->setName("加速度计X轴");
    series1->setName("加速度计Y轴");
    series2->setName("加速度计Z轴");
    series3->setName("陀螺仪X轴");
    series4->setName("陀螺仪Y轴");
    series5->setName("陀螺仪Z轴");
    series6->setName("磁力计X轴");
    series7->setName("磁力计Y轴");
    series8->setName("磁力计Z轴");
    series9->setName("井斜角");
    series10->setName("工具面角");
    series11->setName("磁力计方位角");
    curSeries = series0;
    QPen pen;
    // 加速度计
    pen.setStyle (Qt:: SolidLine);
    pen.setWidth (2);
    pen.setColor (PaleTurquoise1);
    series0->setPen (pen);

    pen.setStyle (Qt::SolidLine);
    pen.setColor(DarkSeaGreen2);
    series1->setPen (pen);

    pen.setStyle (Qt:: SolidLine);
    pen.setWidth (2);
    pen.setColor (SpringGreen1);
    series2->setPen (pen);

    // 陀螺仪
    pen.setStyle(Qt::DashLine);
    pen.setColor(MediumBlue);
    series3->setPen (pen);

    pen.setStyle (Qt:: DashLine);
    pen.setWidth (2);
    pen.setColor (PaleGreen);
    series4->setPen (pen);

    pen.setStyle (Qt::DashLine);
    pen.setColor(IndianRed1);
    series5->setPen (pen);

    // 磁力计
    pen.setStyle (Qt:: DashDotDotLine);
    pen.setWidth (2);
    pen.setColor (DeepPink);
    series6->setPen (pen);

    pen.setStyle (Qt::DashDotDotLine);
    pen.setColor(HotPink1);
    series7->setPen (pen);

    pen.setStyle (Qt::DashDotDotLine);
    pen.setColor(Violet);
    series8->setPen (pen);

    // 姿态角
    pen.setStyle (Qt::DotLine);
    pen.setWidth (2);
    pen.setColor (DodgerBlue1);
    series9->setPen (pen);

    pen.setStyle (Qt::DotLine);
    pen.setColor(SkyBlue1);
    series10->setPen (pen);

    pen.setStyle (Qt::DotLine);
    pen.setColor(LemonChiffon3);
    series11->setPen(pen);


    // 设置背景
    chart->setTheme(QChart::ChartThemeDark);

    chart->addSeries(series0);
    chart->addSeries(series1);
    chart->addSeries(series2);
    chart->addSeries(series3);
    chart->addSeries(series4);
    chart->addSeries(series5);
    chart->addSeries(series6);
    chart->addSeries(series7);
    chart->addSeries(series8);
    chart->addSeries(series9);
    chart->addSeries(series10);
    chart->addSeries(series11);


    curAxis = axisX;
    axisX->setRange (0, maxNumber);
    axisX->setLabelFormat("%d");
    axisX->setTickCount (11);
    axisX->setMinorTickCount(4);
    axisX->setTitleText("采样点");

    axisY->setRange(axisY_Min-100, axisY_Max+100);  //设置Y轴最大最小值
    axisY->setLabelFormat("%.2f");
    axisY->setTitleText("value");
    axisY->setTickCount (5);
    axisY->setMinorTickCount (4);

    chart->addAxis(axisX, Qt::AlignBottom);
    chart->addAxis(axisY, Qt::AlignLeft);

    chart->setAxisX(axisX, series0); // x****
    chart->setAxisX(axisX, series1); //WWx
    chart->setAxisX(axisX, series2); // x****
    chart->setAxisX(axisX, series3); //WWx
    chart->setAxisX(axisX, series4); // x****
    chart->setAxisX(axisX, series5); //WWx
    chart->setAxisX(axisX, series6); // x****
    chart->setAxisX(axisX, series7); //WWx
    chart->setAxisX(axisX, series8); // x****
    chart->setAxisX(axisX, series9); //WWx
    chart->setAxisX(axisX, series10); // x****
    chart->setAxisX(axisX, series11); //WWx

    chart->setAxisY(axisY, series0); //WY
    chart->setAxisY(axisY, series1); //WY
    chart->setAxisY(axisY, series2); //WY
    chart->setAxisY(axisY, series3); //WY
    chart->setAxisY(axisY, series4); //WY
    chart->setAxisY(axisY, series5); //WY
    chart->setAxisY(axisY, series6); //WY
    chart->setAxisY(axisY, series7); //WY
    chart->setAxisY(axisY, series8); //WY
    chart->setAxisY(axisY, series9); //WY
    chart->setAxisY(axisY, series10); //WY
    chart->setAxisY(axisY, series11); //WY

2.3 样式表

原始的控件是很丑的,所以想要界面好看,那就得自己做一个(或者找一个样式表),下面是我目前在用的样式表:

cpp 复制代码
/*
Dark Console Style Sheet for QT Applications
Author: Jaime A. Quiroga P.
Company: GTRONICK
Last updated: 24/05/2018, 17:12.
Available at: https://github.com/GTRONICK/QSS/blob/master/ConsoleStyle.qss
*/
QWidget {
	background-color:rgb(0, 0, 0);
	color: rgb(240, 240, 240);
	border-color: rgb(58, 58, 58);
}

QPlainTextEdit {
	background-color:rgb(0, 0, 0);
	color: rgb(200, 200, 200);
	selection-background-color: rgb(255, 153, 0);
	selection-color: rgb(0, 0, 0);
}

QTabWidget::pane {
    	border-top: 1px solid #000000;
}

QTabBar::tab {
 	background-color:rgb(0, 0, 0);
 	border-style: outset;
	border-width: 1px;
	border-right-color: qlineargradient(spread:pad, x1:0.4, y1:0.5, x2:0.6, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-left-color: qlineargradient(spread:pad, x1:0.6, y1:0.5, x2:0.4, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
  border-bottom-color: rgb(58, 58, 58);
	border-bottom-width: 1px;
	border-top-width: 0px;
	border-style: solid;
	color: rgb(255, 153, 0);
	padding: 4px;
}

QTabBar::tab:selected, QTabBar::tab:hover {
   color: rgb(255, 255, 255);
   background-color:rgb(0, 0, 0);
   border-color:rgb(42, 42, 42);
   margin-left: 0px;
   margin-right: 0px;
   border-bottom-right-radius:4px;
   border-bottom-left-radius:4px;
}

QTabBar::tab:last:selected {
  background-color:rgb(0, 0, 0);
	border-color:rgb(42, 42, 42);
	margin-left: 0px;
  	margin-right: 0px;
	border-bottom-right-radius:4px;
	border-bottom-left-radius:4px;
}

QTabBar::tab:!selected {
   margin-bottom: 4px;
   border-bottom-right-radius:4px;
   border-bottom-left-radius:4px;
}

QPushButton{
	border-style: outset;
	border-width: 2px;
	border-top-color: qlineargradient(spread:pad, x1:0.5, y1:0.6, x2:0.5, y2:0.4, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-right-color: qlineargradient(spread:pad, x1:0.4, y1:0.5, x2:0.6, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-left-color: qlineargradient(spread:pad, x1:0.6, y1:0.5, x2:0.4, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-bottom-color: rgb(58, 58, 58);
	border-bottom-width: 1px;
	border-style: solid;
	color: rgb(255, 255, 255);
	padding: 6px;
	background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(77, 77, 77, 255), stop:1 rgba(97, 97, 97, 255));
}

QPushButton:hover{
	border-style: outset;
	border-width: 2px;
	border-top-color: qlineargradient(spread:pad, x1:0.5, y1:0.6, x2:0.5, y2:0.4, stop:0 rgba(180, 180, 180, 255), stop:1 rgba(110, 110, 110, 255));
	border-right-color: qlineargradient(spread:pad, x1:0.4, y1:0.5, x2:0.6, y2:0.5, stop:0 rgba(180, 180, 180, 255), stop:1 rgba(110, 110, 110, 255));
	border-left-color: qlineargradient(spread:pad, x1:0.6, y1:0.5, x2:0.4, y2:0.5, stop:0 rgba(180, 180, 180, 255), stop:1 rgba(110, 110, 110, 255));
	border-bottom-color: rgb(115, 115, 115);
	border-bottom-width: 1px;
	border-style: solid;
	color: rgb(255, 255, 255);
	padding: 6px;
	background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(107, 107, 107, 255), stop:1 rgba(157, 157, 157, 255));
}

QPushButton:pressed{
	border-style: outset;
	border-width: 2px;
	border-top-color: qlineargradient(spread:pad, x1:0.5, y1:0.6, x2:0.5, y2:0.4, stop:0 rgba(62, 62, 62, 255), stop:1 rgba(22, 22, 22, 255));
	border-right-color: qlineargradient(spread:pad, x1:0.4, y1:0.5, x2:0.6, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-left-color: qlineargradient(spread:pad, x1:0.6, y1:0.5, x2:0.4, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-bottom-color: rgb(58, 58, 58);
	border-bottom-width: 1px;
	border-style: solid;
	color: rgb(255, 255, 255);
	padding: 6px;
	background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(77, 77, 77, 255), stop:1 rgba(97, 97, 97, 255));
}

QPushButton:disabled{
	border-style: outset;
	border-width: 2px;
	border-top-color: qlineargradient(spread:pad, x1:0.5, y1:0.6, x2:0.5, y2:0.4, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-right-color: qlineargradient(spread:pad, x1:0.4, y1:0.5, x2:0.6, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-left-color: qlineargradient(spread:pad, x1:0.6, y1:0.5, x2:0.4, y2:0.5, stop:0 rgba(115, 115, 115, 255), stop:1 rgba(62, 62, 62, 255));
	border-bottom-color: rgb(58, 58, 58);
	border-bottom-width: 1px;
	border-style: solid;
	color: rgb(0, 0, 0);
	padding: 6px;
	background-color: qlineargradient(spread:pad, x1:0.5, y1:1, x2:0.5, y2:0, stop:0 rgba(57, 57, 57, 255), stop:1 rgba(77, 77, 77, 255));
}

QLineEdit {
	border-width: 1px; border-radius: 4px;
	border-color: rgb(58, 58, 58);
	border-style: inset;
	padding: 0 8px;
	color: rgb(255, 255, 255);
	background:rgb(101, 101, 101);
	selection-background-color: rgb(187, 187, 187);
	selection-color: rgb(60, 63, 65);
}

QProgressBar {
	text-align: center;
	color: rgb(255, 255, 255);
	border-width: 1px; 
	border-radius: 10px;
	border-color: rgb(58, 58, 58);
	border-style: inset;
}

QProgressBar::chunk {
	background-color: qlineargradient(spread:pad, x1:0.5, y1:0.7, x2:0.5, y2:0.3, stop:0 rgba(0, 200, 0, 255), stop:1 rgba(30, 230, 30, 255));
	border-radius: 10px;
}

QMenuBar {
	background:rgb(0, 0, 0);
	color: rgb(255, 153, 0);
}

QMenuBar::item {
  	spacing: 3px; 
	padding: 1px 4px;
  	background: transparent;
}

QMenuBar::item:selected { 
  	background:rgb(115, 115, 115);
}

QMenu {
	border-width: 2px; 
	border-radius: 10px;
	border-color: rgb(255, 153, 0);
	border-style: outset;
}

QMenu::item {
	spacing: 3px; 
	padding: 3px 15px;
}

QMenu::item:selected {
	spacing: 3px; 
	padding: 3px 15px;
	background:rgb(115, 115, 115);
	color:rgb(255, 255, 255);
	border-width: 1px; 
	border-radius: 10px;
	border-color: rgb(58, 58, 58);
	border-style: inset;
}

三、串口接收数据

这部分咱就直接上代码了,目前很多博主大部分都在用,我的呢还是有点小bug的,不过是可以用的。
  首先一定要修改.pro文件,而且要在所需的类里包含serialport的头文件:

c 复制代码
QT += serialport
cpp 复制代码
QString lastPort="",newPort="";

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

    m_serialPort = new QSerialPort;

    QStringList baudrateList,stopList,parityList,dataBitList;

    baudrateList<<"1200"<<"2400"<<"4800"<<"9600"<<"19200"<<"38400"<<"57600"<<"115200";
    ui->baud->addItems(baudrateList);

    stopList<<"1"<<"2";
    ui->stopBit->addItems(stopList);

    parityList<<"NoParity"<<"EvenParity"<<"OddParity"<<"SpaceParity"<<"MarkParity";
    ui->parityBit->addItems(parityList);

    dataBitList<<"5"<<"6"<<"7"<<"8";
    ui->dataBit->addItems(dataBitList);

    // 修改功能区标题:
    ui->functionSelect->setTabText(0,"数据波形显示");
    ui->functionSelect->setTabText(1,"传感器校准");
    ui->functionSelect->setTabText(2,"Allan方差分析");
    ui->functionSelect->setTabText(3,"姿态结算");

    // 获取串口号按钮与box连接
    connect(ui->searchPort,&QPushButton::clicked,this,&MainWindow::getPortNameList);

    connect(m_serialPort,&QSerialPort::readyRead,[=](){
        recvData();//读取数据的函数
    });

    // 设置默认参数
    ui->baud->setCurrentText("115200");
    ui->stopBit->setCurrentText("1");
    ui->dataBit->setCurrentText("8");
    ui->parityBit->setCurrentText("NoParity");

    // 创建图形
    createChart();

}
MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::getPortNameList()
{
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
        newPort = info.portName();
        // newPort和lastPort均为全局变量,保证一个串口只打开一次
        if(newPort != lastPort){
            if(newPort==""){
               ui->searchPort->setText("无串口!");
            }
            else ui->serialPort->addItem(newPort);
            // ui->recieveData->appendPlainText("串口号:"+newPort);
        }
        lastPort = newPort;  // 上一次搜索到的串口号
    }
    if(newPort!=""){
        ui->searchPort->setText("获取串口号:"+ui->serialPort->currentText()+"成功!");
    }
}



void MainWindow::on_openPort_clicked()
{
    if(ui->openPort->text()=="打开串口"){  // 如果此时还未打开串口
        ui->openPort->setText("正在打开串口...");

        m_serialPort->setPortName(ui->serialPort->currentText());// 选择当前串口的名称

       if(!m_serialPort->open(QIODevice::ReadWrite)){  // 打开串口失败
            ui->openPort->setText("串口打开失败!");
            return;
       }

       // 根据当前选择设置串口功能
       // 设置波特率
       switch (ui->baud->currentText().toInt()) {
        case 1200: m_serialPort->setBaudRate(QSerialPort::Baud1200,QSerialPort::AllDirections);break;
        case 2400: m_serialPort->setBaudRate(QSerialPort::Baud2400,QSerialPort::AllDirections);break;
        case 4800: m_serialPort->setBaudRate(QSerialPort::Baud4800,QSerialPort::AllDirections);break;
        case 9600: m_serialPort->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections);break;
        case 19200: m_serialPort->setBaudRate(QSerialPort::Baud19200,QSerialPort::AllDirections);break;
        case 38400: m_serialPort->setBaudRate(QSerialPort::Baud38400,QSerialPort::AllDirections);break;
        case 57600: m_serialPort->setBaudRate(QSerialPort::Baud57600,QSerialPort::AllDirections);break;
        case 115200: m_serialPort->setBaudRate(QSerialPort::Baud115200,QSerialPort::AllDirections);break;
       default:break;
       }

       // 设置校验位
       switch (ui->parityBit->currentIndex()) {
        case 0: m_serialPort->setParity(QSerialPort::NoParity);  break;
        case 1: m_serialPort->setParity(QSerialPort::EvenParity);  break;
        case 2: m_serialPort->setParity(QSerialPort::OddParity);  break;
        case 3: m_serialPort->setParity(QSerialPort::SpaceParity);  break;
        case 4: m_serialPort->setParity(QSerialPort::MarkParity);  break;
       default:break;
       }

       // 设置停止位
       switch (ui->stopBit->currentText().toInt()) {
        case 1:m_serialPort->setStopBits(QSerialPort::OneStop);break;
        case 2:m_serialPort->setStopBits(QSerialPort::TwoStop);break;
       default:break;
       }

       //设置数据位
       switch(ui->dataBit->currentText().toInt()){
        case 5: m_serialPort->setDataBits(QSerialPort::Data5);break;
        case 6: m_serialPort->setDataBits(QSerialPort::Data6);break;
        case 7: m_serialPort->setDataBits(QSerialPort::Data7);break;
        case 8: m_serialPort->setDataBits(QSerialPort::Data8);break;
       default:break;
       }

       // 关闭所有box  使其不可选
       ui->baud->setDisabled(1);
       ui->searchPort->setDisabled(1);
       ui->baud->setDisabled(1);
       ui->dataBit->setDisabled(1);
       ui->parityBit->setDisabled(1);
       ui->stopBit->setDisabled(1);
       ui->serialPort->setDisabled(1);
       ui->openPort->setText("关闭串口");

    }

    else if(ui->openPort->text()=="关闭串口"||ui->openPort->text()=="串口打开失败!"){

       // 打开所有box
       ui->baud->setEnabled(1);
       ui->searchPort->setEnabled(1);
       ui->baud->setEnabled(1);
       ui->dataBit->setEnabled(1);
       ui->parityBit->setEnabled(1);
       ui->stopBit->setEnabled(1);
       ui->serialPort->setEnabled(1);

       ui->openPort->setText("打开串口");

       m_serialPort->close();// 记得关闭串口
       //qDebug()<<"1111";

    }
}

char storeData[100];            // 保存数据
int16_t i = 0,displayFlag = 0;         // 数据索引
void MainWindow::recvData()
{
    bool ok;
    int16_t accAndGro_Data[100] = {0};
    QByteArray hexData,G2 ;
    if (m_serialPort->bytesAvailable()) {
        //串口收到的数据可能不是连续的,需要的话应该把数据缓存下来再进行协议解析,类似tcp数据处理
        const QByteArray  recv_data = m_serialPort->readAll();

        if(recv_data.startsWith("\xFF")||displayFlag){
            QString stringHex = recv_data.toHex().toUpper();
            QString textShow;

            // 解析数据:
            for(int j = 0;j<stringHex.length();j++){
                accAndGro_Data[j] = stringHex.mid(2*j,2).toInt(&ok,16);
            }

            // 加速度数据:
            accData[0] = (accAndGro_Data[2]<<8) + accAndGro_Data[3];
            accData[1] = (accAndGro_Data[4]<<8) + accAndGro_Data[5];
            accData[2] = (accAndGro_Data[6]<<8) + accAndGro_Data[7];

            // 陀螺仪数据:
            accData[3] = (accAndGro_Data[8]<<8) + accAndGro_Data[9];
            accData[4] = (accAndGro_Data[10]<<8) + accAndGro_Data[11];
            accData[5] = (accAndGro_Data[12]<<8) + accAndGro_Data[13];

            // 姿态参数:
            accData[6] = (accAndGro_Data[14]<<8) + accAndGro_Data[15]; // 井斜角
            accData[7] = (accAndGro_Data[16]<<8) + accAndGro_Data[17]; // 方位角
            accData[8] = (accAndGro_Data[18]<<8) + accAndGro_Data[19]; // 工具面角

            // 磁力计数据
            accData[9] = (accAndGro_Data[20]<<8) + accAndGro_Data[21];
            accData[10] = (accAndGro_Data[22]<<8) + accAndGro_Data[23];
            accData[11] = (accAndGro_Data[24]<<8) + accAndGro_Data[25];
            // 地磁方位角
            accData[12] = (accAndGro_Data[26]<<8) + accAndGro_Data[27];


            accX_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[0];updataAxisYMaxAndMin(accData[0]);
            accY_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[1];updataAxisYMaxAndMin(accData[1]);
            accZ_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[2];updataAxisYMaxAndMin(accData[2]);

            gyroX_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[3];updataAxisYMaxAndMin(accData[3]);
            gyroY_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[4];updataAxisYMaxAndMin(accData[4]);
            gyroZ_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[5];updataAxisYMaxAndMin(accData[5]);

            magX_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[9];updataAxisYMaxAndMin(accData[9]);
            magY_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[10];updataAxisYMaxAndMin(accData[10]);
            magZ_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[11];updataAxisYMaxAndMin(accData[11]);

            inclina_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[6]/100;updataAxisYMaxAndMin(accData[6]/100);
            toolface_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[8]/100;updataAxisYMaxAndMin(accData[8]/100);
            azimuth_Data[rec_Number - exceedFlag * MAXNUMBER] = accData[7]/100;updataAxisYMaxAndMin(accData[7]/100);


            ui->accX_Data->setNum(accData[0]);
            ui->accY_Data->setNum(accData[1]);
            ui->accZ_Data->setNum(accData[2]);

            ui->gyroX_Data->setNum(accData[3]);
            ui->gyroY_Data->setNum(accData[4]);
            ui->gyroZ_Data->setNum(accData[5]);

            ui->magX_Data->setNum(accData[9]);
            ui->magY_Data->setNum(accData[10]);
            ui->magZ_Data->setNum(accData[11]);

            ui->inclination_Data->setNum(accData[6]/100.0);
            ui->toolFace_Data->setNum(accData[8]/100.0);
            ui->azimuth_Data->setNum(accData[7]/100.0);

            // 更新数据
            serialDataDisplay();

            for(int i=0;i<stringHex.length();i+=2){
               textShow += stringHex.mid(i,2);
               textShow += " ";
            }

            displayFlag = 1;
            if(stringHex.length()>23){
                i=0;
                hexData = 0;
                QDateTime dateTime= QDateTime::currentDateTime();//获取系统当前的时间
                displayFlag =0;
            }
        }
    }
}

四、波形显示

4.1 串口接收数据在chart上以波形显示

话不多说,直接上代码:

cpp 复制代码
void MainWindow::serialDataDisplay()
{
    QLineSeries *series0=(QLineSeries *)ui->serialCurveChart->chart()->series().at(0);
    QLineSeries *series1=(QLineSeries *)ui->serialCurveChart->chart()->series().at(1);
    QLineSeries *series2=(QLineSeries *)ui->serialCurveChart->chart()->series().at(2);
    QLineSeries *series3=(QLineSeries *)ui->serialCurveChart->chart()->series().at(3);
    QLineSeries *series4=(QLineSeries *)ui->serialCurveChart->chart()->series().at(4);
    QLineSeries *series5=(QLineSeries *)ui->serialCurveChart->chart()->series().at(5);
    QLineSeries *series6=(QLineSeries *)ui->serialCurveChart->chart()->series().at(6);
    QLineSeries *series7=(QLineSeries *)ui->serialCurveChart->chart()->series().at(7);
    QLineSeries *series8=(QLineSeries *)ui->serialCurveChart->chart()->series().at(8);
    QLineSeries *series9=(QLineSeries *)ui->serialCurveChart->chart()->series().at(9);
    QLineSeries *series10=(QLineSeries *)ui->serialCurveChart->chart()->series().at(10);
    QLineSeries *series11=(QLineSeries *)ui->serialCurveChart->chart()->series().at(11);

    if(rec_Number>=maxNumber) {
        maxNumber = maxNumber + 2;
        curAxis = axisX;                //
        axisX->setRange (rec_Number-200, maxNumber); //200改为宏定义
    }

    if(rec_Number>=(MAXNUMBER*(exceedFlag+1)-1))  // 数组保存的数据已经超限
    {
        // stopRefreshFlag = 1;
        exceedFlag += 1;
        rec_Number = MAXNUMBER*(exceedFlag);
    }
    else{
        if(dataSelect[0]) series0->append(rec_Number,accX_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[1]) series1->append(rec_Number,accY_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[2]) series2->append(rec_Number,accZ_Data[rec_Number - exceedFlag * MAXNUMBER]);

        if(dataSelect[3]) series3->append(rec_Number,gyroX_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[4]) series4->append(rec_Number,gyroY_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[5]) series5->append(rec_Number,gyroZ_Data[rec_Number - exceedFlag * MAXNUMBER]);

        if(dataSelect[6]) series6->append(rec_Number,magX_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[7]) series7->append(rec_Number,magY_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[8]) series8->append(rec_Number,magZ_Data[rec_Number - exceedFlag * MAXNUMBER]);

        if(dataSelect[9]) series9->append(rec_Number,inclina_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[10])series10->append(rec_Number,toolface_Data[rec_Number - exceedFlag * MAXNUMBER]);
        if(dataSelect[11])series11->append(rec_Number,azimuth_Data[rec_Number - exceedFlag * MAXNUMBER]);
        rec_Number = rec_Number + 1;
    }
}

代码这部分呢虽然麻烦,但是是在调试过程中,逐步解决而完成的,所以会麻烦一点。

4.2 按钮打开新对话框并选择显示的数据

在这里是新建了一个设计器界面,然后和MainWindow进行了信号与槽的连接,进而实现数据选择功能,下面是新建设计器界面的步骤(因为我已经创建了,在此就不再重新添加了):




  下面是我的代码:
  .h文件:

cpp 复制代码
#ifndef DIALOGSELECTDATA_H
#define DIALOGSELECTDATA_H

#include <QDialog>

extern int16_t dataSelect[20];

namespace Ui {
class Dialogselectdata;
}

class Dialogselectdata : public QDialog
{
    Q_OBJECT

public:
    explicit Dialogselectdata(QWidget *parent = nullptr);
    ~Dialogselectdata();

private slots:
    void on_OK_clicked();

public slots:
    void checkBoxState();

private:
    Ui::Dialogselectdata *dialog_ui;
};

#endif // DIALOGSELECTDATA_H

.c文件

cpp 复制代码
#include "dialogselectdata.h"
#include "ui_dialogselectdata.h"

int16_t dataSelect[20]={1,1,1,0,0,0,0}; // 选择要显示的数据

Dialogselectdata::Dialogselectdata(QWidget *parent) :
    QDialog(parent),
    dialog_ui(new Ui::Dialogselectdata)
{
    dialog_ui->setupUi(this);
}

Dialogselectdata::~Dialogselectdata()
{
    delete dialog_ui;
}

void Dialogselectdata::on_OK_clicked()
{
    if(dialog_ui->accX_select->isChecked())dataSelect[0] = 1;
    else dataSelect[0] = 0;

    if(dialog_ui->accY_select->isChecked())dataSelect[1] = 1;
    else dataSelect[1] = 0;

    if(dialog_ui->accZ_select->isChecked())dataSelect[2] = 1;
    else dataSelect[2] = 0;

    if(dialog_ui->gyroX_select->isChecked())dataSelect[3] = 1;
    else dataSelect[3] = 0;

    if(dialog_ui->gyroY_select->isChecked())dataSelect[4] = 1;
    else dataSelect[4] = 0;

    if(dialog_ui->gyroZ_select->isChecked())dataSelect[5] = 1;
    else dataSelect[5] = 0;

    if(dialog_ui->magX_select->isChecked())dataSelect[6] = 1;
    else dataSelect[6] = 0;

    if(dialog_ui->magY_select->isChecked())dataSelect[7] = 1;
    else dataSelect[7] = 0;

    if(dialog_ui->magZ_select->isChecked())dataSelect[8] = 1;
    else dataSelect[8] = 0;

    if(dialog_ui->inclination_select->isChecked())dataSelect[9] = 1;
    else dataSelect[9] = 0;

    if(dialog_ui->toolface_select->isChecked())dataSelect[10] = 1;
    else dataSelect[10] = 0;

    if(dialog_ui->azimuth_select->isChecked())dataSelect[11] = 1;
    else dataSelect[11] = 0;
}

五、总结

虽然边做边学的学习方法做起来可能会比较费劲,但是慢慢地积累多了也就会了,这篇博客代码比较多,可能也比较乱,后面会继续完善这篇博客的,希望和大家共同学习,一起进步哦~

相关推荐
我爱挣钱我也要早睡!7 分钟前
Java 复习笔记
java·开发语言·笔记
知识分享小能手3 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
汇能感知5 小时前
摄像头模块在运动相机中的特殊应用
经验分享·笔记·科技
疾风铸境5 小时前
qt+halcon开发相机拍照软件步骤
数码相机·qt·halcon·拍照
阿巴Jun5 小时前
【数学】线性代数知识点总结
笔记·线性代数·矩阵
茯苓gao5 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾6 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
抠脚学代码6 小时前
Ubuntu Qt x64平台搭建 arm64 编译套件
数据库·qt·ubuntu
利刃大大6 小时前
【高并发内存池】五、页缓存的设计
c++·缓存·项目·内存池
DKPT6 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习