C# 连接 PLC 的S7西门子协议读写,样例分享

最近在研究PLC\C#版本,做了个小Demo

你要连接PLC 用已经有的连接引用S7.Net

下面是代码分享

c 复制代码
		private Plc plc;
        //连接plc
        public bool Connect(string ip, short rack, short slot)
        {
            try
            {
                plc = new Plc(CpuType.S71200, ip, rack, slot);
                plc.Open();

                if (plc.IsConnected)
                {
                    Console.WriteLine("成功连接到PLC");
                    return true;
                }
                else
                {
                    Console.WriteLine("连接失败");
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"连接错误: {ex.Message}");
                return false;
            }
        }

        //断开plc连接
        public void Disconnect()
        {
            if (plc != null && plc.IsConnected)
            {
                plc.Close();
                Console.WriteLine("已断开PLC连接");
            }
        }

连接里面有什么

c 复制代码
CpuType.S71200 连接类型
ip ip地址
port 端口号
rack 机架号
slot 槽位号

连接了之后就操作

先了解有哪些类型,你要学一个东西,建议多翻翻里面的源码(一点个人经验)

这些类型有我们知道的类型,有我们不知道的类型,第一时间做一下对照

c 复制代码
word  : ushort
dword : uint
int   : float
dint  : byte
real  :float

其他类型大差不差

好了,对照了类型之后我们开始获取数据,想看看我们的引用给我们提供了什么些方法

不吹不黑,我是觉得写这些dll 的人是真的非常厉害,好了,我这边决定先用 ReadBytes

先贴代码,有的没的先贴上去,带坏你们我不管哈哈哈

重点:传出参数有哪些

c 复制代码
DataType.DataBlock 块类型
db  块号
startByteAdr 开始的偏移地址
count 字节数
c 复制代码
        public Task<List<DataItem>> ReadMultipleVarsAsync(List<DataItem> Datlist)
        {
            Task<List<DataItem>> bytes = plc.ReadMultipleVarsAsync(Datlist);
            return bytes;
        }


        public float ReadReal(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 4);
            float value = S7.Net.Types.Real.FromByteArray(bytes);
            return value;
        }

        public float ReadInt(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 2);
            float value = S7.Net.Types.Int.FromByteArray(bytes);
            return value;
        }


        // 读取DINT(32位有符号)
        public int ReadDInt(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 4);
            return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
        }

        public ushort ReadWord(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 2);
            ushort value = (ushort)((bytes[0] << 8) | bytes[1]);
            return value;
        }

        public uint ReadWord2_DWord(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 4);
            uint result = BitConverter.ToUInt32(bytes.Reverse().ToArray(), 0);
            //uint result = (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
            return result;
        }

        public int ReadTime(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 4);
            int milliseconds = S7.Net.Types.DInt.FromByteArray(bytes);
            return milliseconds;
        }

        public bool ReadBool(string pyl, int kh)
        {
            string[] pdbs = pyl.Split('.');
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, int.Parse(pdbs[0]), 1);
            bool judge = false;
            if (pdbs.Length > 1)
            {
                judge = (bytes[0] & (1 << int.Parse(pdbs[1]))) != 0;
            }
            else
            {
                judge = (bytes[0] & (1 << 0)) != 0;
            }
            return judge;
        }

        public int ReadArray(int pyl, int kh)
        {
            byte[] bytes = plc.ReadBytes(DataType.DataBlock, kh, pyl, 4);
            return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3];
        }

ReadBytes 一般般,不太好用,实际上不符合我想要的东西

我要大批量传输 ReadMultipleVarsAsync

c 复制代码
  /// <summary>
        /// 获取类型
        /// </summary>
        /// <param name="plc_sjlx"></param>
        /// <returns></returns>
        public VarType setVarType(string plc_sjlx)
        {
            if (plc_sjlx == "real")
            {
                return VarType.Real;
            }
            else if (plc_sjlx == "word")
            {
                return VarType.Word;
            }
            else if (plc_sjlx == "dint")
            {
                return VarType.DInt;
            }
            else if (plc_sjlx == "dword")
            {
                return VarType.DWord;
            }
            else if (plc_sjlx == "int")
            {
                return VarType.Int;
            }
            return VarType.Real;
        }

/// <summary>
        /// 添加到集合
        /// </summary>
        /// <param name="currentTime">当前时间</param>
        /// <param name="listsj">运行次序</param>
        private async Task ExecuteTasks(long currentTime, List<int> listsj)
        {
            List<PlcBlzdbCs> tasksToExecute = new List<PlcBlzdbCs>();//记录组合的地址
            int remainingCapacity = _maxTasksPerExecution;//剩余请求地址数量
            foreach (var interval in listsj)
            {
                //返回值
                TaskGroup group;
                //获取返回值
                if (!_taskGroups.TryGetValue(interval, out group)) continue;
                //当前时间减去上次运行时间大于你的优先级时间则加入
                if (currentTime - group.LastRunTime >= interval)
                {
                    int availableTasks = group.Tasks.Count;
                    int tasksToTake = Math.Min(availableTasks, remainingCapacity);//判断
                    if (tasksToTake > 0)
                    {
                        List<PlcBlzdbCs> tasks =  group.Tasks;
                        tasks.Sort((p1, p2) => p1.Scheduler.CompareTo(p2.Scheduler));
                        tasksToExecute.AddRange(tasks.GetRange(0, tasksToTake));
                        remainingCapacity -= tasksToTake;
                        if (availableTasks <= tasksToTake)
                        {
                            group.LastRunTime = currentTime;
                        }
                        if (remainingCapacity == 0) break;
                    }
                }
            }

            if (tasksToExecute.Count > 0)
            {
                List<S7.Net.Types.DataItem> datas = new List<S7.Net.Types.DataItem>();
                var s7 = new S7Communication();
                string ipdz = "";
                foreach (PlcBlzdbCs task in tasksToExecute)
                {
                    task.Scheduler += 1;
                    if (ipdz == "") { ipdz = task.plc_ip; }
                    VarType type = setVarType(task.plc_sjlx);
                    datas.Add(new S7.Net.Types.DataItem
                    {
                        DataType = S7.Net.DataType.DataBlock,
                        VarType = type,
                        DB = int.Parse(task.plc_cck),
                        StartByteAdr = int.Parse(task.plc_pydz),
                        Count = 1,
                    });
                }

                if (s7.Connect(ipdz, 0, 1))
                {
                    try
                    {
                        var task = s7.ReadMultipleVarsAsync(datas);
                        List<S7.Net.Types.DataItem> taskresult = await task;
                        foreach (var item in taskresult)
                        {
                            PlcBlzdbCs zdb = tasksToExecute.Where(m => m.plc_pydz == item.StartByteAdr.ToString()).FirstOrDefault();
                            PlcBlfhz fhz = new PlcBlfhz();
                            fhz.plc_uuid = zdb.plc_uuid;
                           
                            fhz.plc_delete = "1";
                            PlcBlfhzManager plcblfhzmanager = new PlcBlfhzManager();
                            int xznr = plcblfhzmanager.insertData(fhz);
                        }
                        return;
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"读取数据时发生异常: {ex.Message}");
                        CommonMethods.AddLog(1, "读取数据时发生异常");
                        return; // 直接返回,避免后续代码执行
                    }
                }
            }

重点 ReadMultipleVarsAsync 这个返回的是一个 Task ,我代码是没贴全的,你要用这个方法你得处理这个异步任务,具体怎么处理就看你的业务需求了,只是代码片段就是想你不要拿来直接用,多学习学习,你说是吧

相关推荐
一心赚狗粮的宇叔8 小时前
中级软件开发工程师2025年度总结
java·大数据·oracle·c#
cplmlm9 小时前
EF Core使用CodeFirst生成postgresql数据库表名以及字段名用蛇形命名法,而类名仍使用驼峰命名
c#
lingxiao1688810 小时前
WebApi详解+Unity注入--下篇:Unity注入
unity·c#·wpf
lingxiao1688813 小时前
WebApi详解+Unity注入--中篇:.net core的WebAPI
unity·c#·.netcore
ServBay14 小时前
C# 成为 2025 年的编程语言,7个C#技巧助力开发效率
后端·c#·.net
故事不长丨17 小时前
C#进制转换:从基础原理到实战应用
开发语言·c#·进制转换·16进制·2进制·10进制
liulilittle17 小时前
VEthernet 框架实现 tun2socks 的技术原理
网络·windows·c#·信息与通信·通信
云草桑18 小时前
.net AI API应用 客户发的信息提取对接上下游系统报价
ai·c#·.net·semantickernel·sk
故事不长丨19 小时前
C#File文件操作全解析:从基础用法到异常处理
服务器·开发语言·visualstudio·c#·文件操作·io流·file
工程师00720 小时前
C# 动态编程(基于 dynamic 类型)
开发语言·c#·dynamic·动态编程