若該文為原創文章,轉載請注明原文出處
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110071837
各位讀者,知識無窮而人力有窮,要么改需求,要么找專業人士,要么自己研究
紅胖子(紅模仿)的博文大全:開發技術集合(包含Qt實用技術、樹莓派、三維、OpenCV、OpenGL、ffmpeg、OSG、單片機、軟硬結合等等)持續更新中…(點擊傳送門)
Qt開發專欄:專案實戰(點擊傳送門)
前言
??西門西PLC、臺達觸摸屏、法蘭克機床等等多年以前玩得比較多,改造機床、維修機床、給機床編程等等,沒事還能車個零件啥的,對于多年以前的研發改造,有時間就重新整理下,
??先上點有歷史年代感的照片:
??
??
??
??
??
??
??
??
需求
??基于Qt實作與PLC通訊功能,
Demo
??
??
體驗下載地址
??CSDN:https://download.csdn.net/download/qq21497936/13239895
??QQ群:1047134658(點擊“檔案”搜索“plcCommunication”,群內與博文同步更新)
v1.2.0
??
??
v1.1.0
??
??
關鍵原始碼
??
??
??
PlcWidget.h
#ifndef PLCSERVERMANAGER_H
#define PLCSERVERMANAGER_H
/************************************************************\
* 控制元件名稱:PlcServerManager
* 功能描述:Plc通訊服務器(用于模擬PLC,包括仿真DB資料空間)
* 控制元件功能:
* 1.唯一實體類
* 2.注冊DB
* 3.監聽、停止監聽
* 4.對所有事件進行反饋
* 作者:長沙紅胖子(AAA紅模仿)
* 博客專家地址:https://blog.csdn.net/qq21497936/article/details/102478062
* 聯系方式:QQ(21497936) 微信(yangsir198808)
* 版本資訊
* 日期 版本號 描述
* 2020年11月23日 v1.0.0 基礎功能
* 2020年12月01日 v1.1.0 增加客戶端寫入提示信號
\************************************************************/
#include <QObject>
#include <QMutex>
#include <QHash>
#include "snap7.h"
class PlcServerManager : public QObject
{
Q_OBJECT
private:
explicit PlcServerManager(QObject *parent = 0);
public:
static PlcServerManager * getInstance();
QHash<int, QByteArray> getHashDB2ByteArray() const;
signals:
void signal_listenStateChanged(bool listen);
void signal_dataChanged();
public slots:
void slot_start();
void slot_stop();
void slot_listen(QString ip);
void slot_stopListen();
void slot_regsiterDB(int dbNum, int size);
void slot_setDB(int dbNum, QByteArray data);
private:
static PlcServerManager *_pInstance;
static QMutex _mutex;
static void callBack_event(void *usrPtr, PSrvEvent PEvent, int Size);
private:
bool _running; // 執行緒是否啟用
bool _listen; // 是否連接PLC
QString _ip; // ip地址
QStringList _listIp; // 連接上的客戶端地址
TS7Server *_pTS7Server;
QHash<int, QByteArray> _hashDB2ByteArray;
};
#endif // PLCMANAGER_H
PlcWidget.cpp
#include "PlcWidget.h"
#include "ui_PlcWidget.h"
#include <QDebug>
#define LOG qDebug()<<__FILE__<<__LINE__
PlcWidget::PlcWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::PlcWidget),
_pPlcClientManager(0),
_pPlcClientManagerThread(0),
_pPlcServerManager(0),
_pPlcServerManagerThread(0),
_pTimer(0)
{
ui->setupUi(this);
QString version = "v1.2.0";
setWindowTitle(QString::fromLocal8Bit("西門子PLC通訊Demo %1(作者:紅胖子(AAA紅模仿) QQ:21497936 微信:yangsir198808 博客地址:blog.csdn.net/qq21497936)").arg(version));
// 西門子客戶端初始化
_pPlcClientManager = PlcClientManager::getInstance();
_pPlcClientManagerThread = new QThread;
_pPlcClientManager->moveToThread(_pPlcClientManagerThread);
connect(_pPlcClientManagerThread, SIGNAL(started()),
_pPlcClientManager, SLOT(slot_start()));
connect(_pPlcClientManager, SIGNAL(signal_connectedChanged(bool)),
this, SLOT(slot_connectedChanged(bool)));
connect(_pPlcClientManager, SIGNAL(signal_readDB(int,int,int,QByteArray)),
this, SLOT(slot_readDB(int,int,int,QByteArray)));
_pPlcClientManagerThread->start();
// 西門子服務器初始化
_pPlcServerManager = PlcServerManager::getInstance();
_pPlcServerManagerThread = new QThread;
_pPlcServerManager->moveToThread(_pPlcServerManagerThread);
connect(_pPlcServerManagerThread, SIGNAL(started()),
_pPlcServerManager, SLOT(slot_start()));
connect(_pPlcServerManager, SIGNAL(signal_listenStateChanged(bool)),
this, SLOT(slot_listenStateChanged(bool)));
connect(_pPlcServerManager, SIGNAL(signal_dataChanged()),
this, SLOT(slot_dataChanged()));
_pPlcServerManagerThread->start();
// 初始化控制元件
ui->pushButton_connect->setEnabled(true);
ui->pushButton_disconncet->setEnabled(false);
// 客戶端:控制元件初始化
ui->lineEdit_dbNum->setValidator(new QIntValidator(0, 1024));
ui->lineEdit_dbStart->setValidator(new QIntValidator(0, 1023));
ui->lineEdit_dbSize->setValidator(new QIntValidator(1, 1023));
ui->lineEdit_dbInterval->setValidator(new QIntValidator(100, 10000));
ui->groupBox_read->setEnabled(false);
ui->pushButton_readDB->setEnabled(true);
ui->pushButton_startReadDB->setEnabled(true);
ui->pushButton_stopReadDB->setEnabled(false);
// 回圈讀取定時器
_pTimer = new QTimer(this);
connect(_pTimer, SIGNAL(timeout()), this, SLOT(slot_timeOut()));
// 服務端:控制元件初始化
ui->lineEdit_serverDbNum->setValidator(new QIntValidator(0, 512));
ui->pushButton_serverListen->setEnabled(true);
ui->pushButton_serverStopListen->setEnabled(false);
ui->lineEdit_serverDbNum->setEnabled(true);
ui->lineEdit_serverDbSize->setEnabled(true);
ui->textEdit_serverDB->setEnabled(false);
}
PlcWidget::~PlcWidget()
{
delete ui;
}
void PlcWidget::slot_connectedChanged(bool connected)
{
LOG << connected;
if(connected)
{
ui->pushButton_connect->setEnabled(false);
ui->pushButton_disconncet->setEnabled(true);
ui->groupBox_read->setEnabled(true);
}else{
ui->pushButton_connect->setEnabled(true);
ui->pushButton_disconncet->setEnabled(false);
ui->groupBox_read->setEnabled(false);
}
}
void PlcWidget::slot_readDB(int dbNum, int start, int size, QByteArray data)
{
if(ui->pushButton_connect->isEnabled())
{
return;
}
ui->textEdit_db->append(QString("========== %1 readDB DB%2: %3->%4 total: %5 bytes ==========")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"))
.arg(dbNum)
.arg(start)
.arg(start + size - 1)
.arg(size));
int rowNum = 10;
for(int index = 0; index < data.size(); index+=rowNum)
{
QString str = data.mid(index, rowNum).toHex(' ');
str.push_front("0x");
str = str.replace(" ", " 0x");
str = QString("%1 -> %2 : ")
.arg(start + index)
.arg(start + index + rowNum - 1)
+ str;
ui->textEdit_db->append(str);
}
if(!_pTimer->isActive())
{
ui->pushButton_readDB->setEnabled(true);
}
}
void PlcWidget::slot_timeOut()
{
if(ui->pushButton_connect->isEnabled())
{
on_pushButton_stopReadDB_clicked();
return;
}
QMetaObject::invokeMethod(_pPlcClientManager,
"slot_readDB",
Q_ARG(int, ui->lineEdit_dbNum->text().toInt()),
Q_ARG(int, ui->lineEdit_dbStart->text().toInt()),
Q_ARG(int, ui->lineEdit_dbSize->text().toInt()));
}
void PlcWidget::on_pushButton_connect_clicked()
{
QMetaObject::invokeMethod(_pPlcClientManager,
"slot_connectTo",
Q_ARG(QString, ui->lineEdit_ip->text()));
// 控制元件
ui->pushButton_connect->setEnabled(false);
ui->pushButton_disconncet->setEnabled(false);
ui->groupBox_read->setEnabled(false);
}
void PlcWidget::on_pushButton_disconncet_clicked()
{
_pPlcClientManager->slot_disconnct();
// 控制元件
ui->pushButton_connect->setEnabled(true);
ui->pushButton_disconncet->setEnabled(false);
ui->groupBox_read->setEnabled(false);
}
void PlcWidget::on_pushButton_readDB_clicked()
{
QMetaObject::invokeMethod(_pPlcClientManager,
"slot_readDB",
Q_ARG(int, ui->lineEdit_dbNum->text().toInt()),
Q_ARG(int, ui->lineEdit_dbStart->text().toInt()),
Q_ARG(int, ui->lineEdit_dbSize->text().toInt()));
ui->pushButton_readDB->setEnabled(false);
}
void PlcWidget::on_pushButton_writeDB_clicked()
{
QByteArray data;
if(ui->comboBox_type->currentText() == "byte")
{
data.append((uchar)ui->lineEdit_writeData->text().toInt());
_pPlcClientManager->slot_writeDB(ui->lineEdit_writeDBNum->text().toInt(),
ui->lineEdit_writeDBStart->text().toInt(),
1,
data);
}else if(ui->comboBox_type->currentText() == "int") {
int i = ui->lineEdit_writeData->text().toInt();
data.append((uchar)(i / 256 / 265 / 256));
data.append((uchar)(i / 256 / 265 % 256));
data.append((uchar)(i / 256 % 256));
data.append((uchar)(i % 256));
_pPlcClientManager->slot_writeDB(ui->lineEdit_writeDBNum->text().toInt(),
ui->lineEdit_writeDBStart->text().toInt(),
4,
data);
}
}
void PlcWidget::on_pushButton_startReadDB_clicked()
{
_pTimer->start(ui->lineEdit_dbInterval->text().toInt());
ui->pushButton_readDB->setEnabled(false);
ui->pushButton_startReadDB->setEnabled(false);
ui->pushButton_stopReadDB->setEnabled(true);
}
void PlcWidget::on_pushButton_stopReadDB_clicked()
{
_pTimer->stop();
ui->pushButton_readDB->setEnabled(true);
ui->pushButton_startReadDB->setEnabled(true);
ui->pushButton_stopReadDB->setEnabled(false);
}
void PlcWidget::slot_listenStateChanged(bool listen)
{
LOG << listen;
if(listen)
{
ui->pushButton_serverListen->setEnabled(false);
ui->pushButton_serverStopListen->setEnabled(true);
ui->textEdit_serverDB->setEnabled(true);
ui->lineEdit_ip->setEnabled(false);
ui->lineEdit_serverDbNum->setEnabled(false);
ui->lineEdit_serverDbSize->setEnabled(false);
}else{
ui->pushButton_serverListen->setEnabled(true);
ui->pushButton_serverStopListen->setEnabled(false);
ui->textEdit_serverDB->setEnabled(false);
ui->lineEdit_ip->setEnabled(true);
ui->lineEdit_serverDbNum->setEnabled(true);
ui->lineEdit_serverDbSize->setEnabled(true);
}
}
void PlcWidget::slot_dataChanged()
{
QHash<int, QByteArray> hashDB2Bytearray = _pPlcServerManager->getHashDB2ByteArray();
if(hashDB2Bytearray.contains(ui->lineEdit_serverDbNum->text().toInt()))
{
QString str;
QByteArray byteArray = hashDB2Bytearray.value(ui->lineEdit_serverDbNum->text().toInt());
ui->textEdit_serverDB->clear();
ui->textEdit_serverDB->setText(QString(byteArray.toHex(' ')));
};
}
void PlcWidget::on_pushButton_serverListen_clicked()
{
_pPlcServerManager->slot_regsiterDB(ui->lineEdit_serverDbNum->text().toInt(),
ui->lineEdit_serverDbSize->text().toInt());
QMetaObject::invokeMethod(_pPlcServerManager,
"slot_listen",
Q_ARG(QString, ui->lineEdit_serverIp->text()));
// 控制元件
ui->pushButton_serverListen->setEnabled(false);
ui->pushButton_serverStopListen->setEnabled(false);
ui->lineEdit_serverDbNum->setEnabled(false);
ui->lineEdit_serverDbSize->setEnabled(false);
ui->lineEdit_ip->setEnabled(false);
QHash<int, QByteArray> hashDB2Bytearray = _pPlcServerManager->getHashDB2ByteArray();
if(hashDB2Bytearray.contains(ui->lineEdit_serverDbNum->text().toInt()))
{
QString str;
QByteArray byteArray = hashDB2Bytearray.value(ui->lineEdit_serverDbNum->text().toInt());
ui->textEdit_serverDB->clear();
ui->textEdit_serverDB->setText(QString(byteArray.toHex(' ')));
}
}
void PlcWidget::on_pushButton_serverStopListen_clicked()
{
_pPlcServerManager->slot_stopListen();
// 控制元件
ui->pushButton_serverListen->setEnabled(true);
ui->pushButton_serverStopListen->setEnabled(false);
ui->lineEdit_serverDbNum->setEnabled(true);
ui->lineEdit_serverDbSize->setEnabled(true);
ui->lineEdit_serverIp->setEnabled(true);
}
void PlcWidget::on_pushButton_serverSet_clicked()
{
QByteArray byteArray;
QString str = ui->textEdit_serverDB->toPlainText();
str = str.replace("\n", "");
str = str.replace(" ", " ");
QStringList list = str.split(" ");
LOG << ui->lineEdit_serverDbSize->text().toInt() << list.size();
if(ui->lineEdit_serverDbSize->text().toInt() == list.size())
{
for(int index = 0; index < list.size(); index++)
{
QString d = list.at(index);
byteArray.append(d.toInt(0, 16));
}
_pPlcServerManager->slot_setDB(ui->lineEdit_serverDbNum->text().toInt(),
byteArray);
}
}
void PlcWidget::on_pushButton_clear_clicked()
{
ui->textEdit_db->clear();
}
若該文為原創文章,轉載請注明原文出處
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110071837
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/230339.html
標籤:其他
