当前位置: 首页 > news >正文

C++/Qt使用Snap7对西门子PLC 读写操作

ui界面

#ifndef PLC_DEMO_QTSNAP7_H #define PLC_DEMO_QTSNAP7_H #include <QWidget> #include <QMutex> #include "snap7.h" namespace Ui { class PLC_Demo_QtSnap7; } class PLC_Demo_QtSnap7 : public QWidget { Q_OBJECT public: explicit PLC_Demo_QtSnap7(QWidget *parent = nullptr); ~PLC_Demo_QtSnap7(); public: bool ClientConnectToPlc(); private slots: void on_btn_con_clicked(); void on_btn_disCon_clicked(); void on_btn_write_bit_clicked(); void on_btn_read_bit_clicked(); void on_btn_write_real_clicked(); void on_btn_read_real_clicked(); void on_btn_write_int_clicked(); void on_btn_read_int_clicked(); private: Ui::PLC_Demo_QtSnap7 *ui; std::shared_ptr<TS7Client> client_; QMutex mutex; bool isCon = false; }; #endif // PLC_DEMO_QTSNAP7_H
#include "plc_demo_qtsnap7.h" #include "ui_plc_demo_qtsnap7.h" #include <QMessageBox> PLC_Demo_QtSnap7::PLC_Demo_QtSnap7(QWidget *parent) : QWidget(parent) , ui(new Ui::PLC_Demo_QtSnap7) { ui->setupUi(this); ui->btn_con->setEnabled(true); ui->btn_disCon->setEnabled(false); } PLC_Demo_QtSnap7::~PLC_Demo_QtSnap7() { delete ui; } bool PLC_Demo_QtSnap7::ClientConnectToPlc() { client_ = std::make_shared<TS7Client>(); int res = client_->ConnectTo("192.168.88.129",0,1); // ==0 连接成功 if(res!=0) { ui->lab_concectdState->setText(("连接失败!")); ui->lab_concectdState->setStyleSheet("background-color:red;color:white;"); isCon = false; return false; } ui->lab_concectdState->setText(("连接成功")); ui->lab_concectdState->setStyleSheet("background-color:green;color:white;"); isCon = true; ui->btn_con->setEnabled(false); ui->btn_disCon->setEnabled(true); return true; } void PLC_Demo_QtSnap7::on_btn_con_clicked() { ui->btn_con->setEnabled(true); ui->btn_disCon->setEnabled(false); ClientConnectToPlc(); } void PLC_Demo_QtSnap7::on_btn_disCon_clicked() { client_->Disconnect(); ui->lab_concectdState->setText(("已断开连接!")); ui->lab_concectdState->setStyleSheet("background-color:red;color:white;"); } /* PLC 的控制字 假设一个 PLC 的 DB1.DBB4 是一个 16 位的控制字,定义如下: 位 0:启动电机 位 1:停止电机 位 2:复位故障 位 3:自动模式 位 4:手动模式 */ // 1个字节 = 8 (0~7)位 void PLC_Demo_QtSnap7::on_btn_write_bit_clicked() { quint8 control_byte ; QByteArray buffer; buffer.resize(1); client_->DBRead(1,4,1,buffer.data());//写入到buffer 缓冲区 control_byte = static_cast<quint8>(buffer[0]);// 当前控制字 //设置/清除位 //启动电机,设置位0为1,位1为0 ,其他位保持不变 // 比如 control_byte : 0000 0100 control_byte |= (1<<0);//0000 0101 control_byte &= ~(1<<1);//0000 0101 // 清除位 buffer[0] = control_byte; int res = client_->DBWrite(1,4,1,buffer.data()); if(res==0) { QMessageBox::information(this, "成功", "写入成功!"); } else { QMessageBox::critical(this, "错误", QString("写入失败,错误码:%1").arg(res)); qDebug() << "DBWrite error:" <<res; } //清除位 //停止电机,同时清除启动位(位 0)并设置停止位(位 1) control_byte &= ~(1<<0); // 清除位 0 control_byte |= (1<<1); // 设置位 1 buffer[0] = control_byte; res = client_->DBWrite(1,4,1,buffer.data()); if(res==0) { QMessageBox::information(this, "成功", "写入成功!"); } else { QMessageBox::critical(this, "错误", QString("写入失败,错误码:%1").arg(res)); qDebug() << "DBWrite error:" <<res; } } void PLC_Demo_QtSnap7::on_btn_read_bit_clicked() { } void PLC_Demo_QtSnap7::on_btn_write_real_clicked() { if(!client_ || !client_->Connected() ) return; // float 类型占4个字节,西门子PLC中是大端序 float real_value = ui->write_real_value->text().toFloat(); int start = 264; uint32_t value; std::memcpy(&value, &real_value, sizeof(float)); // 将float值复制到uint32_t中 QByteArray buffer; buffer.resize(4); // 分配4个字节用于写入float值 buffer[0] = (value >> 24) & 0xFF; // 高字节在前 buffer[1] = (value>>16) & 0xFF; buffer[2] = (value >> 8) & 0xFF; buffer[3] = value & 0xFF; int res = client_->DBWrite(1, start, 4, buffer.data());//第四个参数应为 void* 指向存放数据的缓冲区 if(res==0) { QMessageBox::information(this, "成功", "写入成功!"); } else { QMessageBox::critical(this, "错误", QString("写入失败,错误码:%1").arg(res)); qDebug() << "DBWrite error:" <<res; } } void PLC_Demo_QtSnap7::on_btn_read_real_clicked() { if(!client_ || !client_->Connected() ) { ui->lab_concectdState->setText(("已断开连接!")); ui->lab_concectdState->setStyleSheet("background-color:red;color:white;"); return; } QByteArray buffer; buffer.resize(4); // 分配4个字节用于读取float值 int start = 264; int res = client_->DBRead(1,start,4,buffer.data()); if(res==0) { // 读取成功,将字节转换为float // 注意:PLC中可能是高字节在前,所以需要转换 // 先将4个字节组合成一个uint32_t值,再通过memcpy转换为float // 正确组合:先将每个字节转为 uint8_t,再按大端序组合 uint32_t value = (static_cast<uint8_t>(buffer[0]) << 24) | (static_cast<uint8_t>(buffer[1]) << 16) | (static_cast<uint8_t>(buffer[2]) << 8) | static_cast<uint8_t>(buffer[3]); float real_value; std::memcpy(&real_value,&value,sizeof(float)); qDebug()<<value<<" "<<real_value; ui->read_real_value->setText(QString::number(real_value,'f')); } else { QMessageBox::warning(this,"读取数据","读取失败"); } } void PLC_Demo_QtSnap7::on_btn_write_int_clicked() { /* 西门子 int 2个字节 BYTE:1 字节 WORD:2 字节(无符号) DINT:4 字节(有符号) DWORD:4 字节(无符号) REAL:4 字节(浮点数)*/ if(!client_ || !client_->Connected() ) { ui->lab_concectdState->setText(("已断开连接!")); ui->lab_concectdState->setStyleSheet("background-color:red;color:white;"); return; } quint16 int_value = ui->write_int_value->text().toShort(); int start = 262; QByteArray buffer; buffer.resize(2); buffer[0] = (int_value>>8) & 0xFF;//高字节在前 buffer[1] = int_value & 0xFF; int res = client_->DBWrite(1,start,2,buffer.data()); if(res==0) { QMessageBox::information(this, "成功", "写入成功!"); } else { QMessageBox::critical(this, "错误", QString("写入失败,错误码:%1").arg(res)); qDebug() << "DBWrite error:" <<res; } } void PLC_Demo_QtSnap7::on_btn_read_int_clicked() { if(!client_ || !client_->Connected() ) { ui->lab_concectdState->setText(("已断开连接!")); ui->lab_concectdState->setStyleSheet("background-color:red;color:white;"); return; } QByteArray buffer; buffer.resize(2); int start = 262; int res = client_->DBRead(1,start,2,buffer.data()); if(res!=0) { QMessageBox::critical(this, "错误", QString("读取失败,错误码:%1").arg(res)); qDebug() << "DBWrite error:" <<res; return; } // 高字节在前 << 8 | 低字节 quint16 int_value = (static_cast<quint8>(buffer[0]<<8) | static_cast<quint8>(buffer[1])); ui->read_int_value->setText(QString::number(int_value)); }
http://www.jsqmd.com/news/527820/

