本文通过将图片和代码结合的方式,讲解西门子 PLC S7 协议和开发。
本文部分内容参考 Snap7 官网(【参考1】), 博客文章 The Siemens S7 Communication - Part 1 General Structure(【参考2】)、Part 2 Job Requests and Ack Data 。
关键要点:
本文内容
首先展示一下西门子 S7 系列 PLC 硬件。
 
        s7-300
 
        s7-400
 
        s7-1200
 
        s7-1500
西门子并没有发布 S7 协议的官方文档,如下几个开源网站可以帮助理解 S7 协议:
本文所说的 S7 协议(S7 protocol)特指“S7 以太网”通信(基于 RFC1006 使用 TCP/IP 传输),主要用于西门子 PLC 连接到 PC 工作站。从下图可知,西门子 S7 协议也可以通过其他协议(如图中的 FDL)传输数据。
 图 1:从 ISO 七层参考模型视角看 S7 协议,图片来源于 S7 协议有哪些属性,优势及特征?
图 1:从 ISO 七层参考模型视角看 S7 协议,图片来源于 S7 协议有哪些属性,优势及特征?
 图 2:协议封装,图片来源于 Snap7 Siemens communications overview
图 2:协议封装,图片来源于 Snap7 Siemens communications overview
如图2,S7协议数据单元(PDU)主要包含三个部分:
报头长度为10至12字节,其中确认消息包含两个额外的错误代码字节。除此之外,所有协议数据单元(PDU)的报头格式都是一致的。
 图 2:S7 协议报文头,图片来源于【参考 2】
图 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 描述有误?我来纠错