|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.Linq;
|
|
|
using System.Text;
|
|
|
using System.IO.Ports;
|
|
|
|
|
|
namespace Mesnac.Equip.OMRON.HostLink
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 串口工厂类
|
|
|
/// </summary>
|
|
|
public class SerialPortFactory
|
|
|
{
|
|
|
#region 单例实现
|
|
|
|
|
|
private static SerialPortFactory _instance = null; //串口工厂实例
|
|
|
private SerialPort _mainSerialPort = null; //主串口对象
|
|
|
private string _recivedResultMsg = String.Empty; //串口接收结果字符串
|
|
|
private string _lastRecivedMsg = String.Empty; //保存最后一次接收的完整信息
|
|
|
|
|
|
private string _stationNum = "00"; //站号
|
|
|
private string _portName = "COM1"; //端口号
|
|
|
private int _baudRate = 9600; //波特率
|
|
|
private Parity _parity = Parity.Even; //校验位
|
|
|
private int _dataBits = 7; //数据位
|
|
|
private StopBits _stopBits = StopBits.Two; //停止位
|
|
|
private int _buffSize = 1024; //缓冲区大小
|
|
|
|
|
|
private SerialPortFactory(string stationNum, string portName, int baudRate, string parity, int dataBits, string stopBits, int buffSize)
|
|
|
{
|
|
|
this._stationNum = stationNum;
|
|
|
this._portName = portName;
|
|
|
this._baudRate = baudRate;
|
|
|
this._parity = ConvertToParity(parity);
|
|
|
this._dataBits = dataBits;
|
|
|
this._stopBits = ConvertToStopBits(stopBits);
|
|
|
this._buffSize = buffSize;
|
|
|
|
|
|
this._mainSerialPort = new SerialPort();
|
|
|
this._mainSerialPort.PortName = this._portName;
|
|
|
this._mainSerialPort.BaudRate = this._baudRate;
|
|
|
this._mainSerialPort.Parity = this._parity;
|
|
|
this._mainSerialPort.DataBits = this._dataBits;
|
|
|
this._mainSerialPort.StopBits = this._stopBits;
|
|
|
this._mainSerialPort.ReadBufferSize = this._buffSize;
|
|
|
this._mainSerialPort.WriteBufferSize = this._buffSize;
|
|
|
this._mainSerialPort.ReceivedBytesThreshold = 1;
|
|
|
this._mainSerialPort.Handshake = Handshake.None;
|
|
|
//this._mainSerialPort.DataReceived += new SerialDataReceivedEventHandler(_mainSerialPort_DataReceived);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 获取串口工厂实例
|
|
|
/// </summary>
|
|
|
/// <param name="stationNum">站号</param>
|
|
|
/// <param name="portName">端口号</param>
|
|
|
/// <param name="baudRate">波特率</param>
|
|
|
/// <param name="parity">校验位</param>
|
|
|
/// <param name="dataBits">数据位</param>
|
|
|
/// <param name="stopBits">停止位</param>
|
|
|
/// <param name="buffSize">缓冲区大小</param>
|
|
|
/// <returns>返回串口工厂实例</returns>
|
|
|
public static SerialPortFactory GetInstance(string stationNum, string portName, int baudRate, string parity, int dataBits, string stopBits, int buffSize)
|
|
|
{
|
|
|
if (_instance == null)
|
|
|
{
|
|
|
_instance = new SerialPortFactory(stationNum, portName, baudRate, parity, dataBits, stopBits, buffSize);
|
|
|
|
|
|
}
|
|
|
return _instance;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 主串口对象
|
|
|
/// </summary>
|
|
|
public SerialPort MainSerialPort
|
|
|
{
|
|
|
get
|
|
|
{
|
|
|
return this._mainSerialPort;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 最后一次接收的完整信息
|
|
|
/// </summary>
|
|
|
public string RecivedResultMsg
|
|
|
{
|
|
|
get { return _recivedResultMsg; }
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 从串口读取数据
|
|
|
/// <summary>
|
|
|
/// 从串口读取数据
|
|
|
/// </summary>
|
|
|
/// <param name="block">块号</param>
|
|
|
/// <param name="start">起始地址</param>
|
|
|
/// <param name="len">长度</param>
|
|
|
/// <param name="buff">数据缓冲区</param>
|
|
|
/// <returns>返回结果吗</returns>
|
|
|
public string Read(int block, int start, int len, out int[] buff)
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
if (this._mainSerialPort.IsOpen)
|
|
|
{
|
|
|
this._mainSerialPort.DiscardOutBuffer();
|
|
|
start = block + start;
|
|
|
string WriteBit = String.Format("@{0}RD{1}", this._stationNum, this.FillZero(start.ToString(), 4));
|
|
|
WriteBit += this.FillZero(len.ToString(), 4);
|
|
|
this._mainSerialPort.Write(FCS(WriteBit));
|
|
|
System.Threading.Thread.Sleep(2);
|
|
|
|
|
|
string temp1 = this._mainSerialPort.ReadExisting();
|
|
|
this._mainSerialPort.DiscardOutBuffer();
|
|
|
this._recivedResultMsg += temp1;
|
|
|
while (String.IsNullOrEmpty(temp1) || temp1.Substring(temp1.Length - 1, 1) != "\r")
|
|
|
{
|
|
|
temp1 = this._mainSerialPort.ReadExisting();
|
|
|
this._recivedResultMsg += temp1;
|
|
|
this._mainSerialPort.DiscardOutBuffer();
|
|
|
System.Threading.Thread.Sleep(2);
|
|
|
}
|
|
|
|
|
|
this._lastRecivedMsg = this._recivedResultMsg;
|
|
|
this._recivedResultMsg = String.Empty;
|
|
|
|
|
|
if (String.IsNullOrEmpty(this._recivedResultMsg) && !String.IsNullOrEmpty(this._lastRecivedMsg))
|
|
|
{
|
|
|
buff = new int[len];
|
|
|
for (int i = 0; i < len; i++)
|
|
|
{
|
|
|
if (this._lastRecivedMsg.Length > 7 + i * 4)
|
|
|
{
|
|
|
string temp = ToDEC(this._lastRecivedMsg.Substring(7 + i * 4, 4));//this.HEX2DEC(
|
|
|
buff[i] = 0;
|
|
|
if ((block >= 3016 && block <= 3023) || block==3005)
|
|
|
{
|
|
|
int.TryParse(this.HEX2DEC(temp),out buff[i]);
|
|
|
}
|
|
|
else
|
|
|
int.TryParse(temp, out buff[i]);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
return GetReturnCode(this._lastRecivedMsg);
|
|
|
}
|
|
|
buff = new int[] { 0 };
|
|
|
return String.Empty;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
buff = new int[] { 0 };
|
|
|
return "COM is Not Open!";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 向串口写数据
|
|
|
/// <summary>
|
|
|
/// 向串口写数据
|
|
|
/// </summary>
|
|
|
/// <param name="block">块号</param>
|
|
|
/// <param name="start">起始地址</param>
|
|
|
/// <param name="buff">要写入的数</param>
|
|
|
/// <returns>返回结果码</returns>
|
|
|
public string Write(int block, int start, int[] buff)
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
if (this._mainSerialPort.IsOpen)
|
|
|
{
|
|
|
this._mainSerialPort.DiscardOutBuffer();
|
|
|
//string WriteBit = null;
|
|
|
//WriteBit = "@00WD0000" + DEC2HEX(TextBox_DEC.Text);
|
|
|
start = block + start;
|
|
|
string WriteBit = String.Format("@{0}WD{1}", this._stationNum, this.FillZero(start.ToString(), 4));
|
|
|
for (int i = 0; i < buff.Length; i++)
|
|
|
{
|
|
|
WriteBit += DectoBCD(buff[i].ToString());//DEC2HEX(
|
|
|
}
|
|
|
this._mainSerialPort.Write(FCS(WriteBit));
|
|
|
System.Threading.Thread.Sleep(2);
|
|
|
|
|
|
string temp1 = this._mainSerialPort.ReadExisting();
|
|
|
this._mainSerialPort.DiscardOutBuffer();
|
|
|
this._recivedResultMsg += temp1;
|
|
|
while (String.IsNullOrEmpty(temp1) || temp1.Substring(temp1.Length - 1, 1) != "\r")
|
|
|
{
|
|
|
temp1 = this._mainSerialPort.ReadExisting();
|
|
|
this._recivedResultMsg += temp1;
|
|
|
this._mainSerialPort.DiscardOutBuffer();
|
|
|
System.Threading.Thread.Sleep(1);
|
|
|
}
|
|
|
|
|
|
this._lastRecivedMsg = this._recivedResultMsg;
|
|
|
this._recivedResultMsg = String.Empty;
|
|
|
|
|
|
return GetReturnCode(this._lastRecivedMsg);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return "COM is Not Open!";
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 辅助方法
|
|
|
|
|
|
#region 获取响应码
|
|
|
/// <summary>
|
|
|
/// 获取响应码
|
|
|
/// </summary>
|
|
|
/// <param name="responseStr">响应字符串</param>
|
|
|
/// <returns>获取响应码</returns>
|
|
|
public string GetReturnCode(string responseStr)
|
|
|
{
|
|
|
if (!String.IsNullOrEmpty(responseStr) && responseStr.Length >= 7)
|
|
|
{
|
|
|
return responseStr.Substring(5, 2);
|
|
|
}
|
|
|
return String.Empty;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region "按字符串位数补0"
|
|
|
|
|
|
/// <summary>
|
|
|
/// 按字符串位数补0
|
|
|
/// </summary>
|
|
|
/// <param name="CharTxt">字符串</param>
|
|
|
/// <param name="CharLen">字符长度</param>
|
|
|
/// <returns></returns>
|
|
|
public string FillZero(string CharTxt, int CharLen)
|
|
|
{
|
|
|
if (CharTxt.Length < CharLen)
|
|
|
{
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
for (int i = 0; i < CharLen - CharTxt.Length; i++)
|
|
|
{
|
|
|
sb.Append("0");
|
|
|
}
|
|
|
sb.Append(CharTxt);
|
|
|
return sb.ToString();
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return CharTxt;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 对指令及数据的字符串进行最终FCS运算,并添加“*CR”
|
|
|
/// <summary>
|
|
|
/// 对指令及数据的字符串进行最终FCS运算,并添加“*CR”
|
|
|
/// </summary>
|
|
|
/// <param name="Str">要进行FCS运算的字符串</param>
|
|
|
/// <returns>返回经过FCS运算后的结果</returns>
|
|
|
public string FCS(string Str) //对指令及数据的字符串进行最终FCS运算,并添加“*CR”
|
|
|
{
|
|
|
char[] chararraytemp = Str.ToCharArray();
|
|
|
int fcs = 0;
|
|
|
foreach (char chartemp in chararraytemp)
|
|
|
{
|
|
|
fcs = fcs ^ Convert.ToInt16(chartemp); //对字符进行ASC转换,并进行异或运算
|
|
|
}
|
|
|
string fcstohex = String.Format("{0:X2}", (uint)System.Convert.ToUInt32(fcs));
|
|
|
string result = Str + fcstohex + "*" + Convert.ToChar(13);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 十进制转十六进制
|
|
|
|
|
|
/// <summary>
|
|
|
/// 十进制转十六进制
|
|
|
/// </summary>
|
|
|
/// <param name="ox">十进制字符串</param>
|
|
|
/// <returns>返回对应的十六进制字符串</returns>
|
|
|
public string DEC2HEX(string ox)
|
|
|
{
|
|
|
uint ux = 0;
|
|
|
if (uint.TryParse(ox, out ux))
|
|
|
{
|
|
|
string strHex = String.Format("{0:X4}", ux); //转换为16禁止,{0:X4}大写4位;{0:x4}小写4位
|
|
|
return strHex;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
return ox;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 十六进制转十进制
|
|
|
/// <summary>
|
|
|
/// 十六进制转十进制
|
|
|
/// </summary>
|
|
|
/// <param name="ox">十六进制字符串</param>
|
|
|
/// <returns>返回对应的十进制字符串</returns>
|
|
|
public string HEX2DEC(string ox)
|
|
|
{
|
|
|
uint test;
|
|
|
test = System.Convert.ToUInt32(ox, 16); //转换为10禁止
|
|
|
return test.ToString();
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 类型转换
|
|
|
|
|
|
/// <summary>
|
|
|
/// 校验位类型转换
|
|
|
/// </summary>
|
|
|
/// <param name="strParity"></param>
|
|
|
/// <returns></returns>
|
|
|
private Parity ConvertToParity(string strParity)
|
|
|
{
|
|
|
Parity result = Parity.None;
|
|
|
switch (strParity)
|
|
|
{
|
|
|
case "None":
|
|
|
result = Parity.None;
|
|
|
break;
|
|
|
case "Odd":
|
|
|
result = Parity.Odd;
|
|
|
break;
|
|
|
case "Even":
|
|
|
result = Parity.Even;
|
|
|
break;
|
|
|
case "Mark":
|
|
|
result = Parity.Mark;
|
|
|
break;
|
|
|
case "Space":
|
|
|
result = Parity.Space;
|
|
|
break;
|
|
|
default:
|
|
|
result = Parity.None;
|
|
|
break;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 停止位类型转换
|
|
|
/// </summary>
|
|
|
/// <param name="strStopBits"></param>
|
|
|
/// <returns></returns>
|
|
|
private StopBits ConvertToStopBits(string strStopBits)
|
|
|
{
|
|
|
StopBits result = StopBits.None;
|
|
|
switch (strStopBits)
|
|
|
{
|
|
|
case "None":
|
|
|
result = StopBits.None;
|
|
|
break;
|
|
|
case "1":
|
|
|
result = StopBits.One;
|
|
|
break;
|
|
|
case "1.5":
|
|
|
result = StopBits.OnePointFive;
|
|
|
break;
|
|
|
case "2":
|
|
|
result = StopBits.Two;
|
|
|
break;
|
|
|
default:
|
|
|
result = StopBits.None;
|
|
|
break;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
string DectoBCD(string Dec)
|
|
|
{
|
|
|
//if (Dec.Length > 4)
|
|
|
//{
|
|
|
// return DEC2HEX(Dec);
|
|
|
//}
|
|
|
//else
|
|
|
//{
|
|
|
// string retValue = string.Empty;
|
|
|
// for (int j = 0; j < Dec.Length; j++)
|
|
|
// {
|
|
|
// string bv = string.Empty;
|
|
|
|
|
|
// int[] bitValue = ParseBinaryValue(Convert.ToInt32(Dec.Substring(Dec.Length - 1 - j, 1)), 4);
|
|
|
// for (int i = 0; i < 4; i++)
|
|
|
// {
|
|
|
// bv += bitValue[i];
|
|
|
// }
|
|
|
// retValue = GetValues(bv)[0] + retValue;
|
|
|
// }
|
|
|
// return retValue.PadLeft(4, '0');
|
|
|
//}
|
|
|
return Dec.PadLeft(4, '0');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// 解析二进制位
|
|
|
/// </summary>
|
|
|
/// <param name="x">要解析的变量</param>
|
|
|
/// <param name="len">解析的长度</param>
|
|
|
/// <returns>返回解析的二进制值数组</returns>
|
|
|
public int[] ParseBinaryValue(int x, int len)
|
|
|
{
|
|
|
int[] result = new int[len];
|
|
|
int b = 1;
|
|
|
for (int i = len - 1; i >= 0; i--)
|
|
|
{
|
|
|
result[i] = (x & b) == 0 ? 0 : 1;
|
|
|
b = b << 1;
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 二进制转化为十进制
|
|
|
/// </summary>
|
|
|
/// <param name="valvestates"></param>
|
|
|
/// <param name="toBase"></param>
|
|
|
/// <returns></returns>
|
|
|
public object[] GetValues(string valvestates)
|
|
|
{
|
|
|
object[] returnvalue = { Convert.ToInt32(valvestates, 2) };
|
|
|
return returnvalue;
|
|
|
}
|
|
|
|
|
|
public string ToDEC(string ox)
|
|
|
{
|
|
|
//int dec = Convert.ToInt32(ox, 16);
|
|
|
//if (dec.ToString().Length > 4)
|
|
|
// return dec.ToString();
|
|
|
//else
|
|
|
return ox;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#endregion
|
|
|
}
|
|
|
}
|