目录
[1. Read](#1. Read)
[2. Write](#2. Write)
[二.C# Code](# Code)
此篇是C#与三菱PLC FX5U使用Socket进行通信
相当于使用Socket建立通信发送报文给PLC读取和写入PLC program中的内容
一.报文格式
head = 500000FF03FF00
1. Read
假设我想读取M4001寄存器中的内容
message = head+ dataLength + writeCmd + digit
readCmd = monitorTime + 04010000 + M* + startAddress + digit
monitorTime(4位): 0010 // 2*250ms(替换成十进制的2)
M*:是M寄存器的意思(如果其他寄存器,则是D*)
startAdd(6位): 001000 //M1000,如果是M100,则是000100
digit(4位) : 0001 //读取一位的意思
readCmd = 0010 04010000 M* 001000 0001
dataLength :writeCmd的十六进制长度
message = 500000FF03FF00 0018 0010 04010000 M* 004001 0001
2. Write
writeCmd = monitorTime + 14010000 + M* + startAddress + digit + m
上述部分与上面一样
m: 0000 close
0001 open
writeCmd = 0010 14010000 M* 004001 0001 0001
dataLength :writeCmd+m的十六进制长度
message = 500000FF03FF00 0018 0010 14010000 M* 004001 0001 0001 //打开M4001寄存器
二.C# Code
lift.cs
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SF_lift
{
public class Lift
{
public Socket client;
public IPEndPoint serverEndPoint;
public string head = "500000FF03FF00";
public string MonitorTime = "0010"; //监视器时间2*250ms=0.5s
public string wCmd;
public string rCmd;
public string totalWrite;
public string totalRead;
public string writeMessage;
public string readMessage;
public byte[] msg_bytes;
public byte[] msg_bytes1;
public byte[] response;
public int bytesRead;
public Lift(string IP, int port)
{
this.client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
this.serverEndPoint = new IPEndPoint(IPAddress.Parse(IP), port);
this.client.Connect(this.serverEndPoint);
Console.WriteLine("已连接到lift服务器");
}
//写入x寄存器x100一位
//x:register编号 x=D*, x=M* 比如M寄存器,D寄存器
//startAdd格式(6位):000100, digit格式(4位):0001
//m(输入状态4位) 0001:on 0000:off
public void write(string x,string startAdd,string digit,string m)
{
this.wCmd = this.MonitorTime+"14010000"+ x + startAdd + digit;
this.writeMessage = this.head + (this.wCmd+m).Length.ToString("X4") +this.wCmd+ m;
this.msg_bytes = Encoding.ASCII.GetBytes(this.writeMessage);
this.client.Send(msg_bytes);
// 接收响应
byte[] buffer = new byte[1024];
// 缓冲区大小可根据协议调整
int bytesRead = this.client.Receive(buffer);
// 转成字符串并打印
string response = Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine("响应内容: " + response);
}
//x:register编号 x=D*, x=M* 比如M寄存器,D寄存器
//startAdd:000100, digit = 0001
//读取x寄存器x100一位
public void read(string x,string startAdd, string digit)
{
this.rCmd = this.MonitorTime + "04010000" + x + startAdd + digit;
this.readMessage = this.head + this.rCmd.Length.ToString("X4") + this.rCmd;
this.msg_bytes1 = Encoding.ASCII.GetBytes(this.readMessage);
this.client.Send(msg_bytes1);
this.response = new byte[1024];
this.bytesRead = this.client.Receive(this.response);
string respStr = Encoding.ASCII.GetString(this.response, 0, this.bytesRead);
Console.WriteLine("响应字符串:" + respStr);
// 解析最后的数据部分
// 响应格式: D000...0008 0000 [数据]
// 最后4位就是数据值
if (respStr.Length >= 4)
{
string dataValue = respStr.Substring(respStr.Length - 4);
// 取最后4位
string status = dataValue == "0001" ? "enable" :
dataValue == "0000" ? "disable" : "未知";
Console.WriteLine($"寄存器 {x}{startAdd} = {dataValue} ({status})");
}
}
}
}
program.cs
cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SF_lift
{
internal class Program
{
static void Main(string[] args)
{
Lift lift1 = new Lift("10.0.1.130", 5000);
lift1.read("M*", "004001", "0001");
Lift lift = new Lift("10.0.1.130", 5001);
lift.write("M*", "004100", "0001", "0000");
}
}
}