前言

  西门西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 "PlcServerManager.h"
#include <QMessageBox>
#include <QFile>
#include <QHostAddress>
#include <QDebug> #define LOG qDebug()<<__FILE__<<__LINE__ PlcServerManager *PlcServerManager::_pInstance = 0;
QMutex PlcServerManager::_mutex; void PlcServerManager::callBack_event(void *usrPtr, PSrvEvent PEvent, int Size)
{
switch (PEvent->EvtCode)
{
case evcDataRead: // 读取数据 break;
case evcDataWrite: // 写入数据
emit _pInstance->signal_dataChanged();
break;
default:
break;
} } QHash<int, QByteArray> PlcServerManager::getHashDB2ByteArray() const
{
return _hashDB2ByteArray;
} PlcServerManager::PlcServerManager(QObject *parent)
: QObject(parent),
_running(false),
_pTS7Server(0),
_listen(false)
{
} PlcServerManager *PlcServerManager::getInstance()
{
if(!_pInstance)
{
QMutexLocker lock(&_mutex);
if(!_pInstance)
{
_pInstance = new PlcServerManager();
}
}
return _pInstance;
} void PlcServerManager::slot_start()
{
if(_running)
{
LOG << "It's already running!!!";
return;
}
_running = true;
_pTS7Server = new TS7Server();
} void PlcServerManager::slot_stop()
{
if(!_running)
{
LOG << "It's not running!!!";
return;
}
if(_pTS7Server)
{
_running = false;
_pTS7Server->Stop();
delete _pTS7Server;
_pTS7Server = 0;
}
} void PlcServerManager::slot_listen(QString ip)
{
if(!_running)
{
LOG << "It's not running!!!";
return;
}
if(_listen)
{
LOG << "It's already listen!!!";
return;
}
_ip = ip;
_pTS7Server->SetEventsCallback(PlcServerManager::callBack_event, 0);
_pTS7Server->StartTo(_ip.toUtf8().data());
_listen = true;
emit signal_listenStateChanged(_listen);
} void PlcServerManager::slot_stopListen()
{
if(!_running)
{
LOG << "It's not running!!!";
return;
}
LOG << _pTS7Server->Stop();
_listen = false;
emit signal_listenStateChanged(_listen);
} void PlcServerManager::slot_regsiterDB(int dbNum, int size)
{
if(!_running)
{
LOG << "It's not running!!!";
return;
}
QByteArray byteArray(size, 0x00);
_hashDB2ByteArray.insert(dbNum, byteArray);
_pTS7Server->RegisterArea(srvAreaDB, dbNum, _hashDB2ByteArray[dbNum].data(), byteArray.size());
} void PlcServerManager::slot_setDB(int dbNum, QByteArray data)
{
if(!_running)
{
LOG << "It's not running!!!";
return;
}
if(_hashDB2ByteArray.contains(dbNum))
{
for(int index = 0; index < data.size(); index++)
{
_hashDB2ByteArray[dbNum][index] = data.at(index);
}
LOG << _hashDB2ByteArray.value(dbNum).toHex(' ');
}
}
 

若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110071837