相关文章:

  • 别再让标签打架了!高德地图上车辆标签重叠的3种优雅解决方案(附Vue代码)
  • **数据库技术基础**章节中关于**SQL(结构化查询语言)**的核心知识点,主要聚焦于**字符串模式匹配**和**视图查询
  • ChatGPTuino:ESP32/Arduino轻量级LLM嵌入式客户端
  • 图像融合技术:小波变换与拉普拉斯金字塔方法
  • 免费商用地图哪里找?用QGIS+HCMGIS插件搞定建筑轮廓/路网数据下载
  • Swig实战指南:从零构建Java与C/C++的跨语言桥梁(CMake集成版)
  • 大厂都在找场景,滴滴先把 AI 装进了出行里
  • DeOldify移动端适配初探:在Android设备上实现本地图片上色功能
  • 平面设计师效率工具:RMBG-2.0背景移除镜像实战,复杂场景轻松处理
  • 通义千问1.5-1.8B-Chat-GPTQ-Int4实战:辅助C语言初学者理解指针与内存
  • 《深度研究:提示工程架构师在Agentic AI上下文工程用户体验设计的创新实践》
  • AI Infinity镜像大赛圆满收官!17 款优质镜像上线,共筑国产算力开发者新生态
  • 2026最权威AI论文写作软件排名:这些工具被高校和导师悄悄推荐
  • 5大步骤让老款Mac重获新生:OpenCore Legacy Patcher系统升级全指南
  • GLM-4-9B-Chat-1M详细步骤:vLLM启用max_num_batched_tokens=8192吞吐优化
  • Opera 2026年的最近更新后发布个 Web 30 年回顾
  • Docker容器化离线部署Jitsi-Meet:从镜像打包到内网启动全解析
  • 从价格战到价值战:蚂蚁保定期寿险调价背后的市场新周期
  • 周五下午五点半,客户说“系统挂了“
  • Qwen3-ForcedAligner-0.6B在语言教学中的创新应用:跟读节奏可视化方案
  • 极海G32R430绝对值编码器参考方案,为人形机器人及工业自动化注入感知协同芯动能
  • 思源宋体TTF:企业级开源中文字体解决方案全解析
  • 【嵌入式】读代码之startup_stm32f103xb.s
  • 用Dobot机械臂+Python+OpenCV打造你的AI画家:从拍照到素描全流程解析
  • Redis 缓存一致性方案设计思路
  • 编译原理实验避坑指南:算符优先分析法Java实现中的5个常见错误与调试方法
  • OFA视觉问答(VQA)一文详解:ModelScope模型本地化部署实践
  • 优优推联系方式查询指南:如何通过官方渠道获取服务信息并理解其数字营销业务 - 十大品牌推荐
  • 如何在不同业务场景下理解和拆解核心指标
  • 优优推联系方式查询:了解其数字营销服务组合与选择合作方时的通用考量指南 - 十大品牌推荐