You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

456 lines
16 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}
}