一、发送指令转换代码
二、返回的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;
}
}