C#串口驱动包装类代码及概念质量
想知道大家对我的 Serial Wrapper 类有何看法。我已经有一段时间使用串行端口了,但从未分享过代码,这让我对自己的愿景感到封闭。
想知道这是否是一个好/坏的方法,界面是否足够以及您还可以看到什么。
我知道 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();
}
}
}
}
Would like to know from all you guys what do you think about my Serial Wrapper class. Had been a while I've been working with serial ports but never shared the code what somekind make me closed to my very own vision.
Would like to know if it's a good/bad approach, if the interface is enough and what more you see on it.
I know that Stackoverflow is for question but at the same time there's a lot of very good skilled people here and share code and opinion can also benefit everybody, it's why I decided to post it anyway.
thanks!
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();
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
有几件事显而易见:
baudRate
作为字符串并立即将其转换为数字。为什么不只采用整数参数。switch(dataBits)
来检查它是否在一个范围内,为什么不使用if (confDataBits < 5 || confDataBits > 8) //exception
In一般来说,您添加的额外功能对于我使用串行端口所做的事情不会有太大帮助,但您的场景可能与我的不同。您添加的方法似乎忽略了我认为使用串行端口的困难部分,即异步发送和接收。您拥有的所有输入方法都是同步的,因此调用它们将导致线程阻塞,直到有足够的数据进入。
A few things jump out:
baudRate
as a string and immediately convert it to a number. Why not just take an integer parameter.switch(dataBits)
to check if it is in a range, why notif (confDataBits < 5 || confDataBits > 8) //exception
In general, the extra functionality you added would not be too helpful for what I do with serial ports, but your scenarios are probably different then mine. The methods you added seem to ignore what I consider the harder part of using a SerialPort, the asynchronous sending and receiving. All of the input methods you have are synchronous, so calling them will cause the thread to block until enough data comes in.
我假设您有一个应用程序需要像其他应用程序使用标准输入/标准输出一样访问串行端口。如果情况并非如此,您应该重新考虑为此使用单例。
如果串行端口已打开,则
setSerial
方法不会执行任何有用的操作。 抛出异常,更改打开端口的设置,或者关闭端口并使用新设置重新打开它。getInstance
、isOpen
和hasData
可能应该是只读属性而不是方法。sendString
、sendChar
和sendBytes
都可以是send
方法的不同重载。tryGetChar
有一个繁忙的循环。这非常糟糕。使用ReadTimeout
或让读取线程等待超时事件,并从DataReceived
处理程序发出该事件信号。您应该考虑拥有发送超时机制。
I'm assuming that you have an app that needs to access a serial port the way other apps use stdin/stdout. If that's not the case, you should reconsider your use of a singleton for this.
The
setSerial
method doesn't do anything useful if the serial port is already open. It should throw an exception, change the settings of the open port, or close the port and reopen it with new settings.getInstance
,isOpen
, andhasData
should probably be read-only properties rather than methods.sendString
,sendChar
, andsendBytes
could all be different overloads of asend
method.tryGetChar
has a busy loop. That's very bad. Either useReadTimeout
or have the reading thread wait on an event with a timeout and signal the event from aDataReceived
handler.You should consider having a send timeout mechanism.
这是一些(非详尽的)初步观察
Here's some (non exhaustive) initial observations
阅读 http://www.codeproject.com/Tips/353650/Enhanced-Serial-端口
Read http://www.codeproject.com/Tips/353650/Enhanced-Serial-Port