📄 serialport.cs
字号:
//==========================================================================================
//
// OpenNETCF.IO.Ports.SerialPort
// Copyright (c) 2005, OpenNETCF.org
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the OpenNETCF.org Shared Source License.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the OpenNETCF.org Shared Source License
// for more details.
//
// You should have received a copy of the OpenNETCF.org Shared Source License
// along with this library; if not, email licensing@opennetcf.org to request a copy.
//
// If you wish to contact the OpenNETCF Advisory Board to discuss licensing, please
// email licensing@opennetcf.org.
//
// For general enquiries, email enquiries@opennetcf.org or visit our website at:
// http://www.opennetcf.org
//
//==========================================================================================
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Collections;
using System.Text;
using System.ComponentModel;
using OpenNETCF.IO.Serial;
namespace OpenNETCF.IO.Ports {
/// <summary>
/// Represents a serial port resource.
/// <para><b>New in v1.3</b></para>
/// </summary>
#if DESIGN
[ToolboxItemFilter("NETCF",ToolboxItemFilterType.Require),
ToolboxItemFilter("System.CF.Windows.Forms", ToolboxItemFilterType.Custom)]
#endif
public class SerialPort : Component, IDisposable
{
#region Events
public event SerialDataReceivedEventHandler DataReceived;
public event SerialErrorReceivedEventHandler ErrorReceived;
public event SerialPinChangedEventHandler PinChanged;
#endregion
#region Creation Destruction
/// <summary>
/// Not Currently Supported. Initializes a new instance of the <see cref="SerialPort"/> class using the <see cref="System.ComponentModel.IContainer"/> object specified.
/// </summary>
/// <param name="container">An interface to a container.</param>
public SerialPort(IContainer container) : this() {
// add designer support. Low priority as you can still create it in code
//container.Add(this);
throw new NotSupportedException("not yet");
}
/// <summary>
/// Initializes a new instance of the <see cref="SerialPort"/> class.
/// </summary>
public SerialPort(){
// create the API class based on the target
if (System.Environment.OSVersion.Platform != PlatformID.WinCE)
m_CommAPI = new WinCommAPI();
else
m_CommAPI = new CECommAPI();
// create a system event for synchronizing Closing
this.mCloseEvent = m_CommAPI.CreateEvent(true, false, CloseEventName);
}
/// <summary>
/// Initializes a new instance of the <see cref="SerialPort"/> class using the specified port name.
/// </summary>
/// <param name="portName">A string indicating the port to be used, for example, COM1.</param>
public SerialPort(string portName) : this(portName, 9600, Parity.None, 8, StopBits.One) {}
/// <summary>
/// Initializes a new instance of the <see cref="SerialPort"/> class using the specified port name, baud rate and parity bit.
/// </summary>
/// <param name="portName">A string indicating the port to be used, for example, COM1.</param>
/// <param name="baudRate">An integer indicating the baud rate.</param>
public SerialPort(string portName, int baudRate) : this(portName, baudRate, Parity.None, 8, StopBits.One) {}
/// <summary>
/// Initializes a new instance of the <see cref="SerialPort"/> class using the specified port name, baud rate and parity bit.
/// </summary>
/// <param name="portName">A string indicating the port to be used, for example, COM1.</param>
/// <param name="baudRate">An integer indicating the baud rate.</param>
/// <param name="parity">A value from the <see cref="Parity"/> enumeration.</param>
public SerialPort(string portName, int baudRate, Parity parity) : this(portName, baudRate, parity, 8, StopBits.One) {}
/// <summary>
/// Initializes a new instance of the <see cref="SerialPort"/> class using the specified port name, baud rate, parity bit and data bits.
/// </summary>
/// <param name="portName">A string indicating the port to be used, for example, COM1.</param>
/// <param name="baudRate">An integer indicating the baud rate.</param>
/// <param name="parity">A value from the <see cref="Parity"/> enumeration.</param>
/// <param name="dataBits">An integer indicating the data bits value.</param>
public SerialPort(string portName, int baudRate, Parity parity, int dataBits) : this(portName, baudRate, parity, dataBits, StopBits.One) {}
/// <summary>
/// Initializes a new instance of the <see cref="SerialPort"/> class using the specified port name, baud rate, parity bit, data bits and stop bit.
/// </summary>
/// <param name="portName">A string indicating the port to be used, for example, COM1.</param>
/// <param name="baudRate">An integer indicating the baud rate.</param>
/// <param name="parity">A value from the <see cref="Parity"/> enumeration.</param>
/// <param name="dataBits">An integer indicating the data bits value.</param>
/// <param name="stopBits">A value from the <see cref="StopBits"/> enumeration.</param>
public SerialPort(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits) : this() {
this.PortName = portName;
this.BaudRate = baudRate;
this.Parity = parity;
this.DataBits = dataBits;
this.StopBits = stopBits;
}
/// <summary>
/// Releases the unmanaged resources used by the <see cref="SerialPort"/> object.
/// </summary>
public void Dispose() {
if(this.mIsOpen)
this.Close();
//base.Dispose(true);
}
/// <summary>
/// Class destructor
/// </summary>
~SerialPort() {
if(this.mIsOpen)
this.Close();
}
#endregion
#region Private Fields
private Encoding mEncoding = Encoding.ASCII;
private Decoder mDecoder = Encoding.ASCII.GetDecoder();
private string mNewLine = @"\n";
private byte mByteSize = 8;
private bool mDiscardNull = false;
private Handshake mHandshake = Handshake.None;
private byte mErrorChar = 0x3f; //?
private StopBits mStopBits = StopBits.One;
private int mWriteTimeout = InfiniteTimeout;
private int mReadTimeout = InfiniteTimeout;
private int mRxBufferSize = 4096;
private int mTxBufferSize = 2048;
private int mRts = 0;
private int mRthreshold = 1;
private string mPortName = "COM1:";
private Parity mParity = Parity.None;
private bool mIsOpen = false;
private int mDtr = 1;
private bool mInBreak = false;
private int mBaudRate = 9600;
private IntPtr hPort = (IntPtr)CommAPI.INVALID_HANDLE_VALUE;
private DCB mDcb = new DCB();
private Thread mEventThread = null;
private ManualResetEvent mThreadStarted = new ManualResetEvent(false);
private IntPtr mCloseEvent;
private IntPtr mTxOverlapped = IntPtr.Zero;
private IntPtr mRxOverlapped = IntPtr.Zero;
private const string CloseEventName = "CloseEvent";
private CommAPI m_CommAPI = null;
private int mReadPos = 0;
private int mReadLen = 0;
private byte[] mInBuffer = new byte[1024];
#endregion
#region Public Properties
/// <summary>
/// Indicates that no timeout should occur.
/// </summary>
#if DESIGN
[Browsable(false)]
#endif
public const int InfiniteTimeout = -1;
/// <summary>
/// Gets the underlying System.IO.Stream object for a OpenNETCF.IO.Ports.SerialPort object.
/// </summary>
/// <returns>A System.IO.Stream object.</returns>
public System.IO.Stream BaseStream() {
// some day in the distant future someone else may want to consider providing this
throw new NotSupportedException("BaseStream Not supported");
}
/// <summary>
/// Gets or sets the value used to interpret the end of a call to the <see cref="ReadLine"/> and <see cref="WriteLine"/> methods.
/// </summary>
#if DESIGN
[Browsable(false)]
#endif
public string NewLine {
get {
return this.mNewLine;
}
set {
if (value == null) {
throw new ArgumentNullException();
}
if (value.Length == 0) {
throw new ArgumentException("NewLine cannot be empty");
}
this.mNewLine = value;
}
}
/// <summary>
/// Gets or sets the serial baud rate.
/// </summary>
/// <returns>An integer object representing the baud rate.</returns>
#if DESIGN
[DefaultValue(9600)]
#endif
public int BaudRate
{
get {
return this.mBaudRate;
}
set {
if (value <= 0) {
throw new ArgumentOutOfRangeException("BaudRate must be > 0");
}
this.mBaudRate = value;
if (this.IsOpen) {
this.UpdateSettings();
}
}
}
/// <summary>
/// Gets or sets the break signal state.
/// </summary>
/// <returns>true to enter a break state; otherwise false.</returns>
#if DESIGN
[Browsable(false)]
#endif
public bool BreakState
{
get {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
return this.mInBreak;
}
set {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
if (value) {
if (!m_CommAPI.EscapeCommFunction(hPort, CommEscapes.SETBREAK)) {
throw new ApplicationException("Failed to set break");
}
this.mInBreak = true;
}
else {
if (!m_CommAPI.EscapeCommFunction(hPort, CommEscapes.CLRBREAK)) {
throw new ApplicationException("Failed to clear break");
}
this.mInBreak = false;
}
}
}
/// <summary>
/// Gets the number of bytes of data in the receive buffer.
/// </summary>
/// <return>The number of bytes of data in the receive buffer.</return>
#if DESIGN
[Browsable(false)]
#endif
public int BytesToRead
{
get {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
CommErrorFlags errorFlags = new CommErrorFlags();
CommStat commStat = new CommStat();
if(!m_CommAPI.ClearCommError(hPort, ref errorFlags, commStat)) {
throw new ApplicationException("Failed to clear error/read");
}
return (int)commStat.cbInQue + (this.mReadLen - this.mReadPos);
}
}
/// <summary>
/// Gets the number of bytes of data in the send buffer.
/// </summary>
/// <return>The number of bytes of data in the send buffer.</return>
#if DESIGN
[Browsable(false)]
#endif
public int BytesToWrite {
get {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
CommErrorFlags errorFlags = new CommErrorFlags();
CommStat commStat = new CommStat();
if(!m_CommAPI.ClearCommError(hPort, ref errorFlags, commStat)) {
throw new ApplicationException("Failed to clear error/write");
}
return (int)commStat.cbOutQue;
}
}
/// <summary>
/// Gets the state of the Carrier Detect line for the port.
/// </summary>
/// <return>true if carrier is detected; otherwise false.</return>
#if DESIGN
[Browsable(false)]
#endif
public bool CDHolding
{
get {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
uint status = 0;
if (!m_CommAPI.GetCommModemStatus(hPort, ref status)) {
throw new ApplicationException("Failed to get CD");
}
return ((((uint)CommModemStatusFlags.MS_RLSD_ON) & status) != 0);
}
}
/// <summary>
/// Gets the state of the Clear-to-Send line.
/// </summary>
/// <return>true if Clear-to-Send detected; otherwise false.</return>
#if DESIGN
[Browsable(false)]
#endif
public bool CtsHolding
{
get {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
uint status = 0;
if (!m_CommAPI.GetCommModemStatus(hPort, ref status)) {
throw new ApplicationException("Failed to get CTS");
}
return ((((uint)CommModemStatusFlags.MS_CTS_ON) & status) != 0);
}
}
/// <summary>
/// Gets or sets the standard length of data bits per byte.
/// </summary>
/// <return>An integer object specifying the data bits length.</return>
#if DESIGN
[DefaultValue(8)]
#endif
public int DataBits
{
get {
return this.mByteSize;
}
set {
if ((value < 5) || (value > 8)) {
throw new ArgumentOutOfRangeException("DataBits must be >=5 <=8");
}
this.mByteSize = (byte)value;
if (this.IsOpen) {
this.UpdateSettings();
}
}
}
/// <summary>
/// Gets or sets whether null bytes are ignored when transmitted between the port and the receive buffer.
/// </summary>
/// <return>true if null bytes are ignored; otherwise false. The default value for this property is false.</return>
#if DESIGN
[DefaultValue(false)]
#endif
public bool DiscardNull
{
get {
return this.mDiscardNull;
}
set {
this.mDiscardNull = value;
if (this.IsOpen) {
this.UpdateSettings();
}
}
}
/// <summary>
/// Gets the state of the Data Set Ready (DSR) signal.
/// </summary>
/// <return>true if a Data Set Ready signal has been sent to the port; otherwise false.</return>
#if DESIGN
[Browsable(false)]
#endif
public bool DsrHolding
{
get {
if (!this.IsOpen) {
throw new InvalidOperationException("Port is not open");
}
uint status = 0;
if (!m_CommAPI.GetCommModemStatus(hPort, ref status)) {
throw new ApplicationException("Failed to get DSR");
}
return ((((uint)CommModemStatusFlags.MS_DSR_ON) & status) != 0);
}
}
/// <summary>
/// Gets or sets enabling of the Data Terminal Ready (DTR) signal during serial communication.
/// </summary>
/// <return>true to enable DTR, otherwise false.</return>
#if DESIGN
[DefaultValue(false)]
#endif
public bool DtrEnable {
get
{
return (this.mDtr == 1);
}
set {
if (value){
this.mDtr = 1;
}else{
this.mDtr = 0;
}
if (this.IsOpen){
this.UpdateSettings();
if (!m_CommAPI.EscapeCommFunction(hPort, ((this.mDtr == 1) ? CommEscapes.SETDTR : CommEscapes.CLRDTR))){
throw new ApplicationException("Failed to set/clear DTR!");
}
}
}
}
/// <summary>
/// Gets or sets the handshaking protocol for serial port transmission of data.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -