0.实现效果
1.工程文件
#-------------------------------------------------
#
# Project created by QtCreator 2022-11-30T09:37:26
#
#-------------------------------------------------QT += core gui
QT += serialportgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = SerialServo
TEMPLATE = app# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0CONFIG += c++11SOURCES += \console.cpp \main.cpp \mainwindow.cpp \settingsdialog.cppHEADERS += \console.h \mainwindow.h \settingsdialog.hFORMS += \mainwindow.ui \settingsdialog.ui# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += targetRESOURCES += \serialservo.qrc
2. 接受显示区
#ifndef CONSOLE_H
#define CONSOLE_H#include class Console : public QPlainTextEdit
{Q_OBJECTsignals:void getData(const QByteArray &data);public:explicit Console(QWidget *parent = nullptr);void putData(const QByteArray &data);void setLocalEchoEnabled(bool set);protected:void keyPressEvent(QKeyEvent *e) override;void mousePressEvent(QMouseEvent *e) override;void mouseDoubleClickEvent(QMouseEvent *e) override;void contextMenuEvent(QContextMenuEvent *e) override;private:bool m_localEchoEnabled = false;
};#endif // CONSOLE_H
实现文件
#include "console.h"#include Console::Console(QWidget *parent) :QPlainTextEdit(parent)
{document()->setMaximumBlockCount(100);QPalette p = palette();p.setColor(QPalette::Base, Qt::black);p.setColor(QPalette::Text, Qt::green);setPalette(p);
}void Console::putData(const QByteArray &data)
{insertPlainText(data);// QScrollBar *bar = verticalScrollBar();
// bar->setValue(bar->maximum());
}void Console::setLocalEchoEnabled(bool set)
{m_localEchoEnabled = set;
}void Console::keyPressEvent(QKeyEvent *e)
{switch (e->key()) {case Qt::Key_Backspace:case Qt::Key_Left:case Qt::Key_Right:case Qt::Key_Up:case Qt::Key_Down:break;default:if (m_localEchoEnabled)QPlainTextEdit::keyPressEvent(e);emit getData(e->text().toLocal8Bit());}
}void Console::mousePressEvent(QMouseEvent *e)
{Q_UNUSED(e)setFocus();
}void Console::mouseDoubleClickEvent(QMouseEvent *e)
{Q_UNUSED(e)
}void Console::contextMenuEvent(QContextMenuEvent *e)
{Q_UNUSED(e)
}
3. 主程序
#include "mainwindow.h"
#include int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}
4. 主窗体程序
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include
#include QT_BEGIN_NAMESPACEclass QLabel;namespace Ui {
class MainWindow;
}QT_END_NAMESPACEclass Console;
class SettingsDialog;class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();QByteArray hexString2ByteArray(QString HexString);uint16_t comCrcValue(const uint8_t* data, uint16_t length);signals:void VDI1cmd(const QString &s);void VDI2cmd(const QString &s);void VDO1cmd(const QString &s);void Modelcmd(const QString &s);void ComVDIcmd(const QString &s);void ComVDOcmd(const QString &s);void ComVDIDefaultcmd(const QString &s);void DI5Funccmd(const QString &s);void CmdSourcecmd(const QString &s);void MulStageModcmd(const QString &s);void Displacementcmd(const QString &s);void PosAbsLinearcmd(const QString &s);void RunMotorcmd(const QString &s);void FillDisplacementcmd(const QString &s);private slots:void openSerialPort();void closeSerialPort();void about();void writeData(const QByteArray &data);void readData();void saveSettings();void handleError(QSerialPort::SerialPortError error);void on_pushButtonRun_clicked();void on_pushButtonEnable_clicked();void on_pushButtonDisable_clicked();void sendCommands(QString strcommands);void fillDisplacement(QString strcommands);private:void initActionsConnections();void initCommandsConnections();private:void showStatusMessage(const QString &message);Ui::MainWindow *m_ui = nullptr;QLabel *m_status = nullptr;Console *m_console = nullptr;SettingsDialog *m_settings = nullptr;QSerialPort *m_serial = nullptr;long m_displacement;
};#endif // MAINWINDOW_H
实现文件:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "console.h"
#include "settingsdialog.h"#include
#include #include
#include const int SLEEPMS = 50;MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),m_ui(new Ui::MainWindow),m_status(new QLabel),m_console(new Console),m_settings(new SettingsDialog),m_serial(new QSerialPort(this)),m_displacement(0)
{m_ui->setupUi(this);setWindowTitle(tr("Servo Motor Demo"));// m_console->setEnabled(false);
// setCentralWidget(m_console);m_ui->actionConnect->setEnabled(true);m_ui->actionDisconnect->setEnabled(false);m_ui->actionQuit->setEnabled(true);m_ui->statusBar->addWidget(m_status);initActionsConnections();initCommandsConnections();connect(m_serial, &QSerialPort::errorOccurred, this, &MainWindow::handleError);connect(m_serial, &QSerialPort::readyRead, this, &MainWindow::readData);
// connect(m_console, &Console::getData, this, &MainWindow::writeData);
}MainWindow::~MainWindow()
{delete m_ui;delete m_settings;
}void MainWindow::openSerialPort()
{const SettingsDialog::Settings p = m_settings->settings();m_serial->setPortName(p.name);m_serial->setBaudRate(p.baudRate);m_serial->setDataBits(p.dataBits);m_serial->setParity(p.parity);m_serial->setStopBits(p.stopBits);m_serial->setFlowControl(p.flowControl);if(m_serial->open(QIODevice::ReadWrite)){
// m_console->setEnabled(true);
// m_console->setLocalEchoEnabled(p.localEchoEnabled);m_ui->actionConnect->setEnabled(false);m_ui->actionDisconnect->setEnabled(true);m_ui->actionConfigure->setEnabled(false);showStatusMessage(tr("Connect to %1 :%2, %3, %4, %5, %6").arg(p.name).arg(p.stringBaudRate).arg(p.stringDataBits).arg(p.stringParity).arg(p.stringStopBits).arg(p.stringFlowControl));} else {QMessageBox::critical(this, tr("Error"), m_serial->errorString());showStatusMessage(tr("Open error"));}
}void MainWindow::closeSerialPort()
{if(m_serial->isOpen()){m_serial->close();}
// m_console->setEnabled(false);m_ui->actionConnect->setEnabled(true);m_ui->actionDisconnect->setEnabled(false);m_ui->actionConfigure->setEnabled(true);showStatusMessage(tr("Disconnected"));
}void MainWindow::about()
{QMessageBox::about(this, "About Serial Servo",tr("Serial Servo Demo"));
}uint16_t MainWindow::comCrcValue(const uint8_t* data, uint16_t length)
{uint16_t crcValue = 0xffff;int i;while (length--){crcValue ^= *data++;for (i = 0; i < 8; i++){if (crcValue & 0x0001){crcValue = (crcValue >> 1) ^ 0xA001;}else{crcValue = crcValue >> 1;}}}return (crcValue);
}void MainWindow::saveSettings()
{QString strVDI1cmd = QString("01 06 17 00 00 01 4D BE");QString strVDI2cmd = QString("01 06 17 02 00 1C 2C 77");QString strVDO1cmd = QString("01 06 17 21 00 05 1C 77");QString strModelcmd = QString("01 06 02 00 00 01 49 B2");QString strComVDIcmd = QString("01 06 0C 09 00 01 9B 58");QString strComVDOcmd = QString("01 06 0C 0B 00 01 3A 98");QString strComVDIDefaultcmd = QString("01 06 0C 0A 00 01 6B 58");QString strDI5Funccmd = QString("01 06 03 0A 00 00 A9 8C");QString strCmdSourcecmd = QString("01 06 05 00 00 02 08 C7");QString strMulStageModcmd = QString("01 06 11 00 00 00 8C F6");QString strDisplacementcmd = QString("01 10 11 0C 00 02 04 C3 50 00 00 0F FF");QString strPosAbsLinearcmd = QString("01 06 02 01 00 01 18 72");if(m_ui->checkBoxVDI1->checkState() == Qt::Checked){emit VDI1cmd(strVDI1cmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxVDI2->checkState() == Qt::Checked){emit VDI2cmd(strVDI2cmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxVDO1->checkState() == Qt::Checked){emit VDO1cmd(strVDO1cmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxModel->checkState() == Qt::Checked){emit Modelcmd(strModelcmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxComVDI->checkState() == Qt::Checked){emit ComVDIcmd(strComVDIcmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxComVDO->checkState() == Qt::Checked){emit ComVDOcmd(strComVDOcmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxComVDIDefault->checkState() == Qt::Checked){emit ComVDIDefaultcmd(strComVDIDefaultcmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxDI5Func->checkState() == Qt::Checked){emit DI5Funccmd(strDI5Funccmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxCmdSource->checkState() == Qt::Checked){emit CmdSourcecmd(strCmdSourcecmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxMulStageMod->checkState() == Qt::Checked){emit MulStageModcmd(strMulStageModcmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxDisplacement->checkState() == Qt::Checked){emit Displacementcmd(strDisplacementcmd);QThread::msleep(SLEEPMS);}if(m_ui->checkBoxPosAbsLinear->checkState() == Qt::Checked){emit PosAbsLinearcmd(strPosAbsLinearcmd);QThread::msleep(SLEEPMS);}
}void MainWindow::sendCommands(QString strcommands)
{QByteArray settingCmd;settingCmd = hexString2ByteArray(strcommands);writeData(settingCmd);
}void MainWindow::writeData(const QByteArray &data)
{m_serial->write(data);m_serial->waitForBytesWritten(1000);
}void MainWindow::readData()
{const QByteArray data = m_serial->readAll();
// m_console->putData(data);
}void MainWindow::handleError(QSerialPort::SerialPortError error)
{if(error == QSerialPort::ResourceError){QMessageBox::critical(this, tr("Critical Error"), m_serial->errorString());closeSerialPort();}
}void MainWindow::initActionsConnections()
{connect(m_ui->actionConnect, &QAction::triggered, this, &MainWindow::openSerialPort);connect(m_ui->actionDisconnect, &QAction::triggered, this, &MainWindow::closeSerialPort);connect(m_ui->actionQuit, &QAction::triggered, this, &MainWindow::close);connect(m_ui->actionConfigure, &QAction::triggered, m_settings, &SettingsDialog::show);
// connect(m_ui->actionClear, &QAction::triggered, m_console, &Console::clear);connect(m_ui->actionAbout, &QAction::triggered, this, &MainWindow::about);connect(m_ui->actionSaveSetting, &QAction::triggered, this, &MainWindow::saveSettings);
}void MainWindow::initCommandsConnections()
{connect(this, &MainWindow::VDI1cmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::VDI2cmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::VDO1cmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::Modelcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::ComVDIcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::ComVDOcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::ComVDIDefaultcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::DI5Funccmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::CmdSourcecmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::MulStageModcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::Displacementcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::PosAbsLinearcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::RunMotorcmd, this, &MainWindow::sendCommands);connect(this, &MainWindow::FillDisplacementcmd, this, &MainWindow::fillDisplacement);
}void MainWindow::showStatusMessage(const QString &message)
{m_status->setText(message);
}QByteArray MainWindow::hexString2ByteArray(QString HexString)
{bool ok;QByteArray ret;HexString = HexString.trimmed();HexString = HexString.simplified();QStringList sl = HexString.split(" ");foreach (QString s, sl) {if(!s.isEmpty()){char c = s.toInt(&ok,16) & 0xFF;if(ok){ret.append(c);}else{qDebug()<<"invalid hex string"<lineEditDisplacement->text();QString strDisplacement = strcommands;long ldisplacement = strDisplacement.toLong();if((ldisplacement < 10000) || (ldisplacement > 100000)){QMessageBox::warning(this,"Warning","Please enter the value between 10000 and 100000");qDebug() << "invalid value: should be between 10000 and 100000" << endl;return;}QByteArray runCmd;uint16_t a;uint16_t dataLow;uint16_t dataHigh;uint8_t data[13];data[0] = 0x01;data[1] = 0x10;data[2] = 0x11;data[3] = 0x0C;data[4] = 0x00;data[5] = 0x02;data[6] = 0x04;dataLow = ldisplacement & 0xffff;dataHigh = (ldisplacement >> 16) & 0xffff;data[7] = (dataLow >> 8) & 0xff;data[8] = dataLow & 0xff;data[9] = (dataHigh >> 8) & 0xff;data[10] = dataHigh & 0xff;a = comCrcValue(data, 11);data[11] = a & 0xff;data[12] = (a >> 8) & 0xff;QString request= QString("");for (int i=0; i<13;i++) {request += QString("%1 ").arg(data[i],2,16,QChar('0'));}runCmd = hexString2ByteArray(request);writeData(runCmd);}void MainWindow::on_pushButtonRun_clicked()
{long longTemp = m_ui->lineEditDisplacement->text().toLong();if (m_displacement != longTemp){m_displacement = longTemp;emit FillDisplacementcmd(m_ui->lineEditDisplacement->text());QThread::msleep(SLEEPMS);}QString strRunMotorcmd = QString("01 06 31 00 00 03 C7 37");emit RunMotorcmd(strRunMotorcmd);QThread::msleep(SLEEPMS);
}void MainWindow::on_pushButtonEnable_clicked()
{QString strEnableMotorcmd = QString("01 06 31 00 00 01 46 F6");QByteArray runCmd;runCmd = hexString2ByteArray(strEnableMotorcmd);writeData(runCmd);
}void MainWindow::on_pushButtonDisable_clicked()
{QString strDisableMotorcmd = QString("01 06 31 00 00 00 87 36");QByteArray runCmd;runCmd = hexString2ByteArray(strDisableMotorcmd);writeData(runCmd);
}