目录
一、西门子PLC仿真环境搭建
【1.1】创建PLC项目
【1.2】编写PLC程序
二、C#代码编写
【2.1】窗口制作
【2.2】效果演示
【2.3】读取源码
【2.4】FrmSiemensSet源码
【2.5】Variable源码
搭建PLCSIM-Advacend模拟仿真
设置PLC的IP地址和PLCSIM一致
勾选GET/PUT(如果是S7协议必须勾选)选项
勾选块编译时仿真
创建变量用于测试,相关的DB块需要设置为去除优化访问
【PLC作为服务器】
【Modbus Poll测试】
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
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);
}
}
}
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; }
}
}