本文通过将图片和代码结合的方式,讲解西门子 PLC S7 协议和开发。
本文部分内容参考 Snap7 官网(【参考1】), 博客文章 The Siemens S7 Communication - Part 1 General Structure(【参考2】)、Part 2 Job Requests and Ack Data 。
关键要点:
本文内容
首先展示一下西门子 S7 系列 PLC 硬件。
西门子并没有发布 S7 协议的官方文档,如下几个开源网站可以帮助理解 S7 协议:
本文所说的 S7 协议(S7 protocol)特指“S7 以太网”通信(基于 RFC1006 使用 TCP/IP 传输),主要用于西门子 PLC 连接到 PC 工作站。从下图可知,西门子 S7 协议也可以通过其他协议(如图中的 FDL)传输数据。
图 1:从 ISO 七层参考模型视角看 S7 协议,图片来源于 S7 协议有哪些属性,优势及特征?
图 2:协议封装,图片来源于 Snap7 Siemens communications overview
如图2,S7协议数据单元(PDU)主要包含三个部分:
报头长度为10至12字节,其中确认消息包含两个额外的错误代码字节。除此之外,所有协议数据单元(PDU)的报头格式都是一致的。
图 2:S7 协议报文头,图片来源于【参考 2】
字段:
从 snap7-full-1.4.2 中拷贝文件到对应目录即可。
例如,Windows 开发环境下,
日常开发中可以 Snap7 Server 当模拟器用。
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include "lib/snap7.h"
TS7Server *Server;
unsigned char DB1[512]; // Our DB1
unsigned char DB2[128]; // Our DB2
unsigned char DB3[1024]; // Our DB3
unsigned char MB[2048]; // 2048 = CPU 315 Merkers amount
int main(int argc, char* argv[])
{
int Error;
Server = new TS7Server;
Server->RegisterArea(srvAreaDB, // We are registering a DB
1, // Its number is 1 (DB1)
&DB1, // Its address
sizeof(DB1)); // Its size
Server->RegisterArea(srvAreaDB, 2, &DB2, sizeof(DB2));
Server->RegisterArea(srvAreaDB, 3, &DB3, sizeof(DB3));
// Let’s share all Merkers from M0.0 to M2047.7
Server->RegisterArea(srvAreaMK, 0, &MB, sizeof(MB));
// Start the server onto the default adapter “0.0.0.0”
Error=Server->Start();
if (Error==0)
{
// Now the server is running ... wait a key to terminate
getchar();
}
else
printf("%s\n",SrvErrorText(Error).c_str());
Server->Stop(); // not strictly needed
delete Server;
}
#include <iostream>
#include "lib/snap7.h"
// 连接参数
const char* plc_address = "127.0.0.1";
const int rack = 0;
const int slot = 0;
// 数据位置
static int db_number = 1;
const int data_offset = 66;
// 数据存储变量
static bool mydata = false;
int main(){
TS7Client* MyClient = new TS7Client();
MyClient->ConnectTo(plc_address, rack, slot);
if (!MyClient->Connected() && MyClient->Connect()>0) {
return -1;
}
bool newVal = true;
MyClient->DBWrite(db_number, data_offset, 1, &newVal);
MyClient->DBRead(db_number, data_offset, 1, &mydata);
std::cout << "mydata:" << mydata << std::endl;
//输出:mydata:1
delete MyClient;
}
格式转换可以参考库:S7-cpp-for-Snap7 :Mapping data for Snap7 library in C/C++
发布于:2024-10-27 18:57:00 描述有误?我来纠错