最近写的一个程序要和生产线的PLC连动(特定条件下读写指定寄存器),
查询了一些PLC的操作资料,做了一个测试程序:
private void btnRead_Click(object sender, EventArgs e)
{
try
{
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = Dns.GetHostEntry(this.txtIP.Text.Trim()).AddressList[0];
IPEndPoint ipend = new IPEndPoint(ip, int.Parse(this.txtPort.Text.Trim()));
sock.Connect(ipend);
byte[] cmd;
byte[] rec;
cmd = createCommand("R", int.Parse(this.txtStartAddr.Text), 1);
sock.Send(cmd);
Thread.Sleep(1000);
rec = new byte[sock.Available];
sock.Receive(rec);
this.txtRegInfo.Text = this.txtRegInfo.Text + Environment.NewLine + " <读取> " + b2s(rec);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnStop_Click(object sender, EventArgs e)
{
try
{
this.mutexforsocket.WaitOne();
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = Dns.GetHostEntry(this.txtIP.Text.Trim()).AddressList[0];
IPEndPoint ipend = new IPEndPoint(ip, int.Parse(this.txtPort.Text.Trim()));
sock.Connect(ipend);
byte[] cmd;
byte[] rec;
cmd = createCommand("W", int.Parse(this.txtStartAddr.Text), 0x3130);
sock.Send(cmd);
Thread.Sleep(1000);
rec = new byte[sock.Available];
sock.Receive(rec);
this.txtRegInfo.Text = this.txtRegInfo.Text + Environment.NewLine + " <停止> " + b2s(rec);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
this.mutexforsocket.ReleaseMutex();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnStart_Click(object sender, EventArgs e)
{
try
{
this.mutexforsocket.WaitOne();
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = Dns.GetHostEntry(this.txtIP.Text.Trim()).AddressList[0];
IPEndPoint ipend = new IPEndPoint(ip, int.Parse(this.txtPort.Text.Trim()));
sock.Connect(ipend);
byte[] cmd;
byte[] rec;
cmd = createCommand("W", int.Parse(this.txtStartAddr.Text), 0x3030);
sock.Send(cmd);
Thread.Sleep(1000);
rec = new byte[sock.Available];
sock.Receive(rec);
this.txtRegInfo.Text = this.txtRegInfo.Text + Environment.NewLine + " <启动> " + b2s(rec);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
this.mutexforsocket.ReleaseMutex();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnClear_Click(object sender, EventArgs e)
{
try
{
this.mutexforsocket.WaitOne();
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = Dns.GetHostEntry(this.txtIP.Text.Trim()).AddressList[0];
IPEndPoint ipend = new IPEndPoint(ip, int.Parse(this.txtPort.Text.Trim()));
sock.Connect(ipend);
byte[] cmd;
byte[] rec;
cmd = createCommand("W", int.Parse(this.txtStartAddr.Text), 0x0000);
sock.Send(cmd);
Thread.Sleep(1000);
rec = new byte[sock.Available];
sock.Receive(rec);
this.txtRegInfo.Text = this.txtRegInfo.Text + Environment.NewLine + " <还原> " + b2s(rec);
sock.Shutdown(SocketShutdown.Both);
sock.Close();
this.mutexforsocket.ReleaseMutex();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private string b2s(byte[] b)
{
string s = "寄存器[" + this.cbxRegType.Text + "] 地址[" + this.txtStartAddr.Text.Trim() + "]: ";
for (int i = 0; i < b.Length; i++)
{
s = s + b[i].ToString("X").PadLeft(2, '0') + " ";
}
return s;
}
/// 生成Socket命令
/// </summary>
/// <param name="type">R:读,W:写</param>
/// <param name="dreg">寄存器地址</param>
/// <param name="data">数据</param>
/// <returns></returns>
private byte[] createCommand(string type,int dreg,int data)
{
byte[] sendBuf;
switch (type)
{
case "R":
{
sendBuf = new byte[21];
//副标题
sendBuf[0] = 0x50;
sendBuf[1] = 0x00;
//网络号
sendBuf[2] = 0x00;
//PLC号
sendBuf[3] = 0xFF;
//IO
sendBuf[4] = 0xFF;
sendBuf[5] = 0x03;
//站号
sendBuf[6] = 0x00;
//字节数
sendBuf[7] = 0x0c;
sendBuf[8] = 0x00;
//等待长度
sendBuf[9] = 0x0A;
sendBuf[10] = 0x00;
//命令
sendBuf[11] = 0x01;
sendBuf[12] = 0x04;
//子命令
sendBuf[13] = 0x00;
sendBuf[14] = 0x00;
//起始寄存器地址
sendBuf[15] = (byte)(dreg & 0xff);
sendBuf[16] = (byte)((dreg & 0xff00) >> 8);
sendBuf[17] = (byte)((dreg & 0xff0000) >> 16);
if(this.cbxRegType.Text.Equals("R"))
{
//寄存器类型-R类
sendBuf[18] = 0xAF;
}
if (this.cbxRegType.Text.Equals("D"))
{
//寄存器类型-D类
sendBuf[18] = 0xA8;
}
//寄存器连续长度
sendBuf[19] = (byte)(data & 0xff);
sendBuf[20] = (byte)((data & 0xff00) >> 8);
return sendBuf;
}
case "W":
{
sendBuf = new byte[23];
//副标题
sendBuf[0] = 0x50;
sendBuf[1] = 0x00;
//网络号
sendBuf[2] = 0x00;
//PLC号
sendBuf[3] = 0xFF;
//IO
sendBuf[4] = 0xFF;
sendBuf[5] = 0x03;
//站号
sendBuf[6] = 0x00;
//字节数
sendBuf[7] = 0x0E;
sendBuf[8] = 0x00;
//等待长度
sendBuf[9] = 0x0A;
sendBuf[10] = 0x00;
//命令
sendBuf[11] = 0x01;
sendBuf[12] = 0x14;
//子命令
sendBuf[13] = 0x00;
sendBuf[14] = 0x00;
//起始寄存器地址
sendBuf[15] = (byte)(dreg & 0xff);
sendBuf[16] = (byte)((dreg & 0xff00) >> 8);
sendBuf[17] = (byte)((dreg & 0xff0000) >> 16);
if (this.cbxRegType.Text.Equals("R"))
{
//寄存器类型-R类
sendBuf[18] = 0xAF;
}
if (this.cbxRegType.Text.Equals("D"))
{
//寄存器类型-D类
sendBuf[18] = 0xA8;
}
//寄存器连续长度
sendBuf[19] = 0x01;
sendBuf[20] = 0x00;
sendBuf[21] = (byte)(data & 0xff);
sendBuf[22] = (byte)((data & 0xff00) >> 8);
return sendBuf;
}
default: return null ;
}
}