Modbus协议指令转换封装

一、发送指令转换代码

二、返回的byte[]转换为数字

/// <summary>
	/// 单类模板类
	/// </summary>
	/// <typeparam name="T"></typeparam>
	public class SingleTemplate<T> where T : class, new()
	{
		/// <summary>
		/// 
		/// </summary>
		public static object M_Lock = new object();
		/// <summary>
		/// 
		/// </summary>
		private static T M_InstanceT;

		public static T Instance
		{
			get
			{
				lock (M_Lock)
				{
					if (M_InstanceT == null)
					{
						M_InstanceT = Activator.CreateInstance<T>();
					}
				}

				return M_InstanceT;
			}
		}
	}

public class ModbusMgr : SingleTemplate<ModbusMgr>
	{
		/// <summary>
		/// 指令参数:从站、功能码、寄存器信息(起始地址、长度、字节数、高低位顺序)
		/// </summary>
		public class CommandsParam
		{
			/// <summary>
			/// 从站,占指令1个字节
			/// </summary>
			public int StationNo_m;
			/// <summary>
			/// 功能码,占指令1个字节
			/// </summary>
			public int Code_m;
			/// <summary>
			/// 寄存器起始地址,占指令N个字节(N=RegisterBytes_m)
			/// </summary>
			public int Address_m;
			/// <summary>
			///寄存器长度(即读取的寄存器个数) ,占指令N个字节(N=RegisterBytes_m)
			/// </summary>
			public int AddrLength_m;
			/// <summary>
			/// 寄存器(地址、长度)字节个数,范围:1~4
			/// </summary>
			public int RegisterBytes_m;
			/// <summary>
			/// 寄存器参数是否低位在前,true=是
			/// </summary>
			public bool IsLowerRegister_m = false;

			/// <summary>
			/// 读取寄存器指令参数:从站、功能码、寄存器信息(起始地址、长度、字节数、高低位顺序)
			/// </summary>
			/// <param name="stationNo">从站,单字节</param>
			/// <param name="code">功能码,单字节</param>
			/// <param name="address">寄存器起始地址</param>
			/// <param name="length">读取长度,即读取的寄存器个数</param>
			/// <param name="registerBytes">寄存器参数(地址、长度)字节个数 1~4</param>
			/// <param name="isLowerRegister">寄存器参数是否低位在前,true=是</param>
			public CommandsParam(int stationNo, int code, int address, int length, int registerBytes, bool isLowerRegister = false)
			{
				StationNo_m = stationNo;
				Code_m = code;
				Address_m = address;
				AddrLength_m = length;
				RegisterBytes_m = registerBytes;
				IsLowerRegister_m = isLowerRegister;
			}
		}

		/// <summary>
		/// 获取发送指令
		/// </summary>
		/// <param name="commnds">指令参数:从站、功能码、寄存器信息、数据信息</param>
		/// <param name="isLowerCRC">CRC是否低位在前,true=是</param>
		/// <returns></returns>
		public byte[] GetSendCommnds(byte[] bteComm, bool isLowerCRC = true)
		{
			byte[] byteSend = new byte[bteComm.Length + 2];//发送指令未含CRC
			byte[] bteCRC = GetCRC16(bteComm);

			//拼接发送指令byte[]
			for (int i = 0; i < bteComm.Length; i++)
			{
				byteSend[i] = bteComm[i];
			}

			for (int i = 0; i < 2; i++)
			{
				if (isLowerCRC)
				{
					byteSend[bteComm.Length + i] = bteCRC[i];
				}
				else
				{
					byteSend[bteComm.Length + i] = bteCRC[1 - i];
				}
			}
			return byteSend;
		}

		/// <summary>
		/// 指令:从站+功能码+寄存器起始地址 转换为byte[]
		/// </summary>
		/// <param name="param">指令参数</param>
		/// <returns></returns>
		public byte[] CommandsConvertByte(CommandsParam param)
		{
			if (param.RegisterBytes_m < 1 || param.RegisterBytes_m > 4)
			{
				return new byte[0];
			}

			int bytlength = 2 + 1 * param.RegisterBytes_m;//字节长度 = 从站地址1 + 功能码1 + 寄存器地址1 *寄存器字节数 
			byte[] bteCom = new byte[bytlength];//发送指令未含CRC
			int count = 0;//已计算多少个byte指令

			//计算从站和功能码byte值
			bteCom[0] = BitConverter.GetBytes(param.StationNo_m)[0];
			bteCom[1] = BitConverter.GetBytes(param.Code_m)[0];
			count += 2;

			//计算寄存器地址byte值
			byte[] bteTemp = BitConverter.GetBytes(param.Address_m);

			byte[] bteRegister = new byte[param.RegisterBytes_m];
			for (int i = 0; i < param.RegisterBytes_m; i++)
			{
				bteRegister[i] = bteTemp[i];//截取需要的数据
			}

			for (int i = 0; i < param.RegisterBytes_m; i++)
			{
				if (param.IsLowerRegister_m)
				{
					bteCom[count + i] = bteRegister[i];
				}
				else
				{
					bteCom[count + i] = bteRegister[param.RegisterBytes_m - 1 - i];
				}
			}

			return bteCom;
		}

		/// <summary>
		/// 指令:从站+功能码+寄存器起始地址+寄存器长度 转换为byte[],
		/// </summary>
		/// <param name="param">指令参数</param>
		/// <returns></returns>
		public byte[] CommandsConvertByteEx(CommandsParam param)
		{
			int count = 0;//已计算多少个byte指令
			byte[] bte1 = CommandsConvertByte(param);
			byte[] bte2 = IntConvertBytes(param.AddrLength_m, param.RegisterBytes_m, param.IsLowerRegister_m);

			int length = bte1.Length + param.RegisterBytes_m;
			byte[] bteCom = new byte[length];
			for (int i = 0; i < bte1.Length; i++)
			{
				bteCom[i] = bte1[i];
				count += 1;
			}

			for (int i = 0; i < bte2.Length; i++)
			{
				bteCom[count + i] = bte2[i];
			}

			return bteCom;
		}

		/// <summary>
		/// int值转换为byte数组
		/// </summary>
		/// <param name="value">参数值</param>
		/// <param name="length">字节长度</param>
		/// <param name="isLower">是否低位在前,true=是</param>
		/// <returns></returns>
		public byte[] IntConvertBytes(int value, int length, bool isLower = false)
		{
			return ConvertBytes(value, length, 0, isLower);
		}

		/// <summary>
		/// int值转换为byte数组
		/// </summary>
		/// <param name="value">参数值</param>
		/// <param name="length">字节长度</param>
		/// <param name="isLower">是否低位在前,true=是</param>
		/// <returns></returns>
		public byte[] FloatConvertBytes(float value, int length, bool isLower = false)
		{
			return ConvertBytes(value, length, 1, isLower);
		}

		/// <summary>
		/// int值转换为byte数组
		/// </summary>
		/// <param name="value">参数值</param>
		/// <param name="length">字节长度</param>
		/// <param name="isLower">是否低位在前,true=是</param>
		/// <returns></returns>
		public byte[] DoubleConvertBytes(double value, int length, bool isLower = false)
		{
			return ConvertBytes(value, length, 2, isLower);
		}

		/// <summary>
		/// 值转换为byte数组
		/// </summary>
		/// <param name="iParam">参数值</param>
		/// <param name="length">字节长度</param>
		/// <param name="paramType">参数值类型:0=int,1=float,2=double</param>
		/// <param name="isLower">是否低位在前,true=是</param>
		/// <returns></returns>
		private byte[] ConvertBytes(object iParam, int length, int paramType = 0, bool isLower = false)
		{
			byte[] bytResult = new byte[length];
			byte[] byt1 = BitConverter.GetBytes(Convert.ToInt32(iParam));
			if (paramType == 1)
			{
				byt1 = BitConverter.GetBytes(Convert.ToSingle(iParam));
			}
			else if (paramType == 2)
			{
				byt1 = BitConverter.GetBytes(Convert.ToDouble(iParam));
			}

			byte[] bte2 = new byte[length];
			for (int i = 0; i < length; i++)
			{
				//截取需要的数据
				if (i < byt1.Length)
				{
					bte2[i] = byt1[i];
				}
				else
				{
					bte2[i] = 0;
				}
			}

			for (int i = 0; i < length; i++)
			{
				if (isLower)
				{
					bytResult[i] = bte2[i];
				}
				else
				{
					bytResult[i] = bte2[length - 1 - i];
				}
			}

			return bytResult;
		}

		/// <summary>
		/// 获取CRC校验码,2个字节
		/// </summary>
		/// <param name="bytes">指令</param>
		/// <returns></returns>
		private byte[] GetCRC16(byte[] bytes)
		{
			ushort value;
			ushort crcData = 0xffff, In_value;
			int count = 0;
			for (int i = 0; i < bytes.Length; i++)
			{
				value = (ushort)bytes[i];
				crcData = (ushort)(Convert.ToInt32(value) ^ Convert.ToInt32(crcData));
				In_value = 0xA001;
				while (count < 8)
				{
					if (Convert.ToInt32(crcData) % 2 == 1)//判断最低位是否为1
					{
						crcData -= 0x00001;
						crcData = (ushort)(Convert.ToInt32(crcData) / 2);//右移一位
						count++;//计数器加一
						crcData = (ushort)(Convert.ToInt32(crcData) ^ Convert.ToInt32(In_value));//异或操作
					}
					else
					{
						crcData = (ushort)(Convert.ToInt32(crcData) / 2);//右移一位
						count++;//计数器加一
					}
				}
				count = 0;
			}

			byte[] crcBytes = new byte[2];
			crcBytes[0] = (byte)(crcData & 0x00FF);
			crcBytes[1] = (byte)((crcData & 0xFF00) >> 8);

			return crcBytes;
		}

		/// <summary>
		/// byte[4] 转换为 float;索引0=低位
		/// </summary>
		/// <param name="bytes">4字节;索引0为低位</param>
		/// <returns></returns>
		public float BytesConvertFloat(byte[] bytes)
		{
			float fRead = 0.0f;
			if (bytes.Length == 4)
			{
				fRead = BitConverter.ToSingle(bytes, 0);
			}
			return fRead;
		}

		/// <summary>
		/// byte[] 转换为 Int16/Int32 索引0=低位
		/// </summary>
		/// <param name="bytes">2字节Int16,4字节Int32;索引0为低位</param>
		/// <returns></returns>
		public int BytesConvertInt(byte[] bytes)
		{
			//根据通讯协议,返回数据字节数以及数字类型,调用对应转换
			int iRead = 0;
			if (bytes.Length == 4)
			{
				iRead = BitConverter.ToInt32(bytes, 0);
			}
			else if (bytes.Length == 2)
			{
				iRead = BitConverter.ToInt16(bytes, 0);
			}
			return iRead;
		}

		/// <summary>
		/// byte[]转换为double;索引0=低位
		/// </summary>
		/// <param name="bytes">返回数据;索引0为低位</param>
		/// <returns></returns>
		public double BytesConvertDouble(byte[] bytes)
		{
			double dbRead = 0.0;
			if (bytes.Length == 8)
			{
				dbRead = BitConverter.ToDouble(bytes, 0);
			}
			return dbRead;
		}

		/// <summary>
		/// 字节数组转换为16进制ASCII字符串
		/// </summary>
		/// <param name="array"></param>
		/// <returns></returns>
		public string ByteToASCIIString(byte[] array)
		{
			StringBuilder sb = new StringBuilder();

			foreach (byte data in array)
			{
				sb.Append(data.ToString("X2"));
			}

			return sb.ToString();
		}

		/// <summary>
		/// 十六进制string转换为byte[];2个长度转换为一个byte
		/// </summary>
		/// <param name="hexString"></param>
		/// <returns></returns>
		public byte[] StrToToHexByte(string hexString)
		{
			hexString = hexString.Replace(" ", "");
			if ((hexString.Length % 2) != 0)
				hexString = hexString.Insert(hexString.Length - 1, 0.ToString());
			byte[] returnBytes = new byte[hexString.Length / 2];
			for (int i = 0; i < returnBytes.Length; i++)
				returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
			return returnBytes;
		}
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值