声明:本人水平有限,博客可能存在部分错误的地方,请广大读者谅解并向本人反馈错误。
这段时间大部分都是在学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
// 下面三个新建的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 样式表
原始的控件是很丑的,所以想要界面好看,那就得自己做一个(或者找一个样式表),下面是我目前在用的样式表:
/*
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的头文件:
QT += serialport
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上以波形显示
话不多说,直接上代码:
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文件:
#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文件
#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;
}
五、总结
虽然边做边学的学习方法做起来可能会比较费劲,但是慢慢地积累多了也就会了,这篇博客代码比较多,可能也比较乱,后面会继续完善这篇博客的,希望和大家共同学习,一起进步哦~