关于使用TCP-S7协议读写西门子PLC字符串的问题

我们可以使用TCP-S7协议读写西门子PLC,

比如PLC中定义一个String50 的地址DB300.20

地址DB300.20

DB块编号为300,偏移量【地址】是30

S7协议是西门子PLC自定义的协议,默认端口102,本质仍然是TCP协议的一种具体实现,

如果使用C#读写西门子PLC协议,需要开启一个TcpClient,然后连接102端口。然后发哦送两次握手之后即可读写。

一、PLC需要设置 运行远程对象的Put/GET访问

二、PLC还要手动开启对应DB块的【非优化访问】,DB块默认是【优化访问的,无偏移量】

对西门子PLC字符串的读写逻辑如下:

西门子PLC字符串逻辑 string50,占用52个字节(偏移量),第一个字节是最大长度,就是50,第二个字节是实际长度24,第三个字节之后就是ASCII码,

PLC解析逻辑为找到第二个字节的长度length.,然后查找length个字符,就结束

示例读写西门子字符串代码如下:

cs 复制代码
        /// <summary>
        /// 写入西门子PLC的字符串,写入的字节长度为length+2,其中第一个字节代表最大长度【PLC设定的】,第二个字节代表时间长度
        /// </summary>
        /// <param name="dbNumber"></param>
        /// <param name="offsetAddress"></param>
        /// <param name="maxLength"></param>
        /// <param name="writeString"></param>
        /// <returns></returns>
        static bool DB_WriteString(short dbNumber, ushort offsetAddress, int maxLength, string writeString) 
        {
            byte[] byteArray = new byte[maxLength + 2];
            byteArray[0] = (byte)maxLength;//第一个字节代表最大长度
            byteArray[1] = (byte)writeString.Length;//第二次字节代表实际长度
            if (byteArray[1] > byteArray[0]) 
            {
                throw new Exception($"实际长度【{byteArray[1]}】不能超过PLC字符串的最大设定长度【{maxLength}】");
            }
            byte[] stringByteArray = System.Text.Encoding.ASCII.GetBytes(writeString);
            Array.Copy(stringByteArray, 0, byteArray, 2, stringByteArray.Length);//第三个字节开始写入字符串的ASCII码
            return WriteSerialByteArray(dbNumber, offsetAddress, byteArray);
        }

        static bool WriteSerialByteArray(short dbNumber, ushort offsetAddress, byte[] byteArray) 
        {
            Console.WriteLine($"这里写入DB{dbNumber}.{offsetAddress}的连续字节数组【{string.Join(",", byteArray.Select(x => x.ToString("X2")))}】");
            return true;
        }

        static bool ReadSerialByteArray(short dbNumber, ushort offsetAddress, out byte[] byteArray)
        {            
            byteArray = new byte[] { 12, 6, 48, 49, 97, 98, 65, 66, 0, 0, 0, 0 };//假设读取12个字节
            Console.WriteLine($"这里读取DB{dbNumber}.{offsetAddress}的连续字节数组【{string.Join(",", byteArray.Select(x => x.ToString("X2")))}】");
            return true;
        }

        /// <summary>
        /// 读取字符串:从第三个字节开始,读取实际长度个字符  actualLength = byteArray[1]
        /// </summary>
        /// <param name="dbNumber"></param>
        /// <param name="offsetAddress"></param>
        /// <param name="readString"></param>
        /// <returns></returns>
        static bool DB_ReadString(short dbNumber, ushort offsetAddress, out string readString)
        {
            ReadSerialByteArray(dbNumber, offsetAddress, out byte[] byteArray);
            if (byteArray.Length < 2) 
            {
                throw new Exception($"读取字符串时,原字节数组长度不能低于2");
            }
            byte maxLength = byteArray[0];
            byte actualLength = byteArray[1];
            if (byteArray.Length - 2 < actualLength) 
            {
                throw new Exception($"读取到的字节长度 小于 实际长度,非法的读取,PLC设定的字符串最大长度为【{maxLength}】");
            }
            readString = System.Text.Encoding.ASCII.GetString(new ArraySegment<byte>(byteArray, 2, actualLength).ToArray());
            return true;
        }
相关推荐
|_⊙18 小时前
网络层协议 IP
服务器·网络·tcp/ip
沫璃染墨20 小时前
从零入门计算机网络系列(十五):TCP可靠传输机制详解——从序号与确认应答到乱序处理
服务器·网络·c++·tcp/ip·tcp
流浪0011 天前
计算机网络篇20:网络层——IP 协议的定位与 IPv4 报头字段,从 20 字节首部到 TTL 防环
tcp/ip·计算机网络·ttl·网络层协议·ip报头
zhengfei6111 天前
CVE-2026-98432:Linux 内核 TCP 释放后重用漏洞,CVSS 9.8 但补丁覆盖极不均衡
linux·运维·tcp/ip
Soari1 天前
CaaS架构:让整个工业网络成为一台虚拟 PLC
plc·tsn·工业互联网·网内计算·控制即服务·计算通信联合调度
沫璃染墨2 天前
从零入门计算机网络系列(十四):TCP报文与字节流本质——从数据封装到报文边界
linux·服务器·网络·网络协议·tcp/ip·tcp
流浪0012 天前
计算机网络篇17:传输层——TCP 超时重传、三次握手与四次挥手,TIME_WAIT 为什么要等 2MSL
网络协议·tcp/ip·计算机网络·三次握手·四次挥手·超时重传
流浪0013 天前
计算机网络篇16:传输层——TCP 报头属性字段:16 位窗口大小撑起流量控制,六个标志位标识报文类型
网络协议·tcp/ip·计算机网络·urg紧急指针·tcp报头
从琳开始9893 天前
网络原理入门(二)------OSI七层模型?TCP/IP五层(四层)模型原来是这样的
java·网络·tcp/ip·java-ee·php
honsor3 天前
SNMP 读取以太网温湿度传感器数据,监控平台对接实操
物联网·网络协议·tcp/ip