基于ModbusTCP与西门子PLC通讯项目案例

目录

一、西门子PLC仿真环境搭建

【1.1】创建PLC项目

【1.2】编写PLC程序

二、C#代码编写

【2.1】窗口制作

【2.2】效果演示

【2.3】读取源码

【2.4】FrmSiemensSet源码

【2.5】Variable源码


一、西门子PLC仿真环境搭建

【1.1】创建PLC项目

基于ModbusTCP与西门子PLC通讯项目案例_第1张图片

  • 搭建PLCSIM-Advacend模拟仿真

基于ModbusTCP与西门子PLC通讯项目案例_第2张图片

  • 设置PLC的IP地址和PLCSIM一致

基于ModbusTCP与西门子PLC通讯项目案例_第3张图片

  • 勾选GET/PUT(如果是S7协议必须勾选)选项

基于ModbusTCP与西门子PLC通讯项目案例_第4张图片

  • 勾选块编译时仿真

基于ModbusTCP与西门子PLC通讯项目案例_第5张图片

  • 创建变量用于测试,相关的DB块需要设置为去除优化访问

基于ModbusTCP与西门子PLC通讯项目案例_第6张图片

【1.2】编写PLC程序

【PLC作为服务器】

基于ModbusTCP与西门子PLC通讯项目案例_第7张图片

【Modbus Poll测试】

基于ModbusTCP与西门子PLC通讯项目案例_第8张图片

二、C#代码编写

【2.1】窗口制作

基于ModbusTCP与西门子PLC通讯项目案例_第9张图片

【2.2】效果演示

基于ModbusTCP与西门子PLC通讯项目案例_第10张图片

【2.3】读取源码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
​
using Approach.DataConvertLib;
using Approach.ModbusTCPLib;
​
namespace Approach.ModbusTCP
{
    public partial class FrmSiemens : Form
    {
        /// 
        /// 【字段】ModbusTCP连接对象
        /// 
        private ModbusTcp _modbusTcp = new ModbusTcp();
​
        /// 
        /// 【字段】ModbusTCP连接成功标识
        /// 
        private bool _isConnected = false;
​
        /// 
        /// 【字段】多线程取消对象
        /// 
        private CancellationTokenSource _cts = null;
​
        public FrmSiemens()
        {
            InitializeComponent();
        }
​
        /// 
        /// 【控件事件】建立连接
        /// 
        /// 
        /// 
        private void btn_Connect_Click(object sender, EventArgs e)
        {
            // 获取UI信息
            string plcIp = txt_Ip.Text.Trim();
            int plcPort = int.Parse(txt_Port.Text.Trim());
​
            _isConnected = _modbusTcp.Connect(plcIp, plcPort);
            if (_isConnected == true)
            {
                MessageBox.Show("与西门子PLC连接成功!", "连接提示");
                // 开启线程(创建取消线程对象)
                _cts = new CancellationTokenSource();
                // 开启线程(创建线程对象)
                Task.Run(new Action(() =>
                {
                    PlcCommunicatin();
                }), _cts.Token);
            }
            else
            {
                MessageBox.Show("与西门子PLC连接失败!", "连接提示");
            }
        }
​
        /// 
        /// 【方法】与PLC进行通信的线程方法
        /// 
        private void PlcCommunicatin()
        {
            // 线程循环执行
            while(!_cts.IsCancellationRequested)
            {
                // 通过ModbusTCP读取寄存器信息(PLC发送182字节->读取91个字)
                byte[] readData = _modbusTcp.ReadOutputRegisters(0, 91);
                // 读取对应的字节个数
                if(readData != null && readData.Length == 182) // 读取成功
                {
                    // 解析报文,跟新UI数据
                    Invoke(new Action(() => {
                        UpdateUI(readData, gb_Read);
                        UpdateUI(readData, gb_Write);
                    }));
                }
            }
        }
​
        /// 
        /// 【方法】
        /// 
        ///  被处理的数据字节数组 
        ///  控件对象 
        private void UpdateUI(byte[] data, Control control)
        {
            if (!control.HasChildren)
                return;
​
            // 程序走到这里说明:Control控件中包含一个或者多个子控件
            foreach (var item in control.Controls.OfType

【2.4】FrmSiemensSet源码

using Approach.DataConvertLib;
using Approach.ModbusTCPLib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
​
namespace Approach.ModbusTCP
{
    public partial class FrmSiemensSet : Form
    {
        private Variable _variable = null;
        private ModbusTcp _modbusTcp = null;
​
        public FrmSiemensSet(string srcValue, Variable variable, ModbusTcp modbusTcp)
        {
            InitializeComponent();
            lbl_SrcValue.Text = srcValue;
            lbl_ValueType.Text = variable.ValueType.ToString();
​
            _variable = variable;
            _modbusTcp = modbusTcp;
        }
​
​
​
        private void btn_Ok_Click(object sender, EventArgs e)
        {
            bool bResult = false;
            try
            {
                switch (_variable.ValueType)
                {
                    case DataType.Short:
                        {
                            bResult = _modbusTcp.PreSetSingleRegister((ushort)(_variable.Start / 2), Convert.ToInt16(txt_SetValue.Text.Trim()));
                            break;
                        }
                    case DataType.UShort:
                        {
                            bResult = _modbusTcp.PreSetSingleRegister((ushort)(_variable.Start / 2), Convert.ToInt16(txt_SetValue.Text.Trim()));
                            break;
                        }
                    case DataType.Int:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromInt(Convert.ToInt32(txt_SetValue.Text.Trim())));
                            break;
                        }
                    case DataType.UInt:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromUInt(Convert.ToUInt32(txt_SetValue.Text.Trim())));
                            break;
                        }
                    case DataType.Float:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromFloat(Convert.ToSingle(txt_SetValue.Text.Trim())));
                            break;
                        }
                    case DataType.Double:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromDouble(Convert.ToDouble(txt_SetValue.Text.Trim())));
                            break;
                        }
                    case DataType.Long:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromLong(Convert.ToInt64(txt_SetValue.Text.Trim())));
                            break;
                        }
                    case DataType.ULong:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromULong(Convert.ToUInt64(txt_SetValue.Text.Trim())));
                            break;
                        }
                    case DataType.String:
                        {
                            bResult = _modbusTcp.PreSetMultiRegisters((ushort)(_variable.Start / 2), ByteArrayLib.GetByteArrayFromSiemensString(txt_SetValue.Text.Trim()));
                            break;
                        }
                    default:
                        {
                            MessageBox.Show("不支持该数据类型写入", "参数设置");
                            return;
                        }
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show("请检查参数数据类型是否正确:" + ex.Message, "参数设置");
                return;
            }
​
            if (bResult == true)
            {
                this.DialogResult = DialogResult.OK;
            }
        }
        private void btn_Cancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
        }
​
        private void FrmSiemensSet_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btn_Ok_Click(null, null);
        }
    }
}

【2.5】Variable源码

using Approach.DataConvertLib;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
​
namespace Approach.ModbusTCP
{
    /// 
    /// 变量实体类封装
    /// 
    public class Variable
    {
        /// 
        /// 标签名称
        /// 
        public string ValueName { get; set; }
​
        /// 
        /// 起始字节
        /// 
        public int Start { get; set; }
​
        /// 
        /// 数据类型
        /// 
        public DataType ValueType { get; set; }
​
        /// 
        /// (位偏移)或(字符串)长度
        /// 
        public int OffsetOrLength { get; set; }
​
        /// 
        /// 变量实际值
        /// 
        public object Value { get; set; }
    }
}

你可能感兴趣的:(C#,c#)