1,虚拟机...系统Win10...里面安装了VS.
2,本机...系统Win10...里面安装了博图15.
3,转换软件:NetToPLCSIM.
4,本机和虚拟机连接同一个路由器.注意:
5,设置虚拟机为桥接模式,并且选择连接了路由器的网卡.
6,网卡设置自动获取IP地址,并且禁止,启用,让网卡获取IP地址.
正常情况,两台机器能够互相ping 成功!,则基本准备,网络配置完毕.否则,检查防火墙.我没遇到,就没弄.
然后打开博图,必须要进行get/put打勾!
2,GET/PUT 打勾
3,模拟的时候,先点击模拟,但是不要下载PLC.
4,打开Nettoplcsim软件:(其中有 stop server start server 默认即可),注意,一定要先打开这个软件.
5,打开添加对接画面:点击PLCSIM IP.注意,如果先模拟再添加就不会显示.
6,打开PLC模拟器,并下载PLC 点击 PLCSIM IP:这个很关键,必须它自己跳出来的.选择PLC.
7,选择 NET IP ADDR:
8,ok注意 rack和slot选择
9,在虚拟机的VS里面测试通讯
internal static void TestS7()
{
Plc plc = new Plc(CpuType.S71200, "192.168.3.62", 0, 1);
try
{
log("begin open plc");
plc.Open();//一个PLC异步函数,注意,异步函数的异常只能通过
log("plc is open!");
}
catch(Exception e)
{
log(e.Message);
}
}
结果:
10,尝试读取写入byte[]数组:
RecipePLC 数据类型具有:(配方)
一个字符串: string[20] 占用了22个字节.Index0是其大小,应该是22,index1 是实际字符长度.应该是0.现在
一个step数组:step是一个plc数据类型. 其为30个step元素.
每个step含有:
OK,我们先来完成如何读取写入这个结构:
10.1首先在vs中架构一个PLCSTRING类,因为 string这个类不好投射.
public class PlcString:IPlcParse
{
private readonly byte[] bytes;
public PlcString() : this(256) { }
public PlcString(int len )
{
bytes = new byte[len];
bytes[0] = len <= 0xfe ? (byte)len : (byte)0xfe;
}
public void SetString(string str)
{
int len = bytes.Length;
if (str != string.Empty)
{
byte[] str_bytes = ASCIIEncoding.ASCII.GetBytes(str);
bytes[1] = (byte)str_bytes.Length;
str_bytes.CopyTo(bytes, 2);
}
else
{
bytes[1] = 0;
}
}
public string GetString()
{
if (bytes[1] != 0)
{
byte[] strs = new byte[(int)bytes[1]];
Buffer.BlockCopy(bytes, 2, strs, 0, (int)bytes[1]);
return ASCIIEncoding.ASCII.GetString(strs);
}
else
{
return string.Empty;
}
}
public static explicit operator String(PlcString obj)
{
return obj.GetString();
}
public object FromBytes(byte[] bytes, ref double numBytes)
{
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
Buffer.BlockCopy(bytes, (int)numBytes, this.bytes, 0, this.bytes.Length);
numBytes += this.bytes.Length;
return this;
}
public int GetSize()
{
return bytes.Length;
}
public void ToBytes(byte[] bytes, ref double numBytes)
{
numBytes = Math.Ceiling(numBytes);
if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
numBytes++;
Buffer.BlockCopy(this.bytes, 0,bytes, (int)numBytes, this.bytes.Length);
numBytes += this.bytes.Length;
}
public void Display()
{
foreach (var x in bytes)
Console.Write(" {0:X2}", x);
Console.WriteLine();
}
}
这个类实现了如下的接口:
public interface IPlcParse
{
void ToBytes(byte[] bytes, ref double numBytes);
object FromBytes(byte[] bytes, ref double numBytes);
int GetSize();
}
https://gitee.com/mao_qin_bin/s7netplus
算了,太多了,大家到这个地方下载吧. 注意版权.是我的!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
在原有的S7的基础上更改的实现.(git下来之后,我们再开始下一步)
下面我们来实现VS中的step步:
public class Recipe_Step
{
public short element1;
public short element2;
public short element3;
public short element4;
public short element5;
public short element6;
public double element7;
public double element8;
public double element9;
public double element10;
public double element11;
public double element12;
public double element13;
public bool element14;
public bool element15;
public short element16;
}
1,int--投射成short
2,real-投射成double
3,注意大小是64个字节.我们来计算下我们的类的大小.
public static void demo5()
{
PlcClassHelper.DisplayObject(new Recipe_Step());
}
结果:
Recipe_Step : ConsoleApp1.PlcClass.Recipe_Step Size:44
Class of Recipe_Step
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Boolean : False Size:2
Boolean : False Size:2
Int16 : 0 Size:2
OK.
然后再测试下Recipe1:
public class Recipe
{
public static Recipe StaticInstance=new Recipe();
public PlcString Recipe_Name = new PlcString(20, "");
public Recipe_Step[] Recipe_Steps = new Recipe_Step[30];
private Recipe()
{
for(var i = 0; i < Recipe_Steps.Length; i++)
{
Recipe_Steps[i] = new Recipe_Step();
}
}
}
这是PLC数据块(非优化)编译好的
这是我测试的:
Recipe : ConsoleApp1.PlcClass.Recipe Size:1342
Class of Recipe
PlcString : String = Bytes = : 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Size:22
Array of ConsoleApp1.PlcClass.Recipe_Step[] :
Recipe_Step : ConsoleApp1.PlcClass.Recipe_Step Size:44
Class of Recipe_Step
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Int16 : 0 Size:2
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Double : 0 Size:4
Boolean : False Size:2
Boolean : False Size:2
Int16 : 0 Size:2
Recipe_Step : ConsoleApp1.PlcClass.Recipe_Step Size:44
完全正确.下面设定下一些数据并且从PLC的读取:
10.5 设置PLC数据
10.6 从PLC读取数据:
完全一致:
10.7 将数据写入PLC:
public static void demo6()
{
Recipe curRecipe = Recipe.StaticInstance;//引用配方
Recipe.Initial();
short t = 0;
foreach(var step in curRecipe.Recipe_Steps)
{
step.element1 = t++;
step.element16 = t++;
}
Plc plc = new Plc(CpuType.S71200, "192.168.3.62", 0, 1);
try
{
plc.Open();
plc.WriteBytes(DataType.DataBlock, 1, 0, PlcClass.ToBytes(curRecipe));
PlcClassHelper.DisplayObject(curRecipe);
}
catch (PlcException e)
{
Console.WriteLine("Exception'Message is {0},Exception's Errcode is {1}", e.Message, e.ErrorCode.ToString());
}
finally
{
plc.Close();
}
}
上面的Initial是将staticInstance实列给初始化了.
查看结果: PLC
查看结果:VS