我想知道你们对我的串行包装器类有什么看法。已经有一段时间了,我一直在使用串口,但从来没有分享过代码,这让我对自己的愿景关闭了。
我想知道这是不是一个好的/不好的方法,界面是否足够,以及你在上面看到了什么。
我知道Stackoverflow是有问题的,但与此同时,这里有很多非常优秀的技术人员,分享代码和观点也可以让每个人受益,这就是为什么我决定无论如何都要发布它。
谢谢!
using System.Text;
using System.IO;
using System.IO.Ports;
using System;
namespace Driver
{
class SerialSingleton
{
// The singleton instance reference
private static SerialSingleton instance = null;
// System's serial port interface
private SerialPort serial;
// Current com port identifier
private string comPort = null;
// Configuration parameters
private int confBaudRate;
private int confDataBits;
private StopBits confStopBits;
private Parity confParityControl;
ASCIIEncoding encoding = new ASCIIEncoding();
// ==================================================================================
// Constructors
public static SerialSingleton getInstance()
{
if (instance == null)
{
instance = new SerialSingleton();
}
return instance;
}
private SerialSingleton()
{
serial = new SerialPort();
}
// ===================================================================================
// Setup Methods
public string ComPort
{
get { return comPort; }
set {
if (value == null)
{
throw new SerialException("Serial port name canot be null.");
}
if (nameIsComm(value))
{
close();
comPort = value;
}
else
{
throw new SerialException("Serial Port '" + value + "' is not a valid com port.");
}
}
}
public void setSerial(string baudRate, int dataBits, StopBits stopBits, Parity parityControl)
{
if (baudRate == null)
{
throw new SerialException("Baud rate cannot be null");
}
string[] baudRateRef = { "300", "600", "1200", "1800", "2400", "3600", "4800", "7200", "9600", "14400", "19200", "28800", "38400", "57600", "115200" };
int confBaudRate;
if (findString(baudRateRef, baudRate) != -1)
{
confBaudRate = System.Convert.ToInt32(baudRate);
}
else
{
throw new SerialException("Baurate parameter invalid.");
}
int confDataBits;
switch (dataBits)
{
case 5:
confDataBits = 5;
break;
case 6:
confDataBits = 6;
break;
case 7:
confDataBits = 7;
break;
case 8:
confDataBits = 8;
break;
default:
throw new SerialException("Databits parameter invalid");
}
if (stopBits == StopBits.None)
{
throw new SerialException("StopBits parameter cannot be NONE");
}
this.confBaudRate = confBaudRate;
this.confDataBits = confDataBits;
this.confStopBits = stopBits;
this.confParityControl = parityControl;
}
// ==================================================================================
public string[] PortList
{
get {
return SerialPort.GetPortNames();
}
}
public int PortCount
{
get { return SerialPort.GetPortNames().Length; }
}
// ==================================================================================
// Open/Close Methods
public void open()
{
open(comPort);
}
private void open(string comPort)
{
if (isOpen())
{
throw new SerialException("Serial Port is Already open");
}
else
{
if (comPort == null)
{
throw new SerialException("Serial Port not defined. Cannot open");
}
bool found = false;
if (nameIsComm(comPort))
{
string portId;
string[] portList = SerialPort.GetPortNames();
for (int i = 0; i < portList.Length; i++)
{
portId = (portList[i]);
if (portId.Equals(comPort))
{
found = true;
break;
}
}
}
else
{
throw new SerialException("The com port identifier '" + comPort + "' is not a valid serial port identifier");
}
if (!found)
{
throw new SerialException("Serial port '" + comPort + "' not found");
}
serial.PortName = comPort;
try
{
serial.Open();
}
catch (UnauthorizedAccessException uaex)
{
throw new SerialException("Cannot open a serial port in use by another application", uaex);
}
try
{
serial.BaudRate = confBaudRate;
serial.DataBits = confDataBits;
serial.Parity = confParityControl;
serial.StopBits = confStopBits;
}
catch (Exception e)
{
throw new SerialException("Serial port parameter invalid for '" + comPort + "'.\n" + e.Message, e);
}
}
}
public void close()
{
if (serial.IsOpen)
{
serial.Close();
}
}
// ===================================================================================
// Auxiliary private Methods
private int findString(string[] set, string search)
{
if (set != null)
{
for (int i = 0; i < set.Length; i++)
{
if (set[i].Equals(search))
{
return i;
}
}
}
return -1;
}
private bool nameIsComm(string name)
{
int comNumber;
int.TryParse(name.Substring(3), out comNumber);
if (name.Substring(0, 3).Equals("COM"))
{
if (comNumber > -1 && comNumber < 256)
{
return true;
}
}
return false;
}
// =================================================================================
// Device state Methods
public bool isOpen()
{
return serial.IsOpen;
}
public bool hasData()
{
int amount = serial.BytesToRead;
if (amount > 0)
{
return true;
}
else
{
return false;
}
}
// ==================================================================================
// Input Methods
public char getChar()
{
int data = serial.ReadByte();
return (char)data;
}
public int getBytes(ref byte[] b)
{
int size = b.Length;
char c;
int counter = 0;
for (counter = 0; counter < size; counter++)
{
if (tryGetChar(out c))
{
b[counter] = (byte)c;
}
else
{
break;
}
}
return counter;
}
public string getStringUntil(char x)
{
char c;
string response = "";
while (tryGetChar(out c))
{
response = response + c;
if (c == x)
{
break;
}
}
return response;
}
public bool tryGetChar(out char c)
{
c = (char)0x00;
byte[] b = new byte[1];
long to = 10;
long ft = System.Environment.TickCount + to;
while (System.Environment.TickCount < ft)
{
if (hasData())
{
int data = serial.ReadByte();
c = (char)data;
return true;
}
}
return false;
}
// ================================================================================
// Output Methods
public void sendString(string data)
{
byte[] bytes = encoding.GetBytes(data);
serial.Write(bytes, 0, bytes.Length);
}
public void sendChar(char c)
{
char[] data = new char[1];
data[0] = c;
serial.Write(data, 0, 1);
}
public void sendBytes(byte[] data)
{
serial.Write(data, 0, data.Length);
}
public void clearBuffer()
{
if (serial.IsOpen)
{
serial.DiscardInBuffer();
serial.DiscardOutBuffer();
}
}
}
}发布于 2010-05-10 11:13:00
我假设您有一个应用程序需要像其他应用程序使用stdin/stdout一样访问串行端口。如果不是这样的话,你应该重新考虑使用单例。
如果串行端口已经打开,
setSerial方法不会做任何有用的事情。它应该抛出一个异常,更改打开的端口的设置,或者关闭端口并使用新的settings.getInstance,isOpen重新打开它,并且hasData应该是只读属性而不是method.tryGetChar sendChar,并且sendBytes可以是所有不同重载的send methods.sendString,有一个繁忙的循环。这是非常糟糕的。使用ReadTimeout或让读取线程等待具有超时的事件,然后从DataReceived处理程序向该事件发送信号。发布于 2010-05-10 09:48:57
有几件事浮出水面:
,
baudRate,baudRate,并立即将其转换为数字。为什么不使用if (confDataBits < 5 || confDataBits > 8) //exception,使用switch(dataBits)来检查整数parameter.
一般来说,您添加的额外功能对我使用串行端口所做的工作没有太大帮助,但您的场景可能与我的不同。您添加的方法似乎忽略了我认为使用SerialPort较难的部分,即异步发送和接收。您拥有的所有输入方法都是同步的,因此调用它们会导致线程阻塞,直到有足够的数据进入。
发布于 2010-05-10 09:41:18
以下是一些(非详尽的)初步观察
已经有了例外,
https://stackoverflow.com/questions/2799856
复制相似问题