最近学习了ModbusRTU协议,自己就用C#编写了一个ModbusRTU类库,用来和MCGS触摸屏做通讯,因本人新手一个,编出来的类库可能还有漏洞,修望大家多包涵。
这是我编写的类库下载地址MCGSModbusRTU类库
也可以看我下面的代码自己编写。
一、基础设置
1、MCGS设置
因为是与MCGS通讯,首先要设置MCGS的参数。我用的屏型号TPC7032Kt ,屏的编程软件是McgsPro组态软件。这款屏的通讯端口为3个,一个232,两个485.
要添加一个父类设备和和一个数据转发设备
设置父设备的参数,我用的端口号为COM2,波特率9600,数据位8,停止位1,数据校验为 无校验。
数据转发设置,设备地址为1,数据组码顺序数据按默认,字符串选择Unicode,支持中文编码,这个影响你后面对数据进行解析,我的类库也是按照这个顺序进行解析的,感兴趣的可以自己改变,然后自己进行解析。
触摸屏的参数就设置好了,剩下的就是关联变量。需要说明MCGS的地址是从1开始的,而我们用电脑读写是从0开始的。
2、创建引用类库
现在可以开始编类库了,因为我们这个类库是要在Windows窗体中来使用,所以我创建的这个类库为 .NET Framework 类库。
为了调试需要,还要创建Windows窗体,然后在窗体中添加引用,因为我是在同一个解决方案下,可以直接添加引用。类库生成的是.dll文件。
直接添加.dll文件
二、编写类库
1、编写类库接口
以后有可能对这个类库进行扩展,能够走TCP协议,就声明了一个接口,这个不是必须的,
namespace MCGSModbus
{
/// <summary>
/// MCGS通讯接口类
/// </summary>
interface IMCGSData
{
#region 读取数据
/// <summary>
/// 读取bool数据结果
/// </summary>
/// <param name="slaveld">读取从站的地址</param>
/// <param name="functionCode">读取的功能码 值为 01 02 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址 读取的地址从0开始</param>
/// <param name="count">读取的数据长度</param>
/// <returns>读取到的值 返回null则读取失败</returns>
bool[] ReadBool(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取浮点数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
float[] ReadFloat(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取32位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
int[] ReadInt(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取32位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
uint[] ReadUint(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取16位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
short[] ReadShore(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取16位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
ushort[] ReadUshore(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取字符串 格式是ASCII 不能表示中文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取字符的个数 </param>
/// <returns>读取到的值 返回null则读取失败</returns>
string ReadStringASCII(byte slaveld, byte functionCode, ushort startAddress, ushort count);
/// <summary>
/// 读取字符串 格式是Unicode 可以表示中文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取字符的个数 </param>
/// <returns>读取到的值 返回null则读取失败</returns>
string ReadStringUnicode(byte slaveld, byte functionCode, ushort startAddress, ushort count);
#endregion
#region 写入数据
/// <summary>
/// 写入16位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write16(byte slaveld, ushort startAddress, ushort value);
/// <summary>
/// 写入16位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write16(byte slaveld, ushort startAddress, short value);
/// <summary>
/// 写入多个16位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write16(byte slaveld, ushort startAddress, ushort count, short[] value);
/// <summary>
/// 写入多个16位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write16(byte slaveld, ushort startAddress, ushort count, ushort[] value);
/// <summary>
/// 写入32位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write32(byte slaveld, ushort startAddress, int value);
/// <summary>
/// 写入32位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write32(byte slaveld, ushort startAddress, uint value);
/// <summary>
/// 写入多个32位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write32(byte slaveld, ushort startAddress, ushort count, uint[] value);
/// <summary>
/// 写入多个32位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write32(byte slaveld, ushort startAddress, ushort count, int[] value);
/// <summary>
/// 写入32位浮点数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据 </param>
/// <returns>写入的结果 成功返回true</returns>
bool Write32(byte slaveld, ushort startAddress, float value);
/// <summary>
/// 写入多个32位浮点数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
bool Write32(byte slaveld, ushort startAddress, ushort count, float[] value);
/// <summary>
/// 写入字符串
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据 </param>
/// <returns>写入的结果 成功返回true</returns>
bool WriteString(byte slaveld, ushort startAddress, string value);
/// <summary>
/// 写入单个布尔值
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 功能码为05 06 </param>
/// <param name="startAddress">写入偏移地址</param>
/// <param name="value">写入数据</param>
/// <returns>写入是否成功 成功返回true</returns>
bool WriteBool(byte slaveld, byte functionCode, ushort startAddress, ushort value);
#endregion
}
}
接下来写ModbusRTU类库。
首先让这个类库继承接口,在类中实现接口。
2、编写链接、断开方法
建立串口实例,建立链接
/// <summary>
/// 打开串口
/// </summary>
/// <param name="portName">端口号</param>
/// <param name="baudRate">波特率</param>
/// <param name="paritys">校验位 值为 无 奇 偶 </param>
/// <param name="dataBist">数据位 值为 8或7 </param>
/// <param name="stopBits">停止位 值为 0 1 2</param>
public void OpenCOM(string portName, int baudRate, string paritys, int dataBist,int stopBits)
{
//声明校验类型并赋值默认值
Parity parity = Parity.None;
//根基传入的参数来赋值
switch (paritys)
{
case "无":
parity = Parity.None;
break;
case "偶":
parity = Parity.Even;
break;
case "奇":
parity = Parity.Odd;
break;
default:
break;
}
//创建串口实例
CurrentCOM = new SerialPort();
//设置端口号
CurrentCOM.PortName = portName;
//设置波特率
CurrentCOM.BaudRate = baudRate;
//设置奇偶校验
CurrentCOM.Parity = parity;
//设置数据位
CurrentCOM.DataBits = dataBist;
//设置停止位
CurrentCOM.StopBits = (StopBits)stopBits;
//判断端口是否打开,打开就关掉
if (CurrentCOM.IsOpen)
{
CurrentCOM.Close();
}
//打开串口
CurrentCOM.Open();
}
关闭串口
/// <summary>
/// 关闭串口
/// </summary>
public void CloseCOM()
{
//关闭串口
if (CurrentCOM.IsOpen)
{
CurrentCOM.Close();
}
}
3、编写数据处理方法
把二进制字符数组转换成布尔值
/// <summary>
/// 把二进制字符串数组转成布尔数组
/// </summary>
/// <param name="str">要转换的字符数组</param>
/// <returns>转换后的布尔数组,失败返回 null</returns>
private bool[] CharacterToBoolean(char[] str)
{
bool[] b = new bool[str.Length];
for (int i = 0; i < str.Length; i++)
{
if (str[i] == '1' || str[i] == '0')
{
//判断字符是否等1
b[i] = (str[i] == '1' ? true : false);
}
else return null;
}
return b;
}
16位数据高低位交换
/// <summary>
/// 16位数据高低位置转换
/// </summary>
/// <param name="by">要转换的数据</param>
private void ReverseBytes16(byte[] by)
{
List<byte> SendCommand = new List<byte>();
byte[] byt = new byte[2];
for (int i = 0; i < by.Length; i += 2)
{
byt[0] = by[i];
byt[1] = by[i + 1];
Array.Reverse(byt);
SendCommand.AddRange(byt);
}
Array.Copy(SendCommand.ToArray(), by, SendCommand.Count);
}
32位数据进行高低位交换
/// <summary>
/// 32位数据高低位置转换
/// </summary>
/// <param name="by">要转换的数据</param>
private void ReverseBytes32(byte[] by)
{
List<byte> SendCommand = new List<byte>();
byte[] byt = new byte[4];
for (int i = 0; i < by.Length; i +=4)
{
byt[0] = by[i];
byt[1] = by[i + 1];
byt[2] = by[i+2];
byt[3] = by[i + 3];
Array.Reverse(byt);
SendCommand.AddRange(byt);
}
Array.Copy(SendCommand.ToArray(), by, SendCommand.Count);
}
字节数组转换成数据,使用C#内部方法
//数据转换成二进制字符串 result数据
char[] intermediate = Convert.ToString(result, 2).ToArray();
//转换成32位浮点数 result字节数组
float intermediate = BitConverter.ToSingle(result, 4);
//转换成32位整数 result字节数组
int intermediate = BitConverter.ToInt32(result, 4);
//转换成32位无符号整数 result字节数组
uint intermediate = BitConverter.ToUInt32(result, 4);
//转换成16位整数 result字节数组
short intermediate = BitConverter.ToInt16(result, 2);
//转换成16位无符号整数 result字节数组
ushort intermediate = BitConverter.ToUInt16(result, 2);
//字节数组转换成字符串 result字节数组
string intermediate = Encoding.ASCII.GetString(result, 0, result.Length);
//字节数组转换成字符串 result字节数组
string intermediate = Encoding.Unicode.GetString(result, 0, result.Length);
4、CRC16校验
这是从网上找的校验方法
#region CRC16校验
private static readonly byte[] aucCRCHi = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40
};
private static readonly byte[] aucCRCLo = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
0x41, 0x81, 0x80, 0x40
};
/// <summary>
/// CRC校验
/// </summary>
/// <param name="pucFrame">要校验的字节数组</param>
/// <param name="uslen">要校验的字节个数</param>
/// <returns>CRC校验码</returns>
private byte[] Crc16(byte[] pucFrame, int uslen)
{
int i = 0;
byte[] res = new byte[2] { 0xff, 0xff };
ushort iIndex;
while (uslen-- > 0)
{
iIndex = (ushort)(res[0] ^ pucFrame[i++]);
res[0] = (byte)(res[1] ^ aucCRCHi[iIndex]);
res[1] = aucCRCLo[iIndex];
}
return res;
}
/// <summary>
/// 判断CRC校验是否正确
/// </summary>
/// <param name="value">要校验的数据</param>
/// <returns>判断的结果</returns>
private bool CheckCRC(byte[] value)
{
if (value == null) return false;
if (value.Length <= 2) return false;
int length = value.Length;
byte[] buf = new byte[length - 2];
Array.Copy(value, 0, buf, 0, buf.Length);
byte[] CRCbuf = Crc16(buf, buf.Length);
if (CRCbuf[0] == value[length - 2] && CRCbuf[1] == value[length - 1])
{
return true;
}
return false;
}
#endregion
5、编写读取拼接方法
/// <summary>
/// 发送查询数据命令
/// </summary>
/// <param name="slaveld">读取的地址</param>
/// <param name="functionCode">读取的功能码</param>
/// <param name="startAddress">读取的起始地址</param>
/// <param name="count">读取的数据长度</param>
/// <returns>查询的返回数据 null为查询失败</returns>
private byte[] ReadData(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (CurrentCOM != null)
{
//组织读取报文
byte[] SendCommand = GetDatachangeMsgByteRead(slaveld, functionCode, startAddress, count);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
//验证CRC校验
if (CheckCRC(buffer))
{
return buffer;
}
}
return null;
}
/// <summary>
/// 拼接读取数据报文
/// </summary>
/// <param name="slaveld">读取的地址</param>
/// <param name="functionCode">读取的功能码</param>
/// <param name="startAddress">读取的起始地址</param>
/// <param name="count">读取的数据长度</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteRead(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
//拼接报文
//创建字节数组
byte[] SendCommand = new byte[8];
//从站地址+功能码+起始高位+起始低位+数量高位+数量低位+CRC校验
//读取的地址
SendCommand[0] = slaveld;
//读取的功能码
SendCommand[1] = functionCode;
//一个ushort类型的数可以分为 256*高位+低位
//对ushort类型的数进行 这个数除以256 得到高位数 这个数对256求余 得到低位数
//读取的起始地址
SendCommand[2] = (byte)(startAddress / 256);
SendCommand[3] = (byte)(startAddress % 256);
//读取的数据长度
SendCommand[4] = (byte)(count / 256);
SendCommand[5] = (byte)(count % 256);
//CRC校验
byte[] crc = Crc16(SendCommand, 6);
//添加CRC校验
SendCommand[6] = crc[0];
SendCommand[7] = crc[1];
return SendCommand;
}
/// <summary>
/// 发送查询string字符串命令
/// </summary>
/// <param name="slaveld">读取的地址</param>
/// <param name="functionCode">读取的功能码</param>
/// <param name="startAddress">读取的起始地址</param>
/// <param name="count">读取的数据长度</param>
/// <returns>查询的返回数据 null为查询失败</returns>
private byte[] ReadDataString(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (CurrentCOM != null)
{
//组织读取报文
byte[] SendCommand = GetDatachangeMsgByteRead(slaveld, functionCode, startAddress, count);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(300);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
//验证CRC校验
if (CheckCRC(buffer))
{
return buffer;
}
}
return null;
}
6、编写写入拼接方法
/// <summary>
/// 拼接写数据布尔类型 和 ushort报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">写入的功能码 05 06</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, byte functionCode, ushort startAddress, ushort value)
{
//拼接报文
//创建字节数组
byte[] SendCommand = new byte[8];
//从站地址+功能码+起始高位+起始低位+数量高位+数量低位+CRC校验
//写入的地址
SendCommand[0] = slaveld;
//写入的功能码
SendCommand[1] = functionCode;
//一个ushort类型的数可以分为 256*高位+低位
//对ushort类型的数进行 这个数除以256 得到高位数 这个数对256求余 得到低位数
//写入的起始地址
SendCommand[2] = (byte)(startAddress / 256);
SendCommand[3] = (byte)(startAddress % 256);
//判断写入的功能码
if (functionCode == 5)
{
//写入的是0,布尔值为false
if (value == 0)
{
SendCommand[4] = 0x00;
SendCommand[5] = 0x00;
}
//写入的不是0,布尔值为true
else
{
SendCommand[4] = 0xff;
SendCommand[5] = 0x00;
}
}
//转换成16位无符号整数
else
{
SendCommand[4] = (byte)(value / 256);
SendCommand[5] = (byte)(value % 256);
}
//CRC校验
byte[] crc = Crc16(SendCommand, 6);
//添加CRC校验
SendCommand[6] = crc[0];
SendCommand[7] = crc[1];
return SendCommand;
}
/// <summary>
/// 拼接写 short数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, short value)
{
//拼接报文
//创建字节数组
byte[] SendCommand = new byte[8];
//从站地址+功能码+起始高位+起始低位+数量高位+数量低位+CRC校验
//写入的地址
SendCommand[0] = slaveld;
//写入的功能码
SendCommand[1] = 6;
//一个ushort类型的数可以分为 256*高位+低位
//对ushort类型的数进行 这个数除以256 得到高位数 这个数对256求余 得到低位数
//写入的起始地址
SendCommand[2] = (byte)(startAddress / 256);
SendCommand[3] = (byte)(startAddress % 256);
byte[] byt = BitConverter.GetBytes(value);
SendCommand[4] = byt[1];
SendCommand[5] = byt[0];
//CRC校验
byte[] crc = Crc16(SendCommand, 6);
//添加CRC校验
SendCommand[6] = crc[0];
SendCommand[7] = crc[1];
return SendCommand;
}
/// <summary>
/// 拼接写 char数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, char value)
{
//拼接报文
//创建字节数组
byte[] SendCommand = new byte[8];
//从站地址+功能码+起始高位+起始低位+数量高位+数量低位+CRC校验
//写入的地址
SendCommand[0] = slaveld;
//写入的功能码
SendCommand[1] = 6;
//一个ushort类型的数可以分为 256*高位+低位
//对ushort类型的数进行 这个数除以256 得到高位数 这个数对256求余 得到低位数
//写入的起始地址
SendCommand[2] = (byte)(startAddress / 256);
SendCommand[3] = (byte)(startAddress % 256);
byte[] byt = BitConverter.GetBytes(value);
SendCommand[4] = byt[1];
SendCommand[5] = byt[0];
//CRC校验
byte[] crc = Crc16(SendCommand, 6);
//添加CRC校验
SendCommand[6] = crc[0];
SendCommand[7] = crc[1];
return SendCommand;
}
/// <summary>
/// 拼接写16位short数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, short[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
//把16位short型转换成字节数组
byte[] byt = BitConverter.GetBytes(value[i]);
//把字节数组中的高低位颠倒
ReverseBytes16(byt);
//加到集合中
SendCommand.AddRange(byt);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写16位ushort数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, ushort[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
//把16位ushort型转换成字节数组
byte[] byt = BitConverter.GetBytes(value[i]);
//把字节数组中的高低位颠倒
ReverseBytes16(byt);
//加到集合中
SendCommand.AddRange(byt);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写16位ushort数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 15 16</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, byte functionCode, ushort startAddress, ushort count, ushort[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(functionCode);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
if(functionCode==15)
{
//声明一个收到数据的个数
ushort number = (ushort)(count*16);
//寄存器个数的高位
SendCommand.Add((byte)(number / 256));
//寄存器个数的低位
SendCommand.Add((byte)(number % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
SendCommand.Add((byte)(value[i] % 256));
SendCommand.Add((byte)(value[i] / 256));
}
}
else
{
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
SendCommand.Add((byte)(value[i] / 256));
SendCommand.Add((byte)(value[i] % 256));
}
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写32位int数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, int[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count*2));
for (int i = 0; i < value.Length; i++)
{
//把32位int型转换成字节数组
byte[] byt = BitConverter.GetBytes(value[i]);
//把字节数组中的高低位颠倒
ReverseBytes32(byt);
//加到集合中
SendCommand.AddRange(byt);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写32位uint数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, uint[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
//把32位uint型转换成字节数组
byte[] byt = BitConverter.GetBytes(value[i]);
//把字节数组中的高低位颠倒
ReverseBytes32(byt);
//加到集合中
SendCommand.AddRange(byt);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写32位float数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, float[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
//把32位float型转换成字节数组
byte[] byt = BitConverter.GetBytes(value[i]);
//把字节数组中的高低位颠倒
ReverseBytes32(byt);
//加到集合中
SendCommand.AddRange(byt);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写字符串数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <param name="value">写入的数据</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, char[] value)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0; i < value.Length; i++)
{
//把32位int型转换成字节数组
byte[] byt = BitConverter.GetBytes(value[i]);
//把字节数组中的高低位颠倒
ReverseBytes16(byt);
//加到集合中
SendCommand.AddRange(byt);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
/// <summary>
/// 拼接写字符串数据报文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址</param>
/// <param name="count">写入的数据长度</param>
/// <returns>拼接好的报文</returns>
private byte[] GetDatachangeMsgByteWriteString(byte slaveld, ushort startAddress, ushort count)
{
//地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码
//拼接报文
//创建字节数组集合
List<byte> SendCommand = new List<byte>();
//从站地址
SendCommand.Add(slaveld);
//功能码
SendCommand.Add(16);
//寄存器起始地址的高位
SendCommand.Add((byte)(startAddress / 256));
//寄存器起始地址的低位
SendCommand.Add((byte)(startAddress % 256));
//寄存器个数的高位
SendCommand.Add((byte)(count / 256));
//寄存器个数的低位
SendCommand.Add((byte)(count % 256));
//要写入数据的字节数
SendCommand.Add((byte)(count * 2));
for (int i = 0,j=0; i < count * 2; i++)
{
SendCommand.Add((byte)j);
}
//CRC校验
byte[] crc = Crc16(SendCommand.ToArray(), SendCommand.Count);
//CRC校验加到集合中
SendCommand.AddRange(crc);
//返回拼接好的字符
return SendCommand.ToArray();
}
7、编写读取方法
#region 读取数据
/// <summary>
/// 读取bool数据结果
/// </summary>
/// <param name="slaveld">读取从站的地址</param>
/// <param name="functionCode">读取的功能码 值为 01 02 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址 读取的地址从0开始</param>
/// <param name="count">读取的数据长度</param>
/// <returns>读取到的值 返回null则读取失败</returns>
public bool[] ReadBool(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 2 || functionCode == 1 || functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadData(slaveld, functionCode, startAddress, count);
//声明一个收到数据的个数
ushort number;
//表示一个收到数据有多少位
ushort count1;
//判断是读取位还是读取字的
if (functionCode == 2 || functionCode == 1)
{
//表示读取的是位
if ((count % 8) == 0)
{
number = (ushort)(count / 8);
}
else
{
number = (ushort)((count / 8) + 1);
}
count1 = count;
}
else
{
//表示读取的是字
//字的长度有两位组成
number = (ushort)(count * 2);
count1 = (ushort)(number * 8);
}
//验证报文
if (buffer != null)
{
//判断长度是否正常
if (buffer.Length == 5 + number)
{
//判断地址和功能码
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
char[] chk = new char[8] { '0', '0', '0', '0', '0', '0', '0', '0' };
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
if (functionCode == 4 || functionCode == 3)
{
//高低地址交换
ReverseBytes16(result);
}
//声明一个字符数组,用来接受转换后的二进制
char[] returns = new char[count1];
char[] intermediate;
for (int i = 0; i < result.Length; i++)
{
//把收到的数据转换成二进制字符串
intermediate = Convert.ToString(result[i], 2).ToArray();
//反转字符串
Array.Reverse(intermediate);
//把收到的每个数据都加载到声明的字符数组中
Array.Copy(intermediate, 0, returns, i * 8, intermediate.Length);
//补齐收到数据中的零
if (i * 8 + 8 < count1)
{
Array.Copy(chk, 0, returns, i * 8 + intermediate.Length, 8 - intermediate.Length);
}
else if (i * 8 + intermediate.Length < count1)
{
Array.Copy(chk, 0, returns, i * 8 + intermediate.Length, count1 - (i * 8 + intermediate.Length));
}
}
//把收到的字符数组转换成布尔数组并返回
return CharacterToBoolean(returns);
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取浮点数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
public float[] ReadFloat(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadData(slaveld, functionCode, startAddress, (ushort)(count * 2));
//声明一个收到数据的个数
ushort number = (ushort)(count * 4);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//高低地址交换
ReverseBytes32(result);
//声明一个用来返回结果的数组
float[] returns = new float[count];
float intermediate;
for (int i = 0; i * 4 < result.Length; i++)
{
//转换成32位浮点数
intermediate = BitConverter.ToSingle(result, i * 4);
returns[i] = intermediate;
}
//返回结果
return returns;
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取32位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
public int[] ReadInt(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadData(slaveld, functionCode, startAddress, (ushort)(count * 2));
//声明一个收到数据的个数
ushort number = (ushort)(count * 4);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//高低地址交换
ReverseBytes32(result);
//声明一个用来返回结果的数组
int[] returns = new int[count];
int intermediate;
for (int i = 0; i * 4 < result.Length; i++)
{
//转换成32位整数
intermediate = BitConverter.ToInt32(result, i * 4);
returns[i] = intermediate;
}
//返回结果
return returns;
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取32位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
public uint[] ReadUint(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadData(slaveld, functionCode, startAddress, (ushort)(count * 2));
//声明一个收到数据的个数
ushort number = (ushort)(count * 4);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//高低地址交换
ReverseBytes32(result);
//声明一个用来返回结果的数组
uint[] returns = new uint[count];
uint intermediate;
for (int i = 0; i * 4 < result.Length; i++)
{
//转换成32位无符号整数
intermediate = BitConverter.ToUInt32(result, i * 4);
returns[i] = intermediate;
}
//返回结果
return returns;
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取16位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
public short[] ReadShore(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadData(slaveld, functionCode, startAddress, count);
//声明一个收到数据的个数
ushort number = (ushort)(count * 2);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//高低地址交换
ReverseBytes16(result);
//声明一个用来返回结果的数组
short[] returns = new short[count];
short intermediate;
for (int i = 0; i * 2 < result.Length; i++)
{
//转换成16位整数
intermediate = BitConverter.ToInt16(result, i * 2);
returns[i] = intermediate;
}
//返回结果
return returns;
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取16位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取数据的个数</param>
/// <returns>读取到的值 返回null则读取失败</returns>
public ushort[] ReadUshore(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadData(slaveld, functionCode, startAddress, count);
//声明一个收到数据的个数
ushort number = (ushort)(count * 2);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//高低地址交换
ReverseBytes16(result);
//声明一个用来返回结果的数组
ushort[] returns = new ushort[count];
ushort intermediate;
for (int i = 0; i * 2 < result.Length; i++)
{
//转换成16位无符号整数
intermediate = BitConverter.ToUInt16(result, i * 2);
returns[i] = intermediate;
}
//返回结果
return returns;
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取字符串 格式是ASCII 不能表示中文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取字符的个数 </param>
/// <returns>读取到的值 返回null则读取失败</returns>
public string ReadStringASCII(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadDataString(slaveld, functionCode, startAddress, (ushort)(count));
//声明一个收到数据的个数
ushort number = (ushort)(count * 2);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//声明字符串
string intermediate;
//把收到的字节数组转换成字符串
intermediate = Encoding.ASCII.GetString(result, 0, result.Length);
//返回结果
return intermediate;
}
}
}
}
//解析失败返回 nill
return null;
}
/// <summary>
/// 读取字符串 格式是Unicode 可以表示中文
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 03 04 </param>
/// <param name="startAddress">读取的起始地址 偏移地址</param>
/// <param name="count">读取字符的个数 </param>
/// <returns>读取到的值 返回null则读取失败</returns>
public string ReadStringUnicode(byte slaveld, byte functionCode, ushort startAddress, ushort count)
{
if (functionCode == 3 || functionCode == 4)
{
//调用函数来发送查询命令
byte[] buffer = ReadDataString(slaveld, functionCode, startAddress, (ushort)(count));
//声明一个收到数据的个数
ushort number = (ushort)(count * 2);
//验证报文
if (buffer != null)
{
if (buffer.Length == 5 + number)
{
if (buffer[0] == slaveld && buffer[1] == functionCode)
{
//解析报文
//接受数据
byte[] result = new byte[number];
//获取数据,去除报头和校验
Array.Copy(buffer, 3, result, 0, number);
//高低地址交换
ReverseBytes16(result);
//声明字符串
string intermediate;
//把收到的字节数组转换成字符串
intermediate = Encoding.Unicode.GetString(result, 0, result.Length);
//返回结果
return intermediate;
}
}
}
}
//解析失败返回 nill
return null;
}
#endregion
8、编写写入方法
#region 写入数据
/// <summary>
/// 写入16位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write16(byte slaveld, ushort startAddress, ushort value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld,6, startAddress, value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if ( buffer[1] == 6)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入16位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write16(byte slaveld, ushort startAddress, short value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 6)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入多个16位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write16(byte slaveld, ushort startAddress, ushort count, short[] value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, count, value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入多个16位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write16(byte slaveld, ushort startAddress, ushort count, ushort[] value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, count, value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入32位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write32(byte slaveld, ushort startAddress, int value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld,startAddress,2,new int[]{value} );
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入32位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write32(byte slaveld, ushort startAddress, uint value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, 2, new uint[] { value });
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入多个32位无符号整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write32(byte slaveld, ushort startAddress, ushort count, uint[] value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, (ushort)(count*2), value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入多个32位整数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write32(byte slaveld, ushort startAddress, ushort count, int[] value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, (ushort)(count * 2), value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入32位浮点数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据 </param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write32(byte slaveld, ushort startAddress, float value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, 2, new float[] { value });
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入多个32位浮点数
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="count">写入的个数</param>
/// <param name="value">写入的数据</param>
/// <returns>写入的结果 成功返回true</returns>
public bool Write32(byte slaveld, ushort startAddress, ushort count, float[] value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, (ushort)(count * 2), value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入字符串
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="startAddress">写入的起始地址 偏移地址</param>
/// <param name="value">写入的数据 </param>
/// <returns>写入的结果 成功返回true</returns>
public bool WriteString(byte slaveld, ushort startAddress, string value)
{
//清空以前数据
byte[] by = GetDatachangeMsgByteWriteString(slaveld, startAddress, 64);
//发送报文
CurrentCOM.Write(by, 0, by.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffers = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffers, 0, buffers.Length);
//字符串转成字符数组
char[] ch = value.ToCharArray();
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, startAddress, (ushort)(ch.Length), ch);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入单个布尔值
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 功能码为05 06 </param>
/// <param name="startAddress">写入偏移地址</param>
/// <param name="value">写入数据</param>
/// <returns>写入是否成功 成功返回true</returns>
public bool WriteBool(byte slaveld, byte functionCode,ushort startAddress, ushort value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld,functionCode,startAddress,value);
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if(buffer[1]==5|| buffer[1] == 6)
{
return true;
}
//写入失败返回 false
return false;
}
/// <summary>
/// 写入多个布尔值
/// </summary>
/// <param name="slaveld">从站地址</param>
/// <param name="functionCode">功能码 功能码为15 16 </param>
/// <param name="startAddress">写入偏移地址</param>
/// <param name="count">写入数据的个数</param>
/// <param name="value">写入数据</param>
/// <returns>写入是否成功 成功返回true</returns>
public bool WriteBool(byte slaveld, byte functionCode, ushort startAddress, ushort count, ushort[] value)
{
//创建字节数组
byte[] SendCommand = GetDatachangeMsgByteWrite(slaveld, functionCode, startAddress, count,value );
//发送报文
CurrentCOM.Write(SendCommand, 0, SendCommand.Length);
//接受报文
Thread.Sleep(100);
//定义一个字节数组buffer 用来接收缓存区的数据
byte[] buffer = new byte[CurrentCOM.BytesToRead];
//接受缓存取得数据
CurrentCOM.Read(buffer, 0, buffer.Length);
if (buffer[1] == 15 || buffer[1] == 16)
{
return true;
}
//写入失败返回 false
return false;
}
#endregion
三、调用类库
1、打开关闭串口
//引入名称空间
using MCGSModbus;
//声明类库实例
MCGSModbusRTU MCGSModbus = null;
//创建MCGSRTU通讯对象
MCGSModbus = new MCGSModbusRTU();
//打开串口
MCGSModbus.OpenCOM(COMPortComboBox.Text, Convert.ToInt32(BaudRateComboBox.Text), ParityBitComboBox.Text, Convert.ToInt32(DataBitsComboBox.Text), Convert.ToInt32(StopBitComboBox.Text));
//关闭串口
MCGSModbus.CloseCOM();
2、读取数据
//读取数据
private void ReadButton_Click(object sender, EventArgs e)
{
mark = true;
//数据转换
DataParsing(FunctionCodeComboBox.Text, OffsetTextBox.Text, NumberTextBox.Text);
if (mark)
{
try
{
int a;
switch (TypeComboBox.Text)
{
case "位":
{
bool[] accept = MCGSModbus.ReadBool(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
for (int i = 0; i < accept.Length; i++)
{
DataTextBox.Text += (a++) + ": " + accept[i] + " ";
if (i!=0&&i % 7 == 0)
{
//显示数据控件换行
DataTextBox.Text += "\r\n";
}
}
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
case "16位整型":
{
short[] accept = MCGSModbus.ReadShore(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
for (int i = 0; i < accept.Length; i++)
{
DataTextBox.Text += (a++) + ": " + accept[i] + " ";
if (i != 0 && i % 7 == 0)
{
//显示数据控件换行
DataTextBox.Text += "\r\n";
}
}
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
case "16位无符号整型":
{
ushort[] accept = MCGSModbus.ReadUshore(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
for (int i = 0; i < accept.Length; i++)
{
DataTextBox.Text += (a++) + ": " + accept[i] + " ";
if (i != 0 && i % 7 == 0)
{
//显示数据控件换行
DataTextBox.Text += "\r\n";
}
}
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
case "32位整型":
{
int[] accept = MCGSModbus.ReadInt(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
for (int i = 0; i < accept.Length; i++)
{
DataTextBox.Text += a + ": " + accept[i] + " ";
a += 2;
if (i != 0 && i % 7 == 0)
{
//显示数据控件换行
DataTextBox.Text += "\r\n";
}
}
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
case "32位无符号整型":
{
uint[] accept = MCGSModbus.ReadUint(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
for (int i = 0; i < accept.Length; i++)
{
DataTextBox.Text += a + ": " + accept[i] + " ";
a += 2;
if (i != 0 && i % 7 == 0)
{
//显示数据控件换行
DataTextBox.Text += "\r\n";
}
}
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
case "浮点型":
{
float[] accept = MCGSModbus.ReadFloat(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
for (int i = 0; i < accept.Length; i++)
{
DataTextBox.Text += a + ": " + accept[i] + " ";
a += 2;
if (i != 0 && i % 7 == 0)
{
//显示数据控件换行
DataTextBox.Text += "\r\n";
}
}
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
case "字符串":
{
string accept = MCGSModbus.ReadStringUnicode(slaveld, functionCode, startAddress, count);
a = startAddress + 1;
if (accept != null)
{
DataTextBox.Text += a + ": " + accept + " ";
ReadTipLabel.Text = "读取成功";
}
else
{
ReadTipLabel.Text = "读取失败";
return;
}
}
break;
default:
break;
}
//显示数据控件换行
DataTextBox.Text += "\r\n\r\n";
//设置显示数据控件的光标在末尾
this.DataTextBox.SelectionStart = this.DataTextBox.Text.Length;
//跳到光标所在位置
this.DataTextBox.ScrollToCaret();
}
catch
{
ReadTipLabel.Text = "读取失败";
}
}
}
3、写入数据
//写入单个数据
private void WriteDataButton_Click(object sender, EventArgs e)
{
mark = true;
DataParsing(FunctionCodeComboBox1.Text, OffsetTextBox1.Text);
if (mark)
{
try
{
switch (TypeComboBox1.Text)
{
case "位":
{
ushort value;
try
{
value = Convert.ToUInt16(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.WriteBool(slaveld, functionCode, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
case "16位整型":
{
short value;
try
{
value = Convert.ToInt16(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write16(slaveld, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
case "16位无符号整型":
{
ushort value;
try
{
value = Convert.ToUInt16(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write16(slaveld, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
case "32位整型":
{
int value;
try
{
value = Convert.ToInt32(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write32(slaveld, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
case "32位无符号整型":
{
uint value;
try
{
value = Convert.ToUInt32(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write32(slaveld, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
case "浮点型":
{
float value;
try
{
value = Convert.ToSingle(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write32(slaveld, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
case "字符":
{
char value;
try
{
value = Convert.ToChar(WriteDataTextBox.Text);
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write16(slaveld, startAddress, value))
{
WriteSignLabel.Text = "写入成功";
}
else
{
WriteSignLabel.Text = "写入失败";
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
break;
default:
break;
}
}
catch
{
WriteSignLabel.Text = "写入失败";
}
}
}
//写入多个数据
private void WriteDatasButton_Click(object sender, EventArgs e)
{
mark = true;
DataParsing(FunctionCodeComboBox2.Text, OffsetTextBox2.Text);
if (mark)
{
try
{
switch (TypeComboBox2.Text)
{
case "位":
{
ushort[] value;
try
{
string[] strArray;
if (WriteDatasTextBox.Text.Contains(","))
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
else
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
value = new ushort[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
value[i] = Convert.ToUInt16(strArray[i]);
}
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.WriteBool(slaveld, functionCode, startAddress,(ushort) value.Length, value))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
case "16位整型":
{
short[] value;
try
{
string[] strArray;
if (WriteDatasTextBox.Text.Contains(","))
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
else
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
value = new short[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
value[i] = Convert.ToInt16(strArray[i]);
}
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write16(slaveld, startAddress, (ushort)value.Length, value))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
case "16位无符号整型":
{
ushort[] value;
try
{
string[] strArray;
if (WriteDatasTextBox.Text.Contains(","))
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
else
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
value = new ushort[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
value[i] = Convert.ToUInt16(strArray[i]);
}
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write16(slaveld, startAddress, (ushort)value.Length, value))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
case "32位整型":
{
int[] value;
try
{
string[] strArray;
if (WriteDatasTextBox.Text.Contains(","))
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
else
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
value = new int[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
value[i] = Convert.ToInt32(strArray[i]);
}
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write32(slaveld, startAddress, (ushort)value.Length, value))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
case "32位无符号整型":
{
uint[] value;
try
{
string[] strArray;
if (WriteDatasTextBox.Text.Contains(","))
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
else
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
value = new uint[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
value[i] = Convert.ToUInt32(strArray[i]);
}
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write32(slaveld, startAddress, (ushort)value.Length, value))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
case "浮点型":
{
float[] value;
try
{
string[] strArray;
if (WriteDatasTextBox.Text.Contains(","))
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
else
{
strArray = WriteDatasTextBox.Text.Split(',');//字符串转数组
}
value = new float[strArray.Length];
for (int i = 0; i < strArray.Length; i++)
{
value[i] = Convert.ToSingle(strArray[i]);
}
}
catch
{
MessageBox.Show("数据错误");
return;
}
try
{
if (MCGSModbus.Write32(slaveld, startAddress, (ushort)value.Length, value))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
case "字符串":
{
try
{
if (MCGSModbus.WriteString(slaveld, startAddress, WriteDatasTextBox.Text))
{
WriteSignLabel1.Text = "写入成功";
}
else
{
WriteSignLabel1.Text = "写入失败";
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
break;
default:
break;
}
}
catch
{
WriteSignLabel1.Text = "写入失败";
}
}
}