最近学习了ModbusRTU协议,自己就用C#编写了一个ModbusRTU类库,用来和MCGS触摸屏做通讯,因本人新手一个,编出来的类库可能还有漏洞,修望大家多包涵。
这是我编写的类库下载地址MCGSModbusRTU类库
也可以看我下面的代码自己编写。
因为是与MCGS通讯,首先要设置MCGS的参数。我用的屏型号TPC7032Kt ,屏的编程软件是McgsPro组态软件。这款屏的通讯端口为3个,一个232,两个485.
要添加一个父类设备和和一个数据转发设备
设置父设备的参数,我用的端口号为COM2,波特率9600,数据位8,停止位1,数据校验为 无校验。
数据转发设置,设备地址为1,数据组码顺序数据按默认,字符串选择Unicode,支持中文编码,这个影响你后面对数据进行解析,我的类库也是按照这个顺序进行解析的,感兴趣的可以自己改变,然后自己进行解析。
触摸屏的参数就设置好了,剩下的就是关联变量。需要说明MCGS的地址是从1开始的,而我们用电脑读写是从0开始的。
现在可以开始编类库了,因为我们这个类库是要在Windows窗体中来使用,所以我创建的这个类库为 .NET Framework 类库。
为了调试需要,还要创建Windows窗体,然后在窗体中添加引用,因为我是在同一个解决方案下,可以直接添加引用。类库生成的是.dll文件。
直接添加.dll文件
以后有可能对这个类库进行扩展,能够走TCP协议,就声明了一个接口,这个不是必须的,
namespace MCGSModbus
{
///
/// MCGS通讯接口类
///
interface IMCGSData
{
#region 读取数据
///
/// 读取bool数据结果
///
/// 读取从站的地址
/// 读取的功能码 值为 01 02 03 04
/// 读取的起始地址 偏移地址 读取的地址从0开始
/// 读取的数据长度
/// 读取到的值 返回null则读取失败
bool[] ReadBool(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取浮点数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
float[] ReadFloat(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取32位整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
int[] ReadInt(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取32位无符号整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
uint[] ReadUint(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取16位整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
short[] ReadShore(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取16位无符号整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
ushort[] ReadUshore(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取字符串 格式是ASCII 不能表示中文
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取字符的个数
/// 读取到的值 返回null则读取失败
string ReadStringASCIi(byte slaveld, byte functionCode, ushort startAddress, ushort count);
///
/// 读取字符串 格式是Unicode 可以表示中文
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取字符的个数
/// 读取到的值 返回null则读取失败
string ReadStringUnicode(byte slaveld, byte functionCode, ushort startAddress, ushort count);
#endregion
#region 写入数据
///
/// 写入16位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
bool Write16(byte slaveld, ushort startAddress, ushort value);
///
/// 写入16位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
bool Write16(byte slaveld, ushort startAddress, short value);
///
/// 写入多个16位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
bool Write16(byte slaveld, ushort startAddress, ushort count, short[] value);
///
/// 写入多个16位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
bool Write16(byte slaveld, ushort startAddress, ushort count, ushort[] value);
///
/// 写入32位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
bool Write32(byte slaveld, ushort startAddress, int value);
///
/// 写入32位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
bool Write32(byte slaveld, ushort startAddress, uint value);
///
/// 写入多个32位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
bool Write32(byte slaveld, ushort startAddress, ushort count, uint[] value);
///
/// 写入多个32位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
bool Write32(byte slaveld, ushort startAddress, ushort count, int[] value);
///
/// 写入32位浮点数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
bool Write32(byte slaveld, ushort startAddress, float value);
///
/// 写入多个32位浮点数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
bool Write32(byte slaveld, ushort startAddress, ushort count, float[] value);
///
/// 写入字符串
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
bool WriteString(byte slaveld, ushort startAddress, string value);
///
/// 写入单个布尔值
///
/// 从站地址
/// 功能码 功能码为05 06
/// 写入偏移地址
/// 写入数据
/// 写入是否成功 成功返回true
bool WriteBool(byte slaveld, byte functionCode, ushort startAddress, ushort value);
#endregion
}
}
接下来写ModbusRTU类库。
首先让这个类库继承接口,在类中实现接口。
建立串口实例,建立链接
////// 打开串口 /// /// 端口号 /// 波特率 /// 校验位 值为 无 奇 偶 /// 数据位 值为 8或7 /// 停止位 值为 0 1 2 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(); }
关闭串口
///3、编写数据处理方法/// 关闭串口 /// public void CloseCOM() { //关闭串口 if (CurrentCOM.IsOpen) { CurrentCOM.Close(); } }
把二进制字符数组转换成布尔值
////// 把二进制字符串数组转成布尔数组 /// /// 要转换的字符数组 ///转换后的布尔数组,失败返回 null 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位数据高低位交换
////// 16位数据高低位置转换 /// /// 要转换的数据 private void ReverseBytes16(byte[] by) { ListSendCommand = new List (); 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位数据进行高低位交换
///
/// 32位数据高低位置转换
///
/// 要转换的数据
private void ReverseBytes32(byte[] by)
{
List SendCommand = new List();
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
};
///
/// CRC校验
///
/// 要校验的字节数组
/// 要校验的字节个数
/// CRC校验码
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;
}
///
/// 判断CRC校验是否正确
///
/// 要校验的数据
/// 判断的结果
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、编写读取拼接方法
///6、编写写入拼接方法/// 发送查询数据命令 /// /// 读取的地址 /// 读取的功能码 /// 读取的起始地址 /// 读取的数据长度 ///查询的返回数据 null为查询失败 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; } ////// 拼接读取数据报文 /// /// 读取的地址 /// 读取的功能码 /// 读取的起始地址 /// 读取的数据长度 ///拼接好的报文 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; } ////// 发送查询string字符串命令 /// /// 读取的地址 /// 读取的功能码 /// 读取的起始地址 /// 读取的数据长度 ///查询的返回数据 null为查询失败 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; }
///7、编写读取方法/// 拼接写数据布尔类型 和 ushort报文 /// /// 从站地址 /// 写入的功能码 05 06 /// 写入的起始地址 /// 写入的数据 ///拼接好的报文 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; } ////// 拼接写 short数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据 ///拼接好的报文 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; } ////// 拼接写 char数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据 ///拼接好的报文 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; } ////// 拼接写16位short数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, short[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写16位ushort数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, ushort[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写16位ushort数据报文 /// /// 从站地址 /// 功能码 15 16 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, byte functionCode, ushort startAddress, ushort count, ushort[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写32位int数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, int[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写32位uint数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, uint[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写32位float数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, float[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写字符串数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 /// 写入的数据 ///拼接好的报文 private byte[] GetDatachangeMsgByteWrite(byte slaveld, ushort startAddress, ushort count, char[] value) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); } /// /// 拼接写字符串数据报文 /// /// 从站地址 /// 写入的起始地址 /// 写入的数据长度 ///拼接好的报文 private byte[] GetDatachangeMsgByteWriteString(byte slaveld, ushort startAddress, ushort count) { //地址、功能码、寄存器起始地址、寄存器个数、要写入数据的字节数、数据、校验码 //拼接报文 //创建字节数组集合 ListSendCommand = new List (); //从站地址 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(); }
#region 读取数据
///
/// 读取bool数据结果
///
/// 读取从站的地址
/// 读取的功能码 值为 01 02 03 04
/// 读取的起始地址 偏移地址 读取的地址从0开始
/// 读取的数据长度
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取浮点数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取32位整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取32位无符号整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取16位整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取16位无符号整数
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取数据的个数
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取字符串 格式是ASCII 不能表示中文
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取字符的个数
/// 读取到的值 返回null则读取失败
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;
}
///
/// 读取字符串 格式是Unicode 可以表示中文
///
/// 从站地址
/// 功能码 03 04
/// 读取的起始地址 偏移地址
/// 读取字符的个数
/// 读取到的值 返回null则读取失败
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 写入数据
///
/// 写入16位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入16位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入多个16位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入多个16位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入32位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入32位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入多个32位无符号整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入多个32位整数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入32位浮点数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入多个32位浮点数
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的个数
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入字符串
///
/// 从站地址
/// 写入的起始地址 偏移地址
/// 写入的数据
/// 写入的结果 成功返回true
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;
}
///
/// 写入单个布尔值
///
/// 从站地址
/// 功能码 功能码为05 06
/// 写入偏移地址
/// 写入数据
/// 写入是否成功 成功返回true
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;
}
///
/// 写入多个布尔值
///
/// 从站地址
/// 功能码 功能码为15 16
/// 写入偏移地址
/// 写入数据的个数
/// 写入数据
/// 写入是否成功 成功返回true
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 += "rn";
}
}
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 += "rn";
}
}
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 += "rn";
}
}
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 += "rn";
}
}
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 += "rn";
}
}
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 += "rn";
}
}
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 += "rnrn";
//设置显示数据控件的光标在末尾
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 = "写入失败";
}
}
}



