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 ,我代码是没贴全的,你要用这个方法你得处理这个异步任务,具体怎么处理就看你的业务需求了,只是代码片段就是想你不要拿来直接用,多学习学习,你说是吧

相关推荐
斯内科1 小时前
C#进行CAN【控制器局域网】通讯
c#·can·pcanbasic.net
张人玉3 小时前
C#WPF——MVVM框架编写管理系统所遇到的问题
开发语言·c#·wpf·mvvm框架
马达加斯加D4 小时前
C# --- 如何写UT
前端·c#·log4j
Charles_go4 小时前
C#中级39、什么是依赖注入设计模式
java·设计模式·c#
eggcode5 小时前
C#开源库ACadSharp将Dwg转Dxf
c#·dxf·dwg
拼好饭和她皆失5 小时前
C#学习入门
开发语言·学习·c#
小小编程能手7 小时前
大小端字节序
c#
冒泡P9 小时前
【Unity】TextMeshPro富文本中使用精灵图集
ui·unity·c#·游戏引擎
世洋Blog9 小时前
开发思想-组合模式和接口多态的一点思考
c#·组合模式