using System.IO.Ports;
namespace RamonCWQY
{
class RS485Service
{
public static SerialPort SerialPort = null;
public int[] responseArry = null; //返回的数据
/// <summary>
/// 打开串口
/// </summary>
/// <param name="comName">串口名称</param>
/// <param name="baud">比特率</param>
/// <returns></returns>
public static SerialPort OpenPort(string comName, int baud)
{
try
{
//串口未打开
if (SerialPort == null || !SerialPort.IsOpen)
{
SerialPort = new SerialPort();
//串口名称
SerialPort.PortName = comName;
//波特率
SerialPort.BaudRate = baud;
//数据位
SerialPort.DataBits = 8;
//停止位
SerialPort.StopBits = StopBits.One;
//校验位
SerialPort.Parity = Parity.None;
//打开串口
SerialPort.Open();
//串口数据接收事件实现
//SerialPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);
return SerialPort;
}
return SerialPort;
}
catch (System.Exception)
{
throw;
}
}
/// <summary>
/// 关闭端口
/// </summary>
public static void ClosePort()
{
SerialPort.Close();
SerialPort = null;
}
#region 读数据
/// <summary>
/// 根据参数编号进行读取
/// </summary>
/// <param name="iParamNo">要读参数的代号(十进制)</param>
/// <param name="iDevAdd">仪表地址参数值</param>
/// <param name="response">返回的值</param>
/// <returns></returns>
public static int[] ReadParam(byte iParamNo, byte iDevAdd)
{
try
{
if (SerialPort == null || !SerialPort.IsOpen)
{
OpenPort("COM3", 9600);
}
//第一步:拼接报文
ByteArray byteArray = new ByteArray();
byteArray.Add((byte)(128 + iDevAdd));
byteArray.Add((byte)(128 + iDevAdd));
byteArray.Add(82);
byteArray.Add(iParamNo);
byteArray.Add(new byte[] { 0, 0 });
byteArray.Add(GetSendParity(iParamNo, iDevAdd));
//第二步: 发送报文
SerialPort.Write(byteArray.array, 0, byteArray.array.Length);
System.Threading.Thread.Sleep(200);
//第3步:获取数据
int n = SerialPort.BytesToRead;
byte[] original = new byte[n];
SerialPort.Read(original, 0, n);
//第4步:解析数据
if (original == null || original.Length <10)
{
return null;
}
int [] response = TranslateInfo(original);
return response;
}
catch (System.Exception)
{
throw;
}
}
/// <summary>
/// 读校验码
/// </summary>
/// <param name="iParamNo">要读参数的代号</param>
/// <param name="iDevAdd">仪表地址参数值</param>
/// <returns></returns>
private static byte[] GetSendParity(byte iParamNo, byte iDevAdd)
{
int Res = iParamNo * 256 + 82 + iDevAdd;
byte[] crc = new byte[2];
crc[0] = (byte)(Res % 256);
crc[1] = (byte)(Res / 256);
return crc;
}
#endregion
#region 写数据
/// <summary>
/// 根据编号的数字写入参数
/// </summary>
/// <param name="iParamNo"></param>
/// <param name="iValue"></param>
/// <param name="iDevAdd"></param>
/// <returns></returns>
public static int[] SetParam(byte iParamNo, int iValue, byte iDevAdd)
{
//第一步:拼接报文
ByteArray byteArray = new ByteArray();
byteArray.Add((byte)(128 + iDevAdd));
byteArray.Add((byte)(128 + iDevAdd));
byteArray.Add(67);
byteArray.Add((byte)iParamNo);
byteArray.Add((byte)(iValue % 256));
byteArray.Add((byte)(iValue / 256));
byteArray.Add(GetReceiveParity(iParamNo, iValue, iDevAdd));
//第二步: 发送报文
SerialPort.Write(byteArray.array, 0, byteArray.array.Length);
System.Threading.Thread.Sleep(200);
//第3步:获取数据
int n = SerialPort.BytesToRead;
byte[] original = new byte[n];
SerialPort.Read(original, 0, n);
//第4步:解析数据
if (original == null)
{
return null;
}
int [] response = TranslateInfo(original);
return response;
}
/// <summary>
/// 写校验码
/// </summary>
/// <param name="iParamNo">要写参数的代号</param>
/// <param name="iValue">要写的参数值</param>
/// <param name="iDevAdd">仪表地址参数值</param>
/// <returns></returns>
private static byte[] GetReceiveParity(byte iParamNo, int iValue, byte iDevAdd)
{
int Res = iParamNo * 256 + 67 + iValue + iDevAdd;
byte[] crc = new byte[2];
crc[0] = (byte)(Res % 256);
crc[1] = (byte)(Res / 256);
return crc;
}
#endregion
/// <summary>
/// 解析报文
/// </summary>
/// <param name="result"></param>
/// <returns></returns>
public static int[] TranslateInfo(byte[] result)
{
if (result.Length <10)
{
return null;
}
int[] resultArray = new int[3];
resultArray[0] = (result[1] * 256 + result[0])/10;
resultArray[1] = (result[3] * 256 + result[2])/10;
return resultArray;
}
}
}