1.该程可以实现c#与西门子全系列plc(200smart,300,400,1200,1500)的以太网s7通讯,通讯传输快稳定。
2.该程序采用.dll动态链接库方式,是最近几年才出来的一种与西门子plc通讯的方式,本人经过几个星期的测试,找到他的所有使用方法和注意事项,并开发了一个通用类库可以读取写入各种类型的数据,字符串,bool,16位整数,32位整数,浮点数还有struct数据结构。
3.该程序还可以实时监控上位机与plc的通讯状态。程序稍微改造就可以应用到实际项目,已经应用到多条生产线系统中;
4.下面有部分程序源码,如果您需要全套源码+V:1357448516。或者qq:584472557
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using S7.Net;
using System.Threading;
using System.Threading.Tasks;
namespace S7net通信测试
{
public partial class Form1 : Form
{
//该测试程序举了两个PLC实例,PLC1对应S7-200Smart,一定要注意对于S7-200Smart的驱动CpuType.S71200,因为S7-200Smart的通讯协议跟1200是一样的.
//S7-200SmartPLC的V区就用S7-1200PLC的DB1代替,比如想读取VD100,那就用地址DB1.DBD100代替,其他区域跟1200一样。
//PLC2对应S7-1200PLC
S7NetPLC PLC2 = new S7NetPLC(CpuType.S71200, "192.168.0.1", 0, 1);//S7-1200PLC
//textbox控件Text多线程调用枚举
private delegate void delegateText(TextBox textbox, string text);
//label控件Text多线程调用枚举
private delegate void delegateLab(Label textbox, string text);
//CheckBox控件多线程调用枚举
private delegate void delegateCheck(CheckBox checkbox, bool bl);
//PLC循环线程,该线程是实时读取PLC1变量处理数据用的
private Thread threadPLCCycle;
//界面加载延时定时器
System.Windows.Forms.Timer DownloadDelayedTimer;
private bool writeBoolEn = false;
private bool writeStringEn = false;
private bool writeByteEn = false;
private bool writeUshortEn = false;
private bool writeShortEn = false;
private bool writeIntEN = false;
private bool writeRealEN = false;
private bool writeStructEN = false;
private bool writeClassEN = false;
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 界面加载延时处理函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void DownloadDelayedTimer_Tick(object sender, EventArgs e)
{
DownloadDelayedTimer.Enabled = false;
//PLC2.connectPLC();
threadPLCCycle = new Thread(Connectplc);
threadPLCCycle.IsBackground = true;
threadPLCCycle.Start();
}
/// <summary>
/// PLC循环控制线程函数
/// </summary>
private void Connectplc()
{
while (true)
{
PLC2.connectPLC();//判断通讯连接状态
if (PLC2.ConectStatus == true)
{
labShow(labPLC2Conect, "连接");
labPLC2Conect.BackColor = Color.Lime;
}
else
{
labShow(labPLC2Conect, "断开");
labPLC2Conect.BackColor = Color.Red;
}
PLC2CyceleControl();//PLC读写控制
}
}
/// <summary>
/// PLC2循环读取写入方法
/// </summary>
private void PLC2CyceleControl()
{
try
{
if (PLC2.ConectStatus == true)
{
labShow(label10, PLC2.linkErrNum.ToString());//显示重连次数
//bool写入控制
if (writeBoolEn == true)
{
if (chBoxWriteBool2.Checked)
{
//往M10.0写入true
PLC2.WriteBoolenM("M10.0", true);
}
else
{
//往M10.0写入false
PLC2.WriteBoolenM("M10.0", false);
}
if (chBoxWriteBool1.Checked)
{
//往Q0.0写入true
PLC2.WriteBoolenQ("Q0.0", true);
}
else
{
//往Q0.0写入false
PLC2.WriteBoolenQ("Q0.0", false);
}
if (chBoxWriteBool3.Checked)
{
//往DB1.DBX0.0写入true
PLC2.WriteBoolenDB("DB1.DBX0.0", true);
}
else
{
//往DB1.DBX0.0写入false
PLC2.WriteBoolenDB("DB1.DBX0.0", false);
}
writeBoolEn = false;
}
//写入Stirng类型控制
if (writeStringEn == true)
{
string string1 = txtBoxWriteChars.Text;
PLC2.WriteString(CpuType.S71200, DataType.DataBlock, 1, 22, string1, 20);//往DB1.DBB21开始的字节写入字符串,注意:起始地址填字符串首地址
writeStringEn = false;
}
//写入Byte类型控制
if (writeByteEn == true)
{
if (chBoxWriteB1.Checked)
{
byte by = byte.Parse(txtBoxWrtieB.Text.Trim());
}
if (chBoxWriteB2.Checked)
{
byte by = byte.Parse(txtBoxWrtieB.Text.Trim());//往MB11写8位字节整数
PLC2.WriteByte("MB11", by);
}
if (chBoxWriteB3.Checked)
{
byte by = byte.Parse(txtBoxWrtieB.Text.Trim());
PLC2.WriteByte("DB1.DBB1", by);//往DB1.DBB1写8位整数
}
writeByteEn = false;
}
//写入16位无符号整数控制
if (writeUshortEn == true)
{
if (chBoxWriteWord1.Checked)
{
ushort by = ushort.Parse(txtBoxWrtieWord.Text.Trim());
}
if (chBoxWriteWord2.Checked)
{
ushort by = ushort.Parse(txtBoxWrtieWord.Text.Trim());
PLC2.WriteWord("MW12", by);//往MW12写16位无符号整数
}
if (chBoxWriteWord3.Checked)
{
ushort by = ushort.Parse(txtBoxWrtieWord.Text.Trim());
PLC2.WriteWord("DB1.DBW2", by);//往DB1.DBW2写16位无符号整数
}
writeUshortEn = false;
}
//写入16位整数控制
if (writeShortEn == true)
{
if (chBoxWriteInt1.Checked)
{
short by = short.Parse(txtBoxWrtieInt.Text.Trim());
}
if (chBoxWriteInt2.Checked)
{
short by = short.Parse(txtBoxWrtieInt.Text.Trim());
PLC2.WriteShort("MW14", by);//往MW14写16位有符号整数
}
if (chBoxWriteInt3.Checked)
{
short by = short.Parse(txtBoxWrtieInt.Text.Trim());
PLC2.WriteShort("DB1.DBW4", by);//往DB1.DBW4写16位有符号整数
}
writeShortEn = false;
}
//读取双整数控制
if (writeIntEN == true)
{
if (chBoxWriteDInt1.Checked)
{
int by = int.Parse(txtBoxWrtieDInt.Text.Trim());
}
if (chBoxWriteDInt2.Checked)
{
int by = int.Parse(txtBoxWrtieDInt.Text.Trim());
PLC2.WriteInt("MD16", by);//往MD16写32位有符号整数
}
if (chBoxWriteDInt3.Checked)
{
int by = int.Parse(txtBoxWrtieDInt.Text.Trim());
PLC2.WriteInt("DB1.DBD6", by);//往DB1.DBD6写32位有符号整数
}
writeIntEN = false;
}
//写入浮点数控制
if (writeRealEN == true)
{
if (chBoxWriteFloat1.Checked)
{
double by = double.Parse(txtBoxWrtieFloat.Text.Trim());
}
if (chBoxWriteFloat2.Checked)
{
double by = double.Parse(txtBoxWrtieFloat.Text.Trim());
PLC2.WriteReal("MD20", by);//往MD20写32位浮点数
}
if (chBoxWriteFloat3.Checked)
{
double by = double.Parse(txtBoxWrtieFloat.Text.Trim());
PLC2.WriteReal("DB1.DBD10", by);//往DB1.DBD10写32位浮点数
}
writeRealEN = false;
}
//写入Struct控制
if (writeStructEN == true)
{
try
{
TestStruct typeStruct = new TestStruct();
typeStruct.Var1 = double.Parse(txtBoxWrtieStruct1.Text.Trim());
typeStruct.Var2 = ushort.Parse(txtBoxWrtieStruct2.Text.Trim());
typeStruct.Var3 = short.Parse(txtBoxWrtieStruct3.Text.Trim());
PLC2.plc.WriteStruct(typeStruct, 1, 14);//往DB1.DBB14开始的字节开始的结构写入值
}
catch (Exception ex)
{
}
writeStructEN = false;
}
//写入类批量测试程序
if(writeClassEN ==true)
{
try
{
TestClass typeClass = new TestClass();
double[] var1=new double[16]{1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0,16.0};
short[] var2 = new short[16] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
typeClass.Var1 = var1;
typeClass.Var2 = var2;
PLC2.plc.WriteClass(typeClass, 1, 44);//往DB1.DBB44开始的字节开始的数组写入值
}
catch (Exception ex)
{
}
writeClassEN = false;
}
读取bool控制
checkShow(chBoxReadBool2, PLC2.readBoolenM("M10.0"));
checkShow(chBoxReadBool3, PLC2.readBoolenDB("DB1.DBX0.0"));
checkShow(chBoxReadBool1, PLC2.readBoolenQ("Q0.0"));
//读取字符串
string str = PLC2.ReadStringGood(DataType.DataBlock, 1, 24, 20);//读取起始地址为DB1.DBB22的字符串,注意:此处起始地址=填字符串首地址+2
textShow(txtBoxReadChars, str);
//读取8位字节整数
string byte3 = PLC2.ReadByte(DataType.DataBlock, 1, 1).ToString();//读取DB1.DBB1
textShow(txtBoxReadB3, byte3);
//读取16位无符号整数
string ushort2 = PLC2.readInt("MW12").ToString();//读取MW12
textShow(txtBoxReadWord2, ushort2);
string ushort3 = PLC2.readInt("DB1.DBW2").ToString();//读取DB1.DBW2
textShow(txtBoxReadWord3, ushort3);
//读取16位有符号整数
string short2 = PLC2.readInt("MW14").ToString();//读取MW14
textShow(txtBoxReadInt2, short2);
string short3 = PLC2.readInt("DB1.DBW4").ToString();//读取DB1.DBW4
textShow(txtBoxReadInt3, short3);
//读取32位双整数
string Dint2 = PLC2.readDInt("MD16").ToString();//读取MD16
textShow(txtBoxReadDInt2, Dint2);
string Dint3 = PLC2.readDInt("DB1.DBD6").ToString();//读取DB1.DBD6
textShow(txtBoxReadDInt3, Dint3);
//读浮点数
string real2 = PLC2.readReal("MD20").ToString();//读取MD20
textShow(txtBoxReadFloat2, real2);
string real3 = PLC2.readReal("DB1.DBD10").ToString();//读取DB1.DBD10
textShow(txtBoxReadFloat3, real3);
//读取结构变量,批量读取控制
TestStruct test = (TestStruct)PLC2.plc.ReadStruct(typeof(TestStruct), 1, 14);
textShow(txtBoxReadStruct1, test.Var1.ToString());
textShow(txtBoxReadStruct2, test.Var2.ToString());
textShow(txtBoxReadStruct3, test.Var3.ToString());
//类批量读取测试
TestClass test1 = new TestClass();
PLC2.plc.ReadClass(test1, 1, 44);
double[] Var1=new double[16];
short[] Var2=new short[16];
Var1 = test1.Var1;
Var2= test1.Var2;
}
}
catch
{
}
}
private void Form1_Load(object sender, EventArgs e)
{
//初始化界面加载延时计时器
DownloadDelayedTimer = new System.Windows.Forms.Timer();
DownloadDelayedTimer.Interval = 2000;
DownloadDelayedTimer.Tick += new EventHandler(DownloadDelayedTimer_Tick);
DownloadDelayedTimer.Enabled = true;
}
private void btnWrtieBool_Click(object sender, EventArgs e)
{
writeBoolEn = true;
}
private void btnWriteChars_Click(object sender, EventArgs e)
{
writeStringEn = true;
}
private void btnWriteB_Click(object sender, EventArgs e)
{
writeByteEn = true;
}
private void btnWriteWord_Click(object sender, EventArgs e)
{
writeUshortEn = true;
}
private void btnWriteInt_Click(object sender, EventArgs e)
{
writeShortEn = true;
}
private void btnWriteDInt_Click(object sender, EventArgs e)
{
writeIntEN = true;
}
private void btnWriteFloat_Click(object sender, EventArgs e)
{
writeRealEN = true;
}
/// <summary>
/// 写结构类型,注意:结构里不能存在string类型,不然会报错,其他类型都可以。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnWriteStruct_Click(object sender, EventArgs e)
{
writeStructEN = true;
}
/// <summary>
/// PLC结构变量定义
/// </summary>
public struct TestStruct
{
public double Var1;
public ushort Var2;
public short Var3;
}
#region label控件Text多线程显示
private void labShow(Label label, string text)
{
try
{
if (label.InvokeRequired)
{
delegateLab opcdelateTimer = new delegateLab(InvokeLab);
this.Invoke(opcdelateTimer, label, text);
}
else
{
label.Text = text;
}
}
catch
{
}
}
private void InvokeLab(Label label, string text)
{
label.Text = text;
}
#endregion
#region text控件Text多线程显示
private void textShow(TextBox textbox, string text)
{
try
{
if (textbox.InvokeRequired)
{
delegateText opcdelateTimer = new delegateText(InvokeLabel);
this.Invoke(opcdelateTimer, textbox, text);
}
else
{
textbox.Text = text;
}
}
catch
{
}
}
private void InvokeLabel(TextBox textbox, string text)
{
textbox.Text = text;
}
#endregion
#region checkBoX控件Checked多线程显示
private void checkShow(CheckBox checkbox, bool bl)
{
try
{
if (checkbox.InvokeRequired)
{
delegateCheck opcdelateTimer = new delegateCheck(Invokecheck);
this.Invoke(opcdelateTimer, checkbox, bl);
}
else
{
checkbox.Checked = bl;
}
}
catch
{
}
}
private void Invokecheck(CheckBox checkbox, bool bl)
{
checkbox.Checked = bl;
}
#endregion
/// <summary>
/// PLC类变量定义
/// </summary>
public class TestClass
{
private double[] var1= new double[16];
public double[] Var1
{
get//读的属性
{
return var1;//返回值
}
set//写的属性
{
var1 = value;//重新赋值
}
}
private short[] var2 = new short[16];
public short[] Var2
{
get//读的属性
{
return var2;//返回值
}
set//写的属性
{
var2 = value;//重新赋值
}
}
}
//类批量写入
private void button1_Click(object sender, EventArgs e)
{
writeClassEN = true;
}
}
}