搜索引擎優(yōu)化大致包含哪些內(nèi)容或環(huán)節(jié)河北seo推廣公司
前言
1.一直都想要做一個(gè)Qt上位機(jī),趁著這個(gè)周末有時(shí)間,動(dòng)手寫一下
2.comboBox沒有點(diǎn)擊的信號(hào),所以做了一個(gè)觸發(fā)的功能
3.Qt的數(shù)據(jù)類型很奇怪,轉(zhuǎn)來轉(zhuǎn)去的我也搞得很迷糊
4.給自己挖個(gè)坑,下一期做一個(gè)查看波形的上位機(jī)
有紕漏請指出,轉(zhuǎn)載請說明。
學(xué)習(xí)交流請發(fā)郵件 1280253714@qq.com
串口功能
波特率設(shè)置
串口開關(guān)
串口異常檢測
字符串/HEX收發(fā)
定時(shí)發(fā)送
接收數(shù)據(jù)分隔
協(xié)議組包
協(xié)議拆包
源代碼
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QtSerialPort/QSerialPort> // 提供訪問串口的功能
#include <QtSerialPort/QSerialPortInfo> // 提供系統(tǒng)中存在的串口信息
#include <QTime>
#include <QtCharts>
#include <QTimer>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECT//用于表格設(shè)置enum FieldColNum {colTime,colCmd1,colCmd2,colData,};enum CellType {ctTime,ctCmd1,ctCmd2,ctData,};
public:int tableRowCnt = 0;
public:Widget(QWidget *parent = nullptr);~Widget();void serialPortInit(); //串口初始化void windowInit(); //顯示窗口初始化void refreshCom(); //刷新串口void tableInit(); //表格初始化void createItemsARow(int rowNum, QByteArray *protocalData); //表格新建一行QString ByteArrayToHexString(QByteArray &ba);
private:Ui::Widget *ui;QSerialPort* serialPort;
public slots:void comboBoxClicked(); //comboBox被點(diǎn)擊
private slots:void sendData(); //發(fā)送串口數(shù)據(jù)void receiveData(); //接收串口數(shù)據(jù)void openSerialport(); //串口開啟void closeSerialport(); //串口關(guān)閉void setBuad(int); //設(shè)置波特率void clearRcv(); //清楚接收緩存void on_btnConvert_clicked(); //轉(zhuǎn)換按鈕被點(diǎn)擊void on_btnClear_clicked(); //清楚轉(zhuǎn)化的按鈕被點(diǎn)擊void sendProtocalHexData(); //以hex格式發(fā)送串口數(shù)據(jù)void handleSerialError(QSerialPort::SerialPortError serialPortErr); //串口異常捕獲
};#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "newcombobox.h"
#include <algorithm>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//創(chuàng)建一個(gè)定時(shí)器用來定時(shí)發(fā)送QTimer *timer1 = new QTimer();timer1->start(1000);connect(timer1,&QTimer::timeout,[=](){int timed = ui->comboBox_timedSend->currentText().toInt();timer1->start(timed);if(ui->checkBox_timedSend->isChecked() == true){sendData();}});windowInit();tableInit();serialPort = new QSerialPort();serialPortInit();connect(serialPort,SIGNAL(readyRead()),this,SLOT(receiveData()));connect(serialPort,SIGNAL(errorOccurred(QSerialPort::SerialPortError)),this,SLOT(handleSerialError(QSerialPort::SerialPortError)));connect(ui->pushButton_sendData,SIGNAL(clicked()),this,SLOT(sendData()));connect(ui->pushButton_openSerialPort,SIGNAL(clicked()),this,SLOT(openSerialport()));connect(ui->pushButton_closeSerialPort,SIGNAL(clicked()),this,SLOT(closeSerialport()));connect(ui->comboBox_chooseCom,SIGNAL(clicked()),this,SLOT(comboBoxClicked()));connect(ui->pushButton_clearRcv,SIGNAL(clicked()),this,SLOT(clearRcv()));connect(ui->pushButton_convert,SIGNAL(clicked()),this,SLOT(on_btnConvert_clicked()));connect(ui->pushButton_clearConvertData,SIGNAL(clicked()),this,SLOT(on_btnClear_clicked()));connect(ui->pushButton_sendProtocalData,SIGNAL(clicked()),this,SLOT(sendProtocalHexData()));connect(serialPort,SIGNAL(errorOccurred(QSerialPort::SerialPortError)),this,SLOT(handleSerialError(QSerialPort::SerialPortError)));connect(ui->comboBox_setBuad,SIGNAL(activated(int)),this,SLOT(setBuad(int)));
}Widget::~Widget()
{delete ui;
}//串口異常捕獲
void Widget::handleSerialError(QSerialPort::SerialPortError serialPortErr)
{if(serialPortErr == QSerialPort::ResourceError){QMessageBox::critical(NULL, "critical", "設(shè)備拔出", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);closeSerialport();}if(serialPortErr == QSerialPort::DeviceNotFoundError){QMessageBox::critical(NULL, "critical", "找不到串口", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);closeSerialport();}
}void Widget::comboBoxClicked()
{refreshCom();
}void Widget::windowInit()
{ui->pushButton_closeSerialPort->setEnabled(false);ui->pushButton_openSerialPort->setEnabled(false);ui->pushButton_sendData->setEnabled(false);setWindowTitle(tr("串口收發(fā)"));ui->comboBox_timedSend->addItem("10");ui->comboBox_timedSend->addItem("100");ui->comboBox_timedSend->addItem("1000");ui->comboBox_timedSend->setCurrentIndex(2);
}void Widget::refreshCom()
{//顯示串口列表ui->comboBox_chooseCom->clear();foreach(QSerialPortInfo portInfo, QSerialPortInfo::availablePorts())ui->comboBox_chooseCom->addItem(portInfo.portName()+":"+portInfo.description());ui->pushButton_openSerialPort->setEnabled(ui->comboBox_chooseCom->count()>0); //
}void Widget::serialPortInit(){refreshCom();ui->comboBox_setBuad->addItem("9600");ui->comboBox_setBuad->addItem("115200");ui->comboBox_setBuad->addItem("921600");ui->comboBox_setBuad->setCurrentIndex(1);}void Widget::tableInit()
{QStringList headerText;headerText<<"時(shí)間"<<"命令1"<<"命令2"<<"數(shù)據(jù)";ui->tableWidget->setColumnCount(headerText.size()); //設(shè)置表格列數(shù)ui->tableWidget->resizeColumnsToContents();for (int i=0;i<ui->tableWidget->columnCount();i++){QTableWidgetItem *headerItem=new QTableWidgetItem(headerText.at(i));QFont font=headerItem->font(); //獲取原有字體設(shè)置font.setBold(true); //設(shè)置為粗體font.setPointSize(10); //字體大小headerItem->setForeground(QBrush(Qt::black)); //設(shè)置文字顏色headerItem->setFont(font); //設(shè)置字體ui->tableWidget->setHorizontalHeaderItem(i,headerItem); //設(shè)置表頭單元格的item}ui->tableWidget->setColumnWidth(0, 60);ui->tableWidget->setColumnWidth(1, 50);ui->tableWidget->setColumnWidth(2, 50);ui->tableWidget->setColumnWidth(3, 250);
}//為一行的單元格創(chuàng)建 Items
void Widget::createItemsARow(int rowNum, QByteArray *protocalData)
{uchar preFix = 0xA5;uchar crc = 0;uchar temp = 0;temp = static_cast<uchar>(protocalData->at(0));if(static_cast<uchar>(protocalData->at(0)) == preFix){for(int i=1; i<protocalData->length()-2; i++){temp = static_cast<uchar>(protocalData->at(i));crc += static_cast<uchar>(protocalData->at(i));}temp = static_cast<uchar>(protocalData->at(protocalData->length()-2));if(crc != static_cast<uchar>(protocalData->at(protocalData->length()-2))){return;}uchar len = protocalData->at(1);uchar cmd1 = protocalData->at(2);uchar cmd2 = protocalData->at(3);QByteArray data = protocalData->mid(4,len-6);QDateTime curTime = QDateTime::currentDateTime();//獲取系統(tǒng)現(xiàn)在的時(shí)間QString time = curTime.toString("hh:mm:ss"); //設(shè)置顯示格式uint8_t str1 = static_cast<uint8_t>(cmd1);QString hexStr1 = QString("%1").arg(str1, 2, 16, QLatin1Char('0')).toUpper();uint8_t str2 = static_cast<uint8_t>(cmd2);QString hexStr2 = QString("%1").arg(str2, 2, 16, QLatin1Char('0')).toUpper();QString testdata = ByteArrayToHexString(data).toLatin1().toUpper();QTableWidgetItem *item = new QTableWidgetItem(time, ctTime);ui->tableWidget->setItem(rowNum, colTime, item);item = new QTableWidgetItem(hexStr1, ctCmd1);ui->tableWidget->setItem(rowNum, colCmd1, item);item = new QTableWidgetItem(hexStr2, ctCmd2);ui->tableWidget->setItem(rowNum, colCmd2, item);item = new QTableWidgetItem(testdata, ctData);ui->tableWidget->setItem(rowNum, colData, item);}auto lastRowIndex = ui->tableWidget->rowCount()-1; // 最后一行的索引auto lastModelIndex = ui->tableWidget->model()->index(lastRowIndex, 0);ui->tableWidget->scrollTo(lastModelIndex); // 滾動(dòng)到最后一行
}QString Widget::ByteArrayToHexString(QByteArray &ba)
{QDataStream out(&ba,QIODevice::ReadWrite); //將str的數(shù)據(jù) 讀到out里面去QString buf;while(!out.atEnd()){qint8 outChar = 0;out >> outChar; //每次一個(gè)字節(jié)的填充到 outcharQString str = QString("%1").arg(outChar&0xFF,2,16,QLatin1Char('0')).toUpper() + QString(" "); //2 字符寬度buf += str;}return buf;
}void Widget::sendData()
{QString message = ui->lineEdit_sendData->text();if(ui->checkBox_hexSend->isChecked() == true){serialPort->write(QByteArray::fromHex(message.toLatin1()));}else{serialPort->write(message.toLatin1());}
}void Widget::receiveData()
{QByteArray message;QString hexMsg;message.append(serialPort->readAll());QDateTime time = QDateTime::currentDateTime(); //獲取系統(tǒng)現(xiàn)在的時(shí)間QString date = time.toString("hh:mm:ss"); //設(shè)置顯示格式if(ui->checkBox_hexRcv->isChecked() == true){tableRowCnt++;ui->tableWidget->setRowCount(tableRowCnt);createItemsARow(tableRowCnt-1,&message);hexMsg = ByteArrayToHexString(message).toLatin1();ui->textEdit_RecData->append(date+QString("-> ")+hexMsg.toUpper());}else{ui->textEdit_RecData->append(date+QString("-> ")+message);}
}
void Widget::openSerialport()
{ui->pushButton_closeSerialPort->setEnabled(true);ui->pushButton_openSerialPort->setEnabled(false);QList<QSerialPortInfo> comList = QSerialPortInfo::availablePorts();QSerialPortInfo portInfo = comList.at(ui->comboBox_chooseCom->currentIndex());serialPort->setPort(portInfo); //設(shè)置使用哪個(gè)串口if(serialPort->open(QIODevice::ReadWrite) == false){QMessageBox::critical(NULL, "critical", "找不到串口/串口被占用", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);closeSerialport();}else{serialPort->setBaudRate(QSerialPort::Baud115200);serialPort->setDataBits(QSerialPort::Data8);serialPort->setParity(QSerialPort::NoParity);serialPort->setStopBits(QSerialPort::OneStop);serialPort->setFlowControl(QSerialPort::NoFlowControl);ui->pushButton_sendData->setEnabled(true);}
}void Widget::closeSerialport()
{if(serialPort->isOpen()){serialPort->clear();serialPort->close();}ui->pushButton_closeSerialPort->setEnabled(false);ui->pushButton_openSerialPort->setEnabled(true);
}void Widget::setBuad(int buad)
{QString str = ui->comboBox_setBuad->currentText();serialPort->setBaudRate(str.toInt());
}void Widget::clearRcv()
{ui->textEdit_RecData->clear();
}void Widget::on_btnClear_clicked()
{ui->lineEdit_protocalData->clear();
}void Widget::on_btnConvert_clicked()
{ui->lineEdit_protocalData->clear();bool ok;QString str = "A5";int val1= ui->lineEditCmd1->text().toInt(&ok,16); //以十六進(jìn)制數(shù)讀入QString str1 = QString("%1").arg(val1, 2, 16, QLatin1Char('0'));int val2= ui->lineEditCmd2->text().toInt(&ok,16); //以十六進(jìn)制數(shù)讀入QString str2 = QString("%1").arg(val2, 2, 16, QLatin1Char('0'));if ((str1.isEmpty())||(str2.isEmpty()))return;int val3= ui->lineEditData->text().toInt(&ok,16); //以十六進(jìn)制數(shù)讀入QString str3 = QString("%1").arg(val3, 2, 16, QLatin1Char('0'));uint8_t len = 6 + static_cast<uint8_t>(str3.length()/2);QString hexStr = QString("%1").arg(len, 2, 16, QLatin1Char('0'));str.append(hexStr);str.append(str1);str.append(str2);str.append(str3);uint8_t crc;QString tmp;for(int i=0; i<str3.length(); i+=2){tmp = ui->lineEditData->text()[i];tmp += ui->lineEditData->text()[i+1];crc+= tmp.toInt(&ok,16);tmp = "";}crc += len;crc += val1;crc += val2;QString hexCrc= QString("%1").arg(crc, 2, 16, QLatin1Char('0'));str.append(hexCrc);str.append("5A");str = str.toUpper();ui->lineEdit_protocalData->insert(str);
}void Widget::sendProtocalHexData()
{QString message = ui->lineEdit_protocalData->text();serialPort->write(QByteArray::fromHex(message.toLatin1()));
}
ui
代碼框架概覽
演示視頻
串口上位機(jī)(基本設(shè)置/協(xié)議收發(fā))演示_嗶哩嗶哩_bilibili
串口上位機(jī)(基本設(shè)置/協(xié)議收發(fā))演示