项目实战:Qt西门子PLC通讯调试和模拟工具(包含PLC上位机通讯,PLC服务器)的更多相关文章

  1. 倍福TwinCAT3上位机与PLC通信测试(ADS通信) 包含C#和C++代码

    倍福TwinCAT3上位机与PLC通信测试(ADS通信) 包含C#和C++代码 本次测试需要环境: VS2013,TwinCAT3(本人版本TC31-Full-Setup.3.1.4018.16) 代 ...

  2. 多个rs485设备怎样跟上位机通讯?

    http://bbs.hcbbs.com/thread-819457-1-1.html 多个rs485设备怎样跟上位机通讯? [复制链接] |关注本帖     fdemeng 签到天数: 1228 天 ...

  3. (原创)使用C#开发高性能PLC上位机监控系统服务器应用程序

    PLC服务器监控系统的特点: 1·使用微软C#面向对象开发语言开发应用程序.2·使用了健壮性与性能良好的SUPER SOCKET服务器通信框架,实现自定义应用层通信协议,支持多台PC客户端访问服务器, ...

  4. 案例分享:Qt西门子机床人机界面以及数据看板定制(西门子通讯,mysql数据库,生产信息,参数信息,信息化看板,权限控制,播放器,二维图表,参数调试界面)

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/118685521 长期持续带来更多项目与技术分享 ...

  5. c#上位机与三菱PLC(FX3U)串口通讯

    项目中会经常用到上位机与PLC之间的串口通信,本文介绍一下C#如何编写上位机代码 与三菱FX3U进行通讯 1. 第一种方法是自己写代码实现,主要代码如下: //对PLC的Y7进行置1 byte[] Y ...

  6. 嵌入式Linux学习笔记(六) 上位机QT界面实现和串口通讯实现

    目录 (1).参考资料 (2).QT界面布局实现 (3).数据和操作逻辑 在上一章我们实现了下位机的协议制定,并通过串口通讯工具完成了对设备内外设(LED)的状态修改,下面就要进行上位机软件的实现了( ...

  7. WinForm通用自动更新AutoUpdater项目实战

    目前我们做的上位机项目还是以Winform为主,在实际应用过程中,可能还会出现一些细节的修改.对于这种情况,如果上位机带有自动更新功能,我们只需要将更新后的应用程序打包放在指定的路径下,可以让用户自己 ...

  8. 开源纯C#工控网关+组态软件(四)上下位机通讯原理

    一.   网关的功能:承上启下 最近有点忙,更新慢了.感谢园友们给予的支持,现在github上已经有.目标是最好的开源组态,看来又近一步^^ 之前有提到网关是物联网的关键环节,它的作用就是承上启下. ...

  9. 【大话QT之十六】使用ctkPluginFramework插件系统构建项目实战

    "使用ctkPluginFramework插件系统构建项目实战",这篇文章是写博客以来最纠结的一篇文章. 倒不是由于技术都多么困难,而是想去描写叙述一个项目架构採用ctkPlugi ...

  10. QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL

    QT5 QSS QML界面美化视频课程系列 QT原理 项目实战 C++1X STL 课程1   C语言程序设计高级实用速成课程 基础+进阶+自学 课程2   C语言程序设计Windows GDI图形绘 ...

随机推荐

  1. [转帖]数据库篇-MySql架构介绍

    https://zhuanlan.zhihu.com/p/147161770 公众号-坚持原创,码字不易.加微信 : touzinv 关注分享,手有余香~ 本篇咱们也来聊聊mysql物理和逻辑架构,还 ...

  2. [转帖]记录几个常用linux命令的使用方法——find、grep、file、which、whereis和压缩命令gzip、bzip2、tar

    一.命令1: find.grep.file.which.whereis 1.find 目的:查找符合条件的文件 1)在哪些目录中查找 2)查找的内容 格式: find 目录名 选项 查找条件 举例: ...

  3. Zabbix6.0的安装与IPMI的简单使用

    zabbix简介 1.zabbix的安装与使用 建议使用CentOS8进行部署, 不建议使用CentOS7, rpm包直接部署的话,CentOS8比较容易一些 支持mysql数据库.建议先期部署mys ...

  4. 使用rpm打包nacos然后部署为systemd服务开机自动启动的方法

    背景 Nacos是阿里开源的服务注册组件,能够简单的实现微服务的注册与发现机制. 但是官方并没有提供 sytemd的服务脚本, 也没有提供rpm包的方式. 公司里面使用 nacos的场景越来越多, 部 ...

  5. 小记录 单选框的注意点 html中字符串拼接 el-upload手动上传 表格跳转 v-for动态添加背景色 控制label标签于文本框之间的间距

    在element-ui中 单选框的v-model的值最好是一个字符串 否者可能不能够进行数据回填哈 单选框 的类型必须是字符串类型哈 在elemnet-ui中 如果你想从A页面拿到B页面中的值 可以有 ...

  6. 【一个小发现】VictoriaMetrics 中 vmselect 的 `-search.denyPartialResponse` 选项不应该开启

    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 一直以为vmselect 的 -search.denyPa ...

  7. 自动化部署实例(donetcore GitLab CICD )

    主要简单的介绍了一下 GitLab CI 的持续集成以及持续部署,这篇将通过 GitLab CI 发布一个 .net core 项目,来带小伙伴们感受一下自动化的魅力,从此告别手动发布. 准备工作 创 ...

  8. TortoiseGit 常见问题汇总

    1.test分支修改后合并到master分支 1)切换本地分支到master分支 2)TortoiseGit --->  merge,选择远程分支test 提交到远程分支master 2.将远程 ...

  9. Go中字符串处理:fmt.Sprintf与string.Builder的比较

    在Go语言中,我们通常会遇到两种主要的方式来处理和操作字符串:使用fmt.Sprintf函数和string.Builder类型.尽管两者都可以实现字符串的格式化和连接,但它们在性能和用法上有一些关键区 ...

  10. GIT专业术语教程-转载

    目录 一.版本控制概要 1.1.什么是版本控制 1.2.常用术语 1.3.常见的版本控制器 1.4.版本控制分类 1.4.1.本地版本控制 1.4.2.集中版本控制 1.4.3.分布式版本控制 1.5 ...