標題:
三菱PLC與上位機的Modbus通訊 附C#源代碼
[打印本頁]
作者:
leepingan
時間:
2019-7-25 15:31
標題:
三菱PLC與上位機的Modbus通訊 附C#源代碼
0.png
(3.36 KB, 下載次數(shù): 156)
下載附件
2019-7-25 18:15 上傳
單片機源程序如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows;
using System.Threading;
namespace FX3GModbusAPI
{
public class FX3GModbusAPI
{
public struct Type
{
//FX3G
public static string Y = "3300"; //Y元件的定義
public static string X = "3400"; //X元件的定義
public static string S = "2000"; //S元件的定義
public static string M = "0000"; //M元件的定義
public static string TS = "3000"; //TS位元件的定義
public static string MR = "1E00"; //M8000~M8511字元件的定義
public static string CS = "3200"; //CS位元件的定義
public static string D = "0000"; //D0~D7999
public static string WD = "1F40"; //D8000~D8511
}
public enum SoftElemType
{
//FX3G
Y,
X,
S,
M,
TS,
MR,
CS,
D,
WD,
}
public struct FunctionName
{
public static string Read_線圈 = "01";//可多點
public static string Read_輸入 = "02";//可多點
public static string Read_保持寄存器 = "03";//可多點
public static string Read_輸入寄存器 = "04";//可多點
public static string Write_線圈寫入 = "05";//僅一點
public static string Write_寄存器寫入 = "06";//僅一點
public static string Write_批量線圈寫入 = "0F";//多點線圈寫入
public static string Write_批量寄存器寫入 = "10";//多點保持寄存器寫入
}
public SerialPort port;
// private StringBuilder myCompleteMessage = new StringBuilder();//避免在事件處理方法中反復的創(chuàng)建,定義到外面。
public string STATE;
public string myCompleteMessage;
public int FX3G_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
{
try
{
Addr = "";
senddata = "";
value = "";
//num = 0;
switch (eType)
{
case (SoftElemType.Y):
for (int i = 0; i < pValue.Length; i++)
value += string.Format("{0:x2}", pValue[i]);
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.Y.ToString(), 16), 16);
if (nCount == 1)
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_線圈寫入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));
else senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量線圈寫入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString((nCount - 1) / 8 + 1, 16).PadLeft(4, '0'), value);
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x05 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x0F) return -1;
break;
case (SoftElemType.M):
for (int i = 0; i < pValue.Length; i++)
value += string.Format("{0:x2}", pValue[i]);
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
int len = nCount / 8;
if (nCount % 8 != 0)
{
len += 1;
}
if (nCount == 1) senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_線圈寫入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));
else senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量線圈寫入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(len, 16).PadLeft(2, '0'), value);
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x05 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x0F) return -1;
break;
case (SoftElemType.D):
for (int i = 0; i < pValue.Length; i++)
value += string.Format("{0:x2}", pValue[i]);
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
if (nCount == 1) senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_寄存器寫入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));
else senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量寄存器寫入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(2 * nCount, 16).PadLeft(2, '0'), value);
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
break;
case (SoftElemType.WD):
for (int i = 0; i < pValue.Length; i++)
value += string.Format("{0:x2}", pValue[i]);
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量寄存器寫入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(2 * nCount, 16).PadLeft(2, '0'), value);
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
break;
default:
return -1;
}
}
catch
{
return -1;
}
return 1;
}
string Addr = "";
string senddata = "";
string value = "";
// int num = 0;
object locker1 = new object();
public int FX3G_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
{
Addr = "";
senddata = "";
value = "";
// num = 0;
try
{
switch (eType)
{
case (SoftElemType.Y):
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.Y.ToString(), 16), 16).PadLeft(4, '0');
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_線圈, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
int leny = nCount / 8;
if (nCount % 8 != 0)
{
leny += 1;
}
StringBuilder resulty = new StringBuilder(leny * 8);
byte[] bvaluey = new byte[leny];
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x01) return -1;
for (int i = 0; i < leny; i++)
{
bvaluey[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);
}
foreach (byte b in bvaluey)
{
resulty.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
}
for (int i = 0; i < leny * 8; i++)
{
int len1 = (i + 1) / 8;
if ((i + 1) % 8 != 0)
{
len1 += 1;
}
pValue[i] = Convert.ToByte(resulty[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);
}
break;
case (SoftElemType.X):
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.X.ToString(), 16), 16).PadLeft(4, '0'); ;
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_輸入, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
int lenx = nCount / 8;
if (nCount % 8 != 0)
{
lenx += 1;
}
StringBuilder resultx = new StringBuilder(lenx * 8);
byte[] bvaluex = new byte[lenx];
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x02) return -1;
for (int i = 0; i < lenx; i++)
{
bvaluex[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);
}
foreach (byte b in bvaluex)
{
resultx.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
}
for (int i = 0; i < lenx * 8; i++)
{
int len1 = (i + 1) / 8;
if ((i + 1) % 8 != 0)
{
len1 += 1;
}
pValue[i] = Convert.ToByte(resultx[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);
}
break;
case (SoftElemType.M):
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16).PadLeft(4, '0'); ;
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_線圈, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
Write_port(senddata);
//if (myCompleteMessage.Length < 8) return -1;
myCompleteMessage = myCompleteMessage.Replace(" ", "");
int len = nCount / 8;
if (nCount % 8 != 0)
{
len += 1;
}
StringBuilder result = new StringBuilder(len * 8);
byte[] bvalue = new byte[len];
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x01) return -1;
for (int i = 0; i < len; i++)
{
bvalue[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);
}
foreach (byte b in bvalue)
{
result.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
}
for (int i = 0; i < len * 8; i++)
{
int len1 = (i + 1) / 8;
if ((i + 1) % 8 != 0)
{
len1 += 1;
}
pValue[i] = Convert.ToByte(result[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);
}
break;
case (SoftElemType.D):
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_輸入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04) return -1;
for (int i = 0; i < 2 * nCount; i = i + 2)
{
pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(8 + 2 * i, 2), 16);//低8位
}
break;
case (SoftElemType.WD):
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_輸入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04) return -1;
for (int i = 0; i < 2 * nCount; i = i + 4)
{
pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 2, 2), 16);//低8位
pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
pValue[i + 2] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 6, 2), 16);//低8位
pValue[i + 3] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 4, 2), 16);//高8位
}
break;
default:
return -1;
}
return 1;
}
catch
{
return -1;
}
}
object locker = new object();
public void Write_port(string Date)
{
Date = Date.Insert(0, STATE);
List<string> sendData16 = new List<string>();
byte[] sendBuffer = null;
for (int i = 0; i < Date.Length; i += 2)
{
sendData16.Add(Date.Substring(i, 2));
}
sendBuffer = new byte[sendData16.Count];
for (int i = 0; i < sendData16.Count; i++)
{
sendBuffer[i] = (byte)(Convert.ToInt32(sendData16[i], 16));
}
byte[] star = bcrc16(sendBuffer);
StringBuilder recBuffer16 = new StringBuilder();
List<byte> tmp = new List<byte>(sendBuffer.Length + star.Length);
tmp.AddRange(sendBuffer);
tmp.AddRange(star);
byte[] merged = tmp.ToArray();
port.Write(merged, 0, merged.Length);
//DateTime TF_timeh, TS_timeh;
//TF_timeh = DateTime.Now;
//bool cc = true;
//while (cc)
//{
// TS_timeh = DateTime.Now;
// double TDelta_t = (TS_timeh - TF_timeh).TotalMilliseconds;
// if (TDelta_t > 1000) cc = false;
//}
System.Threading.Thread.Sleep(200);
}
public static byte[] bcrc16(byte[] data)
{
if (data.Length == 0)
throw new Exception("調(diào)用CRC16校驗算法,(低字節(jié)在前,高字節(jié)在后)時發(fā)生異常,異常信息:被校驗的數(shù)組長度為0。");
byte[] temdata = new byte[data.Length + 2];
int xda, xdapoly;
byte i, j, xdabit;
xda = 0xFFFF;
xdapoly = 0xA001;
for (i = 0; i < data.Length; i++)
{
xda ^= data[i];
for (j = 0; j < 8; j++)
{
xdabit = (byte)(xda & 0x01);
xda >>= 1;
if (xdabit == 1)
xda ^= xdapoly;
}
}
temdata = new byte[2] { (byte)(xda & 0xFF), (byte)(xda >> 8) };
return temdata;
}//crc校驗
public void serialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
lock(locker)
{
try
{
System.Threading.Thread.Sleep(50);
int n = port.BytesToRead;//先記錄下來,避免某種原因,人為的原因,操作幾次之間時間長,緩存不一致
if (n < 2)
return;
// myCompleteMessage = ""; //清除字符串構(gòu)造器的內(nèi)容
////因為要訪問ui資源,所以需要使用invoke方式同步ui。
byte[] myReadBuffer = new byte[n];
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
numberOfBytesRead = port.Read(myReadBuffer, 0, myReadBuffer.Length);//讀取緩沖數(shù)據(jù)
string[] recData = new string[myReadBuffer.Length];
StringBuilder recBuffer16 = new StringBuilder();
for (int i = 0; i < myReadBuffer.Length; i++)
{
recBuffer16.AppendFormat("{0:X2}" + " ", myReadBuffer[i]);
recData[i] = myReadBuffer[i].ToString("X2");
}
myCompleteMessage = recBuffer16.ToString();
// myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
}
catch
{
return ;
}
}
}
public int FX3G_Read_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
{
try
{
if (eType != SoftElemType.WD)
return -1;
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_輸入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
Write_port(senddata);
lock (locker)
{
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04)
return -1;
for (int i = 0; i < 2 * nCount; i = i + 4)
{
pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 2, 2), 16);//低8位
pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
pValue[i + 2] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 6, 2), 16);//低8位
pValue[i + 3] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 4, 2), 16);//高8位
}
return 1;
}
}
catch
{
return -1;
}
}
public int FX3G_Write_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
{
try
{
if (eType != SoftElemType.WD)
return -1;
for (int i = 0; i < pValue.Length; i++)
value += string.Format("{0:x2}", pValue[i]);
Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量寄存器寫入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(2 * nCount, 16).PadLeft(2, '0'), value);
Write_port(senddata);
myCompleteMessage = myCompleteMessage.Replace(" ", "");
if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
return 1;
}
catch
{
return -1;
}
}
}
}
復制代碼
所有資料51hei提供下載:
FX3GModbusAPI.rar
(27.5 KB, 下載次數(shù): 237)
2019-7-25 15:33 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
作者:
板阿爾高
時間:
2019-7-31 19:25
實在是太有幫助了 ,贊贊贊!
作者:
yywd4
時間:
2020-2-19 09:41
還沒試驗,不夠要感謝發(fā)帖。
作者:
jysliang
時間:
2020-6-8 17:44
源碼能打開,不知道為什么在VS里面打不開
作者:
chaofuzi86
時間:
2020-6-18 22:49
完全看不懂
作者:
fadeded
時間:
2020-7-20 10:17
好帖子,就是為啥代碼有幾個報錯呢
作者:
xinyuan4002
時間:
2021-6-19 18:04
實在是太有幫助了 ,贊贊贊!
作者:
uhfgiu
時間:
2021-7-2 20:56
實在是太有幫助了 ,贊贊贊
作者:
Coders
時間:
2021-7-13 01:32
正在學plc,謝謝
作者:
gaofahao
時間:
2021-11-20 11:17
完全看不懂
作者:
cmyldd
時間:
2023-8-13 20:13
實在是太有幫助了,謝謝樓主!
作者:
jiandan98
時間:
2023-10-3 08:28
實在是太有幫助了 ,贊贊贊!
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1