目录
一、介绍
主要用于三菱PLC(Q系列/FX5U系列和FX3U系列)测试通讯:测试连接、读取数据、写入数据。
下图中的通讯类型:MC1E(三菱FX3U系列通讯);MC3E(三菱Q系列/FX5U系列通讯)。
二、代码
MC1E通讯代码:
public class PLC_MC_1E
{
Socket socketSend;
Thread th;
string fbt = "01";//"00";未读//"01"批量读
string plchao = "FF";
string time = "0A00";//L_H
string start = "";
string A_dress = "";
string count = "";
string r_or_w = "";
// bool IsAuto = false;
//// string head = "500000FF03FF00";//报文头,二进制则改"500000FFFF0300"
// string head = "500000FFFF0300";//二进制的
// string length = "";
// string time = "1000";//"0010";
// string function_code = "";
// string different_code = "";
// string data = "";
public bool Connect(string ServerIP, int ServerProt)//首先使用时需要判断是否已经进行plc的连接
{
socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPAddress ip = IPAddress.Parse(ServerIP);
IPEndPoint point = new IPEndPoint(ip, ServerProt);
try
{
//创建负责通信的Socket
//获得要连接的远程服务器应用程序的IP和端口号
socketSend.Connect(point);
//修改一下這個寫法----------------------
////开启一个新的线程接受服务器接受的数据
//th = new Thread(Recive);//线程
//th.IsBackground = true;
//th.Start();
//-----------------------------------
return true;
}
catch //(Exception ex)
{
//MessageBox.Show(ex.Message);//沒有連起時會跳東西出來
return false;
}
}
bool Recive(ref short[] ad)
{
bool TX;
DateTime dt1 = DateTime.Now;
while (true)
{
byte[] buffer = new byte[1024 * 1024 * 2];
//客户端连接成功后,服务器接受客户端发来的信息
int r = socketSend.Receive(buffer);
r += 0;
if (r >= 2)
{
if (buffer[1] == 0)
{
TX = true;
if (r > 2)
{
string S = "";
// ad = new short[(r - 2) / 2];
for (int i = 0; i < ad.Length; i++)
{
string SS = buffer[2 * i + 3].ToString("x2").ToUpper();
string FDDS = buffer[2 * i + 2].ToString("x2").ToUpper();
ad[i] = Convert.ToInt16(buffer[2 * i + 3].ToString("x2").ToUpper() + buffer[2 * i + 2].ToString("x2").ToUpper(), 16);
}
break;
}
}
}
else
{
TX = false;
}
//ShowMsg(socketSend.RemoteEndPoint + ":" + str);
//if (r == 0)
//{
// TX = false; break;
//}
TimeSpan hh = (DateTime.Now).Subtract(dt1);
if (hh.TotalMilliseconds > 5000)
{
TX = false; break;
}
}
return TX;
}
public bool readData(PLC_MC_1E.plc_address address, int SzDecive, ref short[] readxx)//读取数据(数据地址以及读取的长度,返回读取的数据)
{
fbt = "01";
start = SzDecive.ToString("X8");
start = start.Substring(6, 2) + start.Substring(4, 2) + start.Substring(2, 2) + start.Substring(0, 2);
A_dress = ((int)address).ToString("X4");
A_dress = A_dress.Substring(2, 2) + A_dress.Substring(0, 2);
count = readxx.Length.ToString("X2");
r_or_w = "00";
string str = string.Format("{0}{1}{2}{3}{4}{5}{6}", fbt, plchao, time, start, A_dress, count, r_or_w);
byte[] OML = new byte[str.Length / 2];
for (int I = 0; I < OML.Length; I++)
{
OML[I] = Convert.ToByte(str.Substring(2 * I, 2), 16);
}
short[] ad = new short[readxx.Length];
try
{
socketSend.Send(OML);//將數據發送出去之後
//return GET_BYTE;//数据已发送,读出的数据在哪里等会儿返回
// Thread.Sleep(500);
Thread.Sleep(50);
return Recive(ref readxx);
}
catch (Exception EX)
{
return false;
}
//readxx = ad.ToArray();
//return ;
}
public bool writeData(PLC_MC_1E.plc_address adress, int SzDecive, short[] write1)//写入部分数据(地址,长度,写入数据)不返还数据
{
bool TX = false;
if (socketSend.Connected)
{
byte[] bu_write = new byte[write1.Length * 2];
for (int i = 0; i < write1.Length; i++)
{
bu_write[i * 2] = Convert.ToByte(write1[i].ToString("X4").Substring(2, 2), 16);
bu_write[2 * i + 1] = Convert.ToByte(write1[i].ToString("X4").Substring(0, 2), 16);
}
fbt = "03";
start = SzDecive.ToString("X8");
start = start.Substring(6, 2) + start.Substring(4, 2) + start.Substring(2, 2) + start.Substring(0, 2);
A_dress = ((int)adress).ToString("X4");
A_dress = A_dress.Substring(2, 2) + A_dress.Substring(0, 2);
count = write1.Length.ToString("X2");
r_or_w = "00";
string str = "";
str = string.Format("{0}{1}{2}{3}{4}{5}{6}", fbt, plchao, time, start, A_dress, count, r_or_w);
byte[] buffer = new byte[str.Length / 2 + write1.Length * 2];// NEWSystem.Text.Encoding.ASCII.GetBytes(str);
for (int i = 0; i < str.Length / 2 + write1.Length * 2; i++)
{
if (i < str.Length / 2)
{
buffer[i] = (byte)Convert.ToByte(str.Substring(i * 2, 2), 16);
}
else
{
buffer[i] = Convert.ToByte(write1[(i - str.Length / 2) / 2].ToString("X4").Substring(2, 2), 16);
i++;
buffer[i] = Convert.ToByte(write1[(i - 1 - str.Length / 2) / 2].ToString("X4").Substring(0, 2), 16);
}
}
string[] ASD = new string[buffer.Length];
for (int I = 0; I < ASD.Length; I++)
{
ASD[I] = buffer[I].ToString("X2");
}
socketSend.Send(buffer);
TX = true;
System.Threading.Thread.Sleep(50);
}
return TX;
// return true;
}
public void Connect_Close()//关闭端口
{
if (socketSend != null)
{
if (socketSend.Connected)
{
socketSend.Close();
}
}
//if (th != null)
//{
// if (th.IsAlive)
// {
// th.Abort();
// }
//}
}
//private bool TX { get; set; }
//public short[] ad { get; set; }
public enum plc_address
{
D = 17440,
M = 19744,
R = 21024,
SM = 145,
}
}
MC3E通讯代码参考:
1.代码参考:
代码三菱PLC网络MC3E通信—读取或写入——字符串或数字_susan花雨的博客-优快云博客
2.dll方式:三菱PLC的dll文件-其它文档类资源-优快云下载
dll用法:引用到程式
代码:
public class PLC_MC
{
CsPlcMC PLC = new CsPlcMC();//MC3E 三菱Q系列PLC通讯
//adressNo M、L、X、Y、D、R
public bool WriteData3E(string IP, int Port, int value, CsPlcMC.eAddress adressNo,int adress)
{
int writedata = value;
if (PLC.Connect(IP, Convert.ToInt16(Port.ToString().Trim())))
{
short[] READ = new short[1];
READ[0] = Convert.ToInt16(writedata.ToString().Trim());
if (PLC.WriteBlocks(adressNo, adress, READ))
{
PLC.Disconnect();
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
public int ReadData3E(string IP, int Port, CsPlcMC.eAddress adressNo,int Address)
{
int readdata = 0;
if (PLC.Connect(IP, Convert.ToInt16(Port.ToString().Trim())))
{
short[] READ = new short[1];
if (PLC.ReadBlocks(adressNo, Address, ref READ))//地址
{
readdata = READ[0];
PLC.Disconnect();
}
}
return readdata;
}
}
三、其他
程式应用了皮肤文件IrisSkin4.dll
总结:本片文章主要记录三菱PLC通讯(Q系列/FX5U和FX3U系列),目前只能写入和读取数据,不能读取和写入字符串,待后续更新。