├── .gitignore ├── Alien 2.ico ├── Icons ├── Alien 2.png └── gtk-help.png ├── README.md ├── Serial_Oscilloscope.pro ├── Serial_Oscilloscope.pro.user ├── icon.rc ├── main.cpp ├── mainwindow.cpp ├── mainwindow.h ├── mainwindow.ui ├── myresource.qrc ├── qcustomplot.cpp └── qcustomplot.h /.gitignore: -------------------------------------------------------------------------------- 1 | #release 2 | release/* 3 | 4 | # Prerequisites 5 | *.d 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | *.smod 25 | 26 | # Compiled Static libraries 27 | *.lai 28 | *.la 29 | *.a 30 | *.lib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | -------------------------------------------------------------------------------- /Alien 2.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miller-em/UART_Oscillscope/bfb9982cc880b654990c90ee6659ac95af8219b5/Alien 2.ico -------------------------------------------------------------------------------- /Icons/Alien 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miller-em/UART_Oscillscope/bfb9982cc880b654990c90ee6659ac95af8219b5/Icons/Alien 2.png -------------------------------------------------------------------------------- /Icons/gtk-help.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miller-em/UART_Oscillscope/bfb9982cc880b654990c90ee6659ac95af8219b5/Icons/gtk-help.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UART_Oscillscope 2 | 3 | 4 | 5 | In order to facilitate the viewing of the data collected by the ADC of the microcontroller, and to be able to visualize the data. So use Qt to develop a software that can visualize the serial port data. At the same time, it also supports the sending of PID data, which is more convenient for debugging. 6 | 7 | 8 | 9 | ## User Interface 10 | 11 | ![示波器1](https://cdn.jsdelivr.net/gh/Miller-em/IMAGS/img/20210812170729.gif) -------------------------------------------------------------------------------- /Serial_Oscilloscope.pro: -------------------------------------------------------------------------------- 1 | QT += core gui serialport charts 2 | 3 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport 4 | 5 | CONFIG += c++11 6 | 7 | RC_FILE = icon.rc 8 | 9 | # The following define makes your compiler emit warnings if you use 10 | # any Qt feature that has been marked deprecated (the exact warnings 11 | # depend on your compiler). Please consult the documentation of the 12 | # deprecated API in order to know how to port your code away from it. 13 | DEFINES += QT_DEPRECATED_WARNINGS 14 | 15 | # You can also make your code fail to compile if it uses deprecated APIs. 16 | # In order to do so, uncomment the following line. 17 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 18 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 19 | 20 | SOURCES += \ 21 | main.cpp \ 22 | mainwindow.cpp \ 23 | qcustomplot.cpp 24 | 25 | HEADERS += \ 26 | mainwindow.h \ 27 | qcustomplot.h 28 | 29 | FORMS += \ 30 | mainwindow.ui 31 | 32 | 33 | # Default rules for deployment. 34 | qnx: target.path = /tmp/$${TARGET}/bin 35 | else: unix:!android: target.path = /opt/$${TARGET}/bin 36 | !isEmpty(target.path): INSTALLS += target 37 | 38 | RESOURCES += \ 39 | myresource.qrc 40 | 41 | DISTFILES += \ 42 | icon.rc 43 | -------------------------------------------------------------------------------- /Serial_Oscilloscope.pro.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | EnvironmentId 7 | {7a4af49b-5b15-4c7a-b176-7ed7a738cb2c} 8 | 9 | 10 | ProjectExplorer.Project.ActiveTarget 11 | 0 12 | 13 | 14 | ProjectExplorer.Project.EditorSettings 15 | 16 | true 17 | false 18 | true 19 | 20 | Cpp 21 | 22 | CppGlobal 23 | 24 | 25 | 26 | QmlJS 27 | 28 | QmlJSGlobal 29 | 30 | 31 | 2 32 | UTF-8 33 | false 34 | 4 35 | false 36 | 80 37 | true 38 | true 39 | 1 40 | true 41 | false 42 | 0 43 | true 44 | true 45 | 0 46 | 8 47 | true 48 | 1 49 | true 50 | true 51 | true 52 | false 53 | 54 | 55 | 56 | ProjectExplorer.Project.PluginSettings 57 | 58 | 59 | -fno-delayed-template-parsing 60 | 61 | false 62 | {4ca48680-40b5-4f3b-beee-126f4d282b42} 63 | 64 | 65 | 66 | ProjectExplorer.Project.Target.0 67 | 68 | Desktop (x86-windows-msys-pe-64bit) 69 | Desktop (x86-windows-msys-pe-64bit) 70 | {0f665f2f-234f-4193-881c-c68d44f17e04} 71 | 1 72 | 0 73 | 0 74 | 75 | E:/Qt Develop/build-Serial_Oscilloscope-Quick_Demo-Debug 76 | 77 | 78 | true 79 | QtProjectManager.QMakeBuildStep 80 | true 81 | 82 | false 83 | false 84 | false 85 | 86 | 87 | true 88 | Qt4ProjectManager.MakeStep 89 | 90 | false 91 | 92 | 93 | false 94 | 95 | 2 96 | Build 97 | Build 98 | ProjectExplorer.BuildSteps.Build 99 | 100 | 101 | 102 | true 103 | Qt4ProjectManager.MakeStep 104 | 105 | true 106 | clean 107 | 108 | false 109 | 110 | 1 111 | Clean 112 | Clean 113 | ProjectExplorer.BuildSteps.Clean 114 | 115 | 2 116 | false 117 | 118 | Debug 119 | Qt4ProjectManager.Qt4BuildConfiguration 120 | 2 121 | 122 | 123 | E:/Qt Develop/Serial_Oscilloscope/release 124 | 125 | 126 | true 127 | QtProjectManager.QMakeBuildStep 128 | false 129 | 130 | false 131 | false 132 | true 133 | 134 | 135 | true 136 | Qt4ProjectManager.MakeStep 137 | 138 | false 139 | 140 | 141 | false 142 | 143 | 2 144 | Build 145 | Build 146 | ProjectExplorer.BuildSteps.Build 147 | 148 | 149 | 150 | true 151 | Qt4ProjectManager.MakeStep 152 | 153 | true 154 | clean 155 | 156 | false 157 | 158 | 1 159 | Clean 160 | Clean 161 | ProjectExplorer.BuildSteps.Clean 162 | 163 | 2 164 | false 165 | 166 | Release 167 | Qt4ProjectManager.Qt4BuildConfiguration 168 | 0 169 | 170 | 171 | E:/Qt Develop/build-Serial_Oscilloscope-Quick_Demo-Profile 172 | 173 | 174 | true 175 | QtProjectManager.QMakeBuildStep 176 | true 177 | 178 | false 179 | true 180 | true 181 | 182 | 183 | true 184 | Qt4ProjectManager.MakeStep 185 | 186 | false 187 | 188 | 189 | false 190 | 191 | 2 192 | Build 193 | Build 194 | ProjectExplorer.BuildSteps.Build 195 | 196 | 197 | 198 | true 199 | Qt4ProjectManager.MakeStep 200 | 201 | true 202 | clean 203 | 204 | false 205 | 206 | 1 207 | Clean 208 | Clean 209 | ProjectExplorer.BuildSteps.Clean 210 | 211 | 2 212 | false 213 | 214 | Profile 215 | Qt4ProjectManager.Qt4BuildConfiguration 216 | 0 217 | 218 | 3 219 | 220 | 221 | 0 222 | Deploy 223 | Deploy 224 | ProjectExplorer.BuildSteps.Deploy 225 | 226 | 1 227 | ProjectExplorer.DefaultDeployConfiguration 228 | 229 | 1 230 | 231 | 232 | dwarf 233 | 234 | cpu-cycles 235 | 236 | 237 | 250 238 | 239 | -e 240 | cpu-cycles 241 | --call-graph 242 | dwarf,4096 243 | -F 244 | 250 245 | 246 | -F 247 | true 248 | 4096 249 | false 250 | false 251 | 1000 252 | 253 | true 254 | 255 | false 256 | false 257 | false 258 | false 259 | true 260 | 0.01 261 | 10 262 | true 263 | kcachegrind 264 | 1 265 | 25 266 | 267 | 1 268 | true 269 | false 270 | true 271 | valgrind 272 | 273 | 0 274 | 1 275 | 2 276 | 3 277 | 4 278 | 5 279 | 6 280 | 7 281 | 8 282 | 9 283 | 10 284 | 11 285 | 12 286 | 13 287 | 14 288 | 289 | 2 290 | 291 | Qt4ProjectManager.Qt4RunConfiguration:E:/Qt Develop/Serial_Oscilloscope/Serial_Oscilloscope.pro 292 | E:/Qt Develop/Serial_Oscilloscope/Serial_Oscilloscope.pro 293 | 294 | false 295 | 296 | false 297 | true 298 | true 299 | false 300 | false 301 | true 302 | 303 | E:/Qt Develop/Serial_Oscilloscope/release 304 | 305 | 1 306 | 307 | 308 | 309 | ProjectExplorer.Project.TargetCount 310 | 1 311 | 312 | 313 | ProjectExplorer.Project.Updater.FileVersion 314 | 22 315 | 316 | 317 | Version 318 | 22 319 | 320 | 321 | -------------------------------------------------------------------------------- /icon.rc: -------------------------------------------------------------------------------- 1 | IDI_ICON1 ICON "Alien 2.ico" -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | 3 | #include 4 | 5 | int main(int argc, char *argv[]) 6 | { 7 | QApplication a(argc, argv); 8 | MainWindow w; 9 | w.show(); 10 | return a.exec(); 11 | } 12 | -------------------------------------------------------------------------------- /mainwindow.cpp: -------------------------------------------------------------------------------- 1 | #include "mainwindow.h" 2 | #include "ui_mainwindow.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | const int color[10]={ 16 | 0xff0000,0xffff00,0x00ff00,0x0000ff,0xff00ff, 17 | 0xff8000,0xc0ff00,0x00ffff,0x8000ff,0x000001, 18 | }; 19 | 20 | MainWindow::MainWindow(QWidget *parent) 21 | : QMainWindow(parent) 22 | , ui(new Ui::MainWindow) 23 | { 24 | ui->setupUi(this); 25 | this->setWindowIcon(QIcon(":/Images/Icons/Alien 2.png")); 26 | this->setWindowTitle(tr("串口示波器")); 27 | ui->baudRate->setCurrentIndex(1); 28 | this->system_init(); //系统各组件初始化 29 | } 30 | 31 | MainWindow::~MainWindow() 32 | { 33 | delete ui; 34 | } 35 | 36 | /*----------------------------------------------------------- 37 | * functions 38 | * ----------------------------------------------------------*/ 39 | 40 | void MainWindow::system_init() 41 | { 42 | // 这是statusbar的相关初始化 43 | QLabel *permanent = new QLabel(this); 44 | permanent->setFrameStyle(QFrame::Box | QFrame::Sunken); 45 | permanent->setText( 46 | tr("xiaozhoua.top")); 47 | permanent->setTextFormat(Qt::RichText); 48 | permanent->setOpenExternalLinks(true); 49 | ui->statusbar->addPermanentWidget(permanent); 50 | statusLabel = new QLabel; 51 | statusLabel->setMinimumSize(150, 20); // 设置标签最小大小 52 | statusLabel->setFrameShape(QFrame::WinPanel); // 设置标签形状 53 | statusLabel->setFrameShadow(QFrame::Sunken); // 设置标签阴影 54 | ui->statusbar->addWidget(statusLabel); 55 | statusLabel->setText(tr("所属人:Xiaozhoua")); 56 | statusLabel->setStyleSheet("color: white"); 57 | statusBar()->setStyleSheet("background-color : rgb(30,30,30)"); 58 | 59 | //PID 控制初始值控制 60 | ui->lineEdit->setText(tr("0")); 61 | ui->lineEdit_2->setText(tr("0")); 62 | ui->lineEdit_3->setText(tr("0")); 63 | ui->lineEdit_4->setText(tr("0")); 64 | 65 | // 串口初始化配置 66 | global_port.setParity(QSerialPort::NoParity); //无奇偶校验位 67 | global_port.setDataBits(QSerialPort::Data8); //8位校验位 68 | global_port.setStopBits(QSerialPort::OneStop); //停止位为1 69 | global_port.setFlowControl(QSerialPort::NoFlowControl); //无流控制 70 | connect(&global_port, SIGNAL(readyRead()), this, SLOT(receiveInfo())); 71 | 72 | // 示波器初始化配置 73 | ui->customPlot->setBackground(QBrush(QColor("#474848"))); 74 | } 75 | 76 | QStringList MainWindow::getPortNameList() 77 | { 78 | /*-------------------------------- 79 | * 获取系统串口信息 80 | *-------------------------------*/ 81 | QStringList m_serialPortName; 82 | foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) 83 | { 84 | m_serialPortName << info.portName(); 85 | qDebug()<<"serialPortName:"<customPlot->setBackground(QBrush(QColor("#000000"))); 90 | void MainWindow::buildChart() 91 | { 92 | /*-------------------------------- 93 | * 构造示波器 94 | *-------------------------------*/ 95 | ui->customPlot->setBackground(QBrush(QColor("#474848"))); 96 | ui->customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables); //可拖拽+可滚轮缩放 97 | 98 | ui->customPlot->axisRect()->setupFullAxesBox(); 99 | ui->customPlot->yAxis->setRange(0, 3.3); 100 | } 101 | 102 | void MainWindow::plotCustom(QByteArray info) 103 | { 104 | //避免中文乱码 105 | QTextCodec *tc = QTextCodec::codecForName("GBK"); 106 | QString tmpQStr = tc->toUnicode(info); 107 | 108 | // 若示波器打开,开始解析数据 109 | if (oscill_flag){ 110 | QStringList datakeys; 111 | 112 | QJsonParseError jsonError; 113 | QJsonDocument jsonDoc = QJsonDocument::fromJson(info, &jsonError); 114 | 115 | if (jsonError.error != QJsonParseError::NoError) 116 | { 117 | qDebug() << "parse json object failed, " << jsonError.errorString(); 118 | ui->textBrowser->append("parse json object failed!"); 119 | return; 120 | } 121 | QJsonObject jsonObj = jsonDoc.object(); 122 | 123 | qDebug() << "parse json object Successfully"; 124 | datakeys = jsonObj.keys(); // 获取通道名称 125 | qDebug() << datakeys; 126 | 127 | if (Received_Keys != datakeys){ 128 | // 只能够设置一次标签 129 | qDebug() << "update keys"; 130 | Received_Keys = datakeys; 131 | 132 | this->index = 0; 133 | this->Ptext.clear(); 134 | this->XData.clear(); 135 | this->YData.clear(); 136 | // 清除画布 137 | ui->customPlot->clearGraphs(); 138 | ui->customPlot->legend->setVisible(false); 139 | ui->customPlot->replot(); 140 | 141 | ui->customPlot->legend->setVisible(true); //右上角指示曲线的缩略框 142 | ui->customPlot->legend->setBrush(QColor(100, 100, 100, 0));//设置图例背景颜色,可设置透明 143 | ui->customPlot->legend->setTextColor(Qt::white); 144 | for (int i=0; i < datakeys.size(); i++){ 145 | ui->customPlot->addGraph(); 146 | ui->customPlot->graph(i)->setPen(QPen(color[i])); 147 | ui->customPlot->graph(i)->setName(datakeys[i]); 148 | Ptext.push_back(datakeys[i]); 149 | } 150 | } 151 | 152 | // 添加XData , YData 数据 153 | XData.push_back(index); 154 | QVector Data; 155 | YData.resize(datakeys.size()); 156 | 157 | for (int i = 0; i < Ptext.size(); ++i) { 158 | Data.push_back(jsonObj.value(datakeys[i]).toDouble()); 159 | } 160 | for (int i = 0; i < Ptext.size(); ++i) { 161 | YData[i].push_back(Data[i]); 162 | } 163 | 164 | //向坐标值赋值 165 | for (int i=0; i < datakeys.size(); ++i){ 166 | ui->customPlot->graph(i)->addData(XData[index], YData[i][index]); 167 | } 168 | this->index++; 169 | // 更新坐标 170 | ui->customPlot->xAxis->setRange((ui->customPlot->graph(0)->dataCount()>1000)? 171 | (ui->customPlot->graph(0)->dataCount()-1000): 172 | 0, 173 | ui->customPlot->graph(0)->dataCount()); 174 | ui->customPlot->replot(QCustomPlot::rpQueuedReplot); //实现重绘 175 | } 176 | // 向接收区打印 177 | ui->textBrowser->append(tmpQStr); 178 | qDebug() << "Received Data: " << tmpQStr; 179 | } 180 | /*----------------------------------------------------------- 181 | * slots 182 | * ----------------------------------------------------------*/ 183 | 184 | void MainWindow::on_OpenorClose_clicked() 185 | { 186 | /*-------------------------------- 187 | * 打开或者关闭串口 188 | *-------------------------------*/ 189 | if (!this->OpenorClose_Flag){ 190 | // 打开串口 191 | ui->OpenorClose->setText("关闭串口"); 192 | this->OpenorClose_Flag = true; 193 | 194 | //设置串口端口 195 | QStringList m_serialPortName; 196 | m_serialPortName = getPortNameList(); //配置 197 | qDebug()<portId->clear(); 199 | ui->portId->addItems(m_serialPortName); 200 | 201 | //Serial 配置 202 | 203 | QString portId; 204 | portId = ui->portId->currentText(); 205 | qDebug() << "portId: " << portId; 206 | global_port.setPortName(portId); //配置端口号 207 | 208 | QString baudRate; 209 | baudRate = ui->baudRate->currentText(); 210 | qDebug() << "baudRate: " << baudRate; 211 | global_port.setBaudRate(baudRate.toInt(), QSerialPort::AllDirections); //配置波特率 212 | 213 | // 配置完成,开启串口 214 | global_port.open(QIODevice::ReadWrite); 215 | qDebug() << "Open Serial Successfully"; 216 | }else{ 217 | // 关闭串口 218 | global_port.close(); 219 | qDebug() << "Close Serial Successfully"; 220 | ui->OpenorClose->setText("打开串口"); 221 | this->OpenorClose_Flag = false; 222 | } 223 | } 224 | 225 | void MainWindow::on_sendPIDData_clicked() 226 | { 227 | /*-------------------------------- 228 | * 发送PID相关数据 229 | *-------------------------------*/ 230 | if (global_port.isOpen()){ 231 | QString P, I, D, targetVal; 232 | QJsonObject sendPIDData; 233 | 234 | P = ui->lineEdit->text(); 235 | I = ui->lineEdit_2->text(); 236 | D = ui->lineEdit_3->text(); 237 | targetVal = ui->lineEdit_4->text(); 238 | sendPIDData.insert("P", P.toFloat()); 239 | sendPIDData.insert("I", I.toFloat()); 240 | sendPIDData.insert("D", D.toFloat()); 241 | sendPIDData.insert("Target", targetVal.toFloat()); 242 | QJsonDocument document; 243 | document.setObject(sendPIDData); 244 | QByteArray pidbyte_array = document.toJson(QJsonDocument::Compact); 245 | QString pidjson_str(pidbyte_array); 246 | pidjson_str += '\n'; 247 | qDebug() << QString::fromLocal8Bit("PID Data:") << pidjson_str; 248 | global_port.write(pidjson_str.toLocal8Bit()); 249 | }else{ 250 | QMessageBox box; 251 | box.setWindowTitle(tr("警告")); 252 | box.setWindowIcon(QIcon(":/Images/Icons/Alien 2.png")); 253 | box.setIcon(QMessageBox::Warning); 254 | box.setText(tr(" 未检测到串口,请确认串口是否打开?")); 255 | box.exec(); 256 | } 257 | } 258 | 259 | void MainWindow::on_sendData_clicked() 260 | { 261 | /*-------------------------------- 262 | * 发送串口数据 263 | *-------------------------------*/ 264 | if (global_port.isOpen()){ 265 | QString sendData; 266 | 267 | sendData = ui->textEdit->toPlainText() + '\n'; 268 | qDebug() << sendData; 269 | ui->textEdit->clear(); 270 | global_port.write(sendData.toLocal8Bit()); 271 | }else{ 272 | QMessageBox box; 273 | box.setWindowTitle(tr("警告")); 274 | box.setWindowIcon(QIcon(":/Images/Icons/Alien 2.png")); 275 | box.setIcon(QMessageBox::Warning); 276 | box.setText(tr(" 未检测到串口,请确认串口是否打开?")); 277 | box.exec(); 278 | } 279 | } 280 | 281 | void MainWindow::on_viewManual_clicked() 282 | { 283 | /*-------------------------------- 284 | * 查看帮助手册 285 | *-------------------------------*/ 286 | QString strtext="1.串口通讯格式:用Json数据格式进行传输。发送数据的字符串不得超过45个字符,否则漏失数据较为严重\n" 287 | "2.下位机MCU使用cJson进行发送数据\n" 288 | "3.暂停示波器,看波形目前只支持开关串口,但这样会造成丢失数据\n" 289 | "4.下位机发送字符串格式为: {\"xxx\":%.3f,\"xxx\":%.3f}"; 290 | QMessageBox::information(this, "帮助信息", strtext, QMessageBox::Ok); 291 | } 292 | 293 | void MainWindow::on_pushButton_clicked() 294 | { 295 | /*-------------------------------- 296 | * 清空PID相关数据 297 | *-------------------------------*/ 298 | ui->lineEdit->setText(tr("0")); 299 | ui->lineEdit_2->setText(tr("0")); 300 | ui->lineEdit_3->setText(tr("0")); 301 | ui->lineEdit_4->setText(tr("0")); 302 | } 303 | 304 | void MainWindow::on_openOscill_clicked() 305 | { 306 | /*-------------------------------- 307 | * 打开示波器 308 | *-------------------------------*/ 309 | if (!oscill_flag){ 310 | if (global_port.isOpen()){ 311 | oscill_flag = true; 312 | buildChart(); 313 | ui->openOscill->setText("关闭示波器"); 314 | }else{ 315 | QMessageBox box; 316 | box.setWindowTitle(tr("警告")); 317 | box.setWindowIcon(QIcon(":/Images/Icons/Alien 2.png")); 318 | box.setIcon(QMessageBox::Warning); 319 | box.setText(tr(" 未检测到串口,请确认串口是否打开?")); 320 | box.exec(); 321 | } 322 | }else{ 323 | // 置空所有状态值 324 | oscill_flag = false; 325 | this->index = 0; 326 | this->Ptext.clear(); 327 | this->XData.clear(); 328 | this->YData.clear(); 329 | this->Received_Keys.clear(); 330 | // 清楚画布 331 | ui->customPlot->clearGraphs(); 332 | ui->customPlot->legend->setVisible(false); 333 | ui->customPlot->replot(); 334 | ui->customPlot->setBackground(QBrush(QColor("#474848"))); 335 | ui->openOscill->setText("打开示波器"); 336 | } 337 | } 338 | 339 | void MainWindow::receiveInfo() 340 | { 341 | /*-------------------------------- 342 | * 接受串口信息 343 | *-------------------------------*/ 344 | QString data; 345 | QByteArray info = global_port.readAll(); 346 | QStringList list; 347 | 348 | if(!info.isEmpty()) 349 | { 350 | if (info.contains('{')){ 351 | data = info; 352 | list= data.split("{"); 353 | if (list.length() == 2){ 354 | if (frontData.isEmpty()){ 355 | frontData = list.at(1); 356 | frontData.insert(0,'{'); 357 | return; 358 | } 359 | oneData = frontData + list.at(0); 360 | frontData = list.at(1); 361 | frontData.insert(0,'{'); 362 | plotCustom(oneData.toLocal8Bit()); //绘图 363 | qDebug() << "One data: " << oneData; 364 | } 365 | 366 | if (list.length() == 3){ 367 | oneData = frontData + list.at(0); 368 | plotCustom(oneData.toLocal8Bit()); //绘图 369 | qDebug() << "One data: " << oneData; 370 | oneData = list.at(1); 371 | oneData.insert(0,'{'); 372 | plotCustom(oneData.toLocal8Bit()); //绘图 373 | qDebug() << "One data: " << oneData; 374 | frontData = list.at(2); 375 | frontData.insert(0,'{'); 376 | } 377 | } 378 | } 379 | } 380 | 381 | void MainWindow::on_clearReceived_clicked() 382 | { 383 | /*-------------------------------- 384 | * 清空接收区 385 | *-------------------------------*/ 386 | ui->textBrowser->clear(); 387 | } 388 | 389 | void MainWindow::on_stopOscill_clicked() 390 | { 391 | /*-------------------------------- 392 | * 坐标轴缩放 393 | *-------------------------------*/ 394 | if (stop_flag){ 395 | ui->customPlot->axisRect()->setRangeZoom(Qt::Vertical); 396 | stop_flag = false; 397 | ui->stopOscill->setText("水平缩放"); 398 | }else{ 399 | ui->customPlot->axisRect()->setRangeZoom(Qt::Horizontal); 400 | stop_flag = true; 401 | ui->stopOscill->setText("垂直缩放"); 402 | } 403 | } 404 | -------------------------------------------------------------------------------- /mainwindow.h: -------------------------------------------------------------------------------- 1 | #ifndef MAINWINDOW_H 2 | #define MAINWINDOW_H 3 | 4 | #include 5 | 6 | /*-------------include----------------*/ 7 | #include 8 | #include 9 | #include "qcustomplot.h" 10 | //#include 11 | 12 | /*-------------class------------------*/ 13 | class QLabel; 14 | class QString; 15 | class QTimer; 16 | class QDebug; 17 | 18 | /*-------------define-----------------*/ 19 | #define cout qDebug() << "[" << __FILE__ << ":" << __LINE__ << "]" 20 | 21 | /*-------------namespace--------------*/ 22 | //using namespace QtCharts; 23 | QT_BEGIN_NAMESPACE 24 | namespace Ui { class MainWindow; } 25 | QT_END_NAMESPACE 26 | 27 | 28 | class MainWindow : public QMainWindow 29 | { 30 | Q_OBJECT 31 | 32 | public: 33 | MainWindow(QWidget *parent = nullptr); 34 | ~MainWindow(); 35 | 36 | void buildChart(); //创建图表函数 37 | void plotCustom(QByteArray info); 38 | 39 | private slots: 40 | void on_OpenorClose_clicked(); 41 | 42 | void on_sendPIDData_clicked(); 43 | 44 | void on_sendData_clicked(); 45 | 46 | void on_viewManual_clicked(); 47 | 48 | void on_pushButton_clicked(); 49 | 50 | void on_openOscill_clicked(); 51 | 52 | void receiveInfo(); 53 | 54 | void on_clearReceived_clicked(); 55 | 56 | void on_stopOscill_clicked(); 57 | 58 | private: 59 | Ui::MainWindow *ui; 60 | 61 | /*-------------function----------------*/ 62 | void system_init(); 63 | QStringList getPortNameList(); 64 | 65 | /*-------------variable----------------*/ 66 | // 串口声明 67 | QSerialPort global_port; 68 | // 状态栏声明 69 | QLabel *statusLabel; 70 | QLabel *msgLabel; 71 | 72 | // 串口相关 73 | QString receivedDdata = ""; 74 | bool receivedFlag = false; 75 | bool OpenorClose_Flag = false; 76 | bool stop_flag = true; 77 | 78 | // 示波器相关 79 | bool oscill_flag = false; 80 | QVector Ptext; // 每条曲线上的显示的文字 81 | QVector > YData; // Y轴数据,可具有多个数据曲线 82 | QVector XData; // x轴数据 83 | double index = 0; // 索引 84 | QString frontData; 85 | QString backData; 86 | QString oneData; 87 | QStringList Received_Keys; // 标签值 88 | }; 89 | #endif // MAINWINDOW_H 90 | -------------------------------------------------------------------------------- /mainwindow.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 859 10 | 584 11 | 12 | 13 | 14 | 15 | 黑体 16 | 11 17 | 18 | 19 | 20 | MainWindow 21 | 22 | 23 | 24 | QWidget#centralwidget{ 25 | background:rgb(30, 30, 30); 26 | } 27 | 28 | 29 | 30 | 0 31 | 32 | 33 | QLayout::SetDefaultConstraint 34 | 35 | 36 | 37 | 38 | QFrame{ 39 | color:rgb(60, 60, 60); 40 | background:rgb(30,30,30); 41 | border-top:1px solid darkGray; 42 | border-bottom:1px solid darkGray; 43 | border-right:1px solid darkGray; 44 | border-left:1px solid darkGray; 45 | border-top-right-radius:5px; 46 | border-bottom-right-radius:5px; 47 | border-top-left-radius:5px; 48 | border-bottom-left-radius:5px; 49 | } 50 | QLabel{ 51 | border:none; 52 | color:white; 53 | font-size:16px; 54 | font-weight:700; 55 | font-family: "微软雅黑"; 56 | } 57 | 58 | 59 | 60 | 61 | 62 | QPushButton{ 63 | color:white; 64 | background:rgb(50,50,50); ; 65 | border-radius:3px; 66 | font-size:15px; 67 | font-weight:700; 68 | font-family: "微软雅黑"; 69 | } 70 | QPushButton:hover{ 71 | color:rgb(42,105,192); 72 | font-size:15px; 73 | font-weight:700; 74 | } 75 | 76 | 77 | QFrame::StyledPanel 78 | 79 | 80 | QFrame::Raised 81 | 82 | 83 | 84 | 85 | 86 | 查看使用说明 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | QFrame#frame{ 97 | color:rgb(60, 60, 60); 98 | background:rgb(30,30,30); 99 | border-top:1px solid darkGray; 100 | border-bottom:1px solid darkGray; 101 | border-right:1px solid darkGray; 102 | border-left:1px solid darkGray; 103 | border-top-right-radius:5px; 104 | border-bottom-right-radius:5px; 105 | border-top-left-radius:5px; 106 | border-bottom-left-radius:5px; 107 | } 108 | 109 | QComboBox{ 110 | font-size:12px; 111 | font-weight:700; 112 | font-family: "微软雅黑"; 113 | } 114 | 115 | QPushButton{ 116 | color:white; 117 | background:rgb(50,50,50); ; 118 | border-radius:3px; 119 | font-size:15px; 120 | font-weight:700; 121 | font-family: "微软雅黑"; 122 | } 123 | QPushButton:hover{ 124 | color:rgb(42,105,192); 125 | font-size:15px; 126 | font-weight:700; 127 | } 128 | 129 | 130 | 131 | QFrame::StyledPanel 132 | 133 | 134 | QFrame::Raised 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 微软雅黑 144 | -1 145 | 87 146 | true 147 | 148 | 149 | 150 | 操作: 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 微软雅黑 159 | -1 160 | 87 161 | true 162 | 163 | 164 | 165 | 端口: 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 微软雅黑 174 | -1 175 | 87 176 | true 177 | 178 | 179 | 180 | 打开串口 181 | 182 | 183 | 184 | 185 | 186 | 187 | Qt::Vertical 188 | 189 | 190 | QSizePolicy::Fixed 191 | 192 | 193 | 194 | 20 195 | 10 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 微软雅黑 205 | -1 206 | 87 207 | true 208 | 209 | 210 | 211 | 波特率: 212 | 213 | 214 | 215 | 216 | 217 | 218 | QComboBox::AdjustToContentsOnFirstShow 219 | 220 | 221 | true 222 | 223 | 224 | 225 | 4800 226 | 227 | 228 | 229 | 230 | 9600 231 | 232 | 233 | 234 | 235 | 115200 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | Qt::Vertical 247 | 248 | 249 | QSizePolicy::Fixed 250 | 251 | 252 | 253 | 20 254 | 10 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | QFrame#frame{ 268 | color:rgb(60, 60, 60); 269 | background:rgb(30,30,30); 270 | border-top:1px solid darkGray; 271 | border-bottom:1px solid darkGray; 272 | border-right:1px solid darkGray; 273 | border-left:1px solid darkGray; 274 | border-top-right-radius:5px; 275 | border-bottom-right-radius:5px; 276 | border-top-left-radius:5px; 277 | border-bottom-left-radius:5px; 278 | } 279 | 280 | QLineEdit{ 281 | font-size:12px; 282 | font-weight:700; 283 | font-family: "微软雅黑"; 284 | } 285 | 286 | QPushButton{ 287 | color:white; 288 | background:rgb(50,50,50); ; 289 | border-radius:3px; 290 | font-size:15px; 291 | font-weight:700; 292 | font-family: "微软雅黑"; 293 | } 294 | QPushButton:hover{ 295 | color:rgb(42,105,192); 296 | font-size:15px; 297 | font-weight:700; 298 | } 299 | 300 | 301 | QFrame::StyledPanel 302 | 303 | 304 | QFrame::Raised 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 微软雅黑 314 | -1 315 | 87 316 | true 317 | 318 | 319 | 320 | 发送数据 321 | 322 | 323 | 324 | 325 | 326 | 327 | Qt::Vertical 328 | 329 | 330 | QSizePolicy::Fixed 331 | 332 | 333 | 334 | 20 335 | 10 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 微软雅黑 345 | -1 346 | 87 347 | true 348 | 349 | 350 | 351 | I: 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 微软雅黑 360 | -1 361 | 87 362 | true 363 | 364 | 365 | 366 | D: 367 | 368 | 369 | 370 | 371 | 372 | 373 | Qt::Vertical 374 | 375 | 376 | QSizePolicy::Fixed 377 | 378 | 379 | 380 | 20 381 | 10 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 微软雅黑 391 | -1 392 | 87 393 | true 394 | 395 | 396 | 397 | P: 398 | 399 | 400 | 401 | 402 | 403 | 404 | Qt::Vertical 405 | 406 | 407 | QSizePolicy::Fixed 408 | 409 | 410 | 411 | 20 412 | 10 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 微软雅黑 422 | -1 423 | 87 424 | true 425 | 426 | 427 | 428 | 操作: 429 | 430 | 431 | 432 | 433 | 434 | 435 | 目标值: 436 | 437 | 438 | 439 | 440 | 441 | 442 | Qt::Vertical 443 | 444 | 445 | QSizePolicy::Fixed 446 | 447 | 448 | 449 | 20 450 | 10 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 清空数据 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | QPushButton{ 483 | color:white; 484 | background:rgb(50,50,50); ; 485 | border-radius:3px; 486 | font-size:15px; 487 | font-weight:700; 488 | font-family: "微软雅黑"; 489 | } 490 | QPushButton:hover{ 491 | color:rgb(42,105,192); 492 | font-size:15px; 493 | font-weight:700; 494 | } 495 | 496 | 497 | QFrame::StyledPanel 498 | 499 | 500 | QFrame::Raised 501 | 502 | 503 | 504 | 505 | 506 | Qt::Vertical 507 | 508 | 509 | 1 510 | 511 | 512 | 513 | 打开示波器 514 | 515 | 516 | 517 | 518 | 垂直缩放 519 | 520 | 521 | 522 | 16 523 | 16 524 | 525 | 526 | 527 | false 528 | 529 | 530 | false 531 | 532 | 533 | false 534 | 535 | 536 | 537 | 538 | 发送数据 539 | 540 | 541 | 542 | 543 | 清空接收区 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | QLabel{ 558 | border:none; 559 | color:white; 560 | font-size:26px; 561 | font-weight:700; 562 | font-family: "楷体"; 563 | } 564 | QWidget#customPlot{ 565 | color:#232C51; 566 | background:rgb(47,48,48); 567 | border-top:1px solid darkGray; 568 | border-bottom:1px solid darkGray; 569 | border-right:1px solid darkGray; 570 | border-left:1px solid darkGray; 571 | border-top-right-radius:10px; 572 | border-bottom-right-radius:10px; 573 | border-top-left-radius:10px; 574 | border-bottom-left-radius:10px; 575 | } 576 | QTextEdit{ 577 | color: white; 578 | font-family: "JetBrains Mono"; 579 | background:rgb(75,75,75); 580 | border-top:1px solid darkGray; 581 | border-bottom:1px solid darkGray; 582 | border-right:1px solid darkGray; 583 | border-left:1px solid darkGray; 584 | border-top-right-radius:10px; 585 | border-bottom-right-radius:10px; 586 | border-top-left-radius:10px; 587 | border-bottom-left-radius:10px; 588 | } 589 | QTextBrowser{ 590 | color: white; 591 | font-size: 12px; 592 | font-family: "JetBrains Mono"; 593 | background:rgb(75,75,75); 594 | border-top:1px solid darkGray; 595 | border-bottom:1px solid darkGray; 596 | border-right:1px solid darkGray; 597 | border-left:1px solid darkGray; 598 | border-top-right-radius:10px; 599 | border-bottom-right-radius:10px; 600 | border-top-left-radius:10px; 601 | border-bottom-left-radius:10px; 602 | } 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 楷体 616 | -1 617 | 87 618 | true 619 | 620 | 621 | 622 | 2021功率国赛工具—串口示波器 623 | 624 | 625 | Qt::AlignCenter 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | QLabel{ 636 | border:none; 637 | color:white; 638 | font-size:15px; 639 | font-weight:700; 640 | font-family: "微软雅黑"; 641 | } 642 | 643 | 644 | 发送区 645 | 646 | 647 | 648 | 649 | 650 | 651 | QLabel{ 652 | border:none; 653 | color:white; 654 | font-size:15px; 655 | font-weight:700; 656 | font-family: "微软雅黑"; 657 | } 658 | 659 | 660 | 接收区 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | :/Images/Icons/gtk-help.png:/Images/Icons/gtk-help.png 674 | 675 | 676 | 使用说明 677 | 678 | 679 | Ctrl+H 680 | 681 | 682 | 683 | 684 | 685 | QCustomPlot 686 | QWidget 687 |
qcustomplot.h
688 | 1 689 |
690 |
691 | 692 | 693 | 694 | 695 |
696 | -------------------------------------------------------------------------------- /myresource.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | Icons/gtk-help.png 4 | Icons/Alien 2.png 5 | 6 | 7 | --------------------------------------------------------------------------------