0.实现效果
1.工程文件
#-------------------------------------------------
#
# Project created by QtCreator 2022-11-30T09:37:26
#
#-------------------------------------------------
QT += core gui
QT += serialport
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = 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.0
CONFIG += c++11
SOURCES += \
console.cpp \
main.cpp \
mainwindow.cpp \
settingsdialog.cpp
HEADERS += \
console.h \
mainwindow.h \
settingsdialog.h
FORMS += \
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 += target
RESOURCES += \
serialservo.qrc
2. 接受显示区
#ifndef CONSOLE_H
#define CONSOLE_H
#include <QPlainTextEdit>
class Console : public QPlainTextEdit
{
Q_OBJECT
signals:
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 <QScrollBar>
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 <QApplication>
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 <QMainWindow>
#include <QSerialPort>
QT_BEGIN_NAMESPACE
class QLabel;
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class Console;
class SettingsDialog;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
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 <QLabel>
#include <QMessageBox>
#include <QDebug>
#include <QThread>
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"<<s;
}
}
}
return ret;
}
void MainWindow::fillDisplacement(QString strcommands)
{
// QString strDisplacement = m_ui->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);
}