⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commbase.cs

📁 C#串口编程。详细讲解
💻 CS
📖 第 1 页 / 共 4 页
字号:
				//JH 1.1: Avoid use of GetHandleInformation for W98 compatability.
				if (hPort != (System.IntPtr)Win32Com.INVALID_HANDLE_VALUE) return true;
				ThrowException("Offline");
				return false;
			}
			else
			{
				if (auto) 
				{
					if (Open()) return true;
				}
				ThrowException("Offline");
				return false;
			}
		}

	}

	/// <summary>
	/// Overlays CommBase to provide line or packet oriented communications to derived classes. Strings
	/// are sent and received and the Transact method is added which transmits a string and then blocks until
	/// a reply string has been received (subject to a timeout).
	/// </summary>
	public abstract class CommLine : CommBase {
		private byte[] RxBuffer;
		private uint RxBufferP = 0;
		private ASCII RxTerm;
		private ASCII[] TxTerm;
		private ASCII[] RxFilter;
		private string RxString = "";
		private ManualResetEvent TransFlag = new ManualResetEvent(true);
		private uint TransTimeout;

		/// <summary>
		/// Extends CommBaseSettings to add the settings used by CommLine.
		/// </summary>
		public class CommLineSettings : CommBase.CommBaseSettings 
		{
			/// <summary>
			/// Maximum size of received string (default: 256)
			/// </summary>
			public int rxStringBufferSize = 256;
			/// <summary>
			/// ASCII code that terminates a received string (default: CR)
			/// </summary>
			public ASCII rxTerminator = ASCII.CR;
			/// <summary>
			/// ASCII codes that will be ignored in received string (default: null)
			/// </summary>
			public ASCII[] rxFilter;
			/// <summary>
			/// Maximum time (ms) for the Transact method to complete (default: 500)
			/// </summary>
			public int transactTimeout = 500;
			/// <summary>
			/// ASCII codes transmitted after each Send string (default: null)
			/// </summary>
			public ASCII[] txTerminator;

			public static new CommLineSettings LoadFromXML(Stream s)
			{
				return (CommLineSettings)LoadFromXML(s, typeof(CommLineSettings));
			}
		}
	
		/// <summary>
		/// Queue the ASCII representation of a string and then the set terminator bytes for sending.
		/// </summary>
		/// <param name="toSend">String to be sent.</param>
		protected void Send(string toSend) 
		{
			//JH 1.1: Use static encoder for efficiency. Thanks to Prof. Dr. Peter Jesorsky!
			uint l = (uint)Encoding.ASCII.GetByteCount(toSend);
			if (TxTerm != null) l += (uint)TxTerm.GetLength(0);
			byte[] b = new byte[l];
			byte[] s = Encoding.ASCII.GetBytes(toSend);
			int i;
			for (i = 0; (i <= s.GetUpperBound(0)); i++) b[i] = s[i];
			if (TxTerm != null) for (int j = 0; (j <= TxTerm.GetUpperBound(0)); j++, i++) b[i] = (byte)TxTerm[j];
			Send(b);
		}

		/// <summary>
		/// Transmits the ASCII representation of a string followed by the set terminator bytes and then
		/// awaits a response string.
		/// </summary>
		/// <param name="toSend">The string to be sent.</param>
		/// <returns>The response string.</returns>
		protected string Transact(string toSend) {
			Send(toSend);
			TransFlag.Reset();
			if (!TransFlag.WaitOne((int)TransTimeout, false)) ThrowException("Timeout");
			string s;
			lock(RxString) {s = RxString;}
			return s;
		}
		
		/// <summary>
		/// If a derived class overrides ComSettings(), it must call this prior to returning the settings to
		/// the base class.
		/// </summary>
		/// <param name="s">Class containing the appropriate settings.</param>
		protected void Setup(CommLineSettings s) {
			RxBuffer = new byte[s.rxStringBufferSize];
			RxTerm = s.rxTerminator;
			RxFilter = s.rxFilter;
			TransTimeout = (uint)s.transactTimeout;
			TxTerm = s.txTerminator;
		}

		/// <summary>
		/// Override this to process unsolicited input lines (not a result of Transact).
		/// </summary>
		/// <param name="s">String containing the received ASCII text.</param>
		protected virtual void OnRxLine(string s) {}

		protected override void OnRxChar(byte ch) {
			ASCII ca = (ASCII)ch;
			if ((ca == RxTerm) || (RxBufferP > RxBuffer.GetUpperBound(0))) {
				//JH 1.1: Use static encoder for efficiency. Thanks to Prof. Dr. Peter Jesorsky!
				lock(RxString) {RxString = Encoding.ASCII.GetString(RxBuffer, 0, (int)RxBufferP);}
				RxBufferP = 0;
				if (TransFlag.WaitOne(0,false)) {
					OnRxLine(RxString);
				} else {
					TransFlag.Set();
				}
			} else {
				bool wr = true;
				if (RxFilter != null) {
					for (int i=0; i <= RxFilter.GetUpperBound(0); i++) if (RxFilter[i] == ca) wr = false;
				}
				if (wr) {
					RxBuffer[RxBufferP] = ch;
					RxBufferP++;
				}
			}
		}
	}

	/// <summary>
	/// Exception used for all errors.
	/// </summary>
	public class CommPortException : ApplicationException
	{
		/// <summary>
		/// Constructor for raising direct exceptions
		/// </summary>
		/// <param name="desc">Description of error</param>
		public CommPortException(string desc) : base(desc) {}

		/// <summary>
		/// Constructor for re-raising exceptions from receive thread
		/// </summary>
		/// <param name="e">Inner exception raised on receive thread</param>
		public CommPortException(Exception e) : base("Receive Thread Exception", e) {}
	}

	internal class Win32Com {

		/// <summary>
		/// Opening Testing and Closing the Port Handle.
		/// </summary>
		[DllImport("kernel32.dll", SetLastError=true)]
		internal static extern IntPtr CreateFile(String lpFileName, UInt32 dwDesiredAccess, UInt32 dwShareMode,
			IntPtr lpSecurityAttributes, UInt32 dwCreationDisposition, UInt32 dwFlagsAndAttributes,
			IntPtr hTemplateFile);

		//Constants for errors:
			internal const UInt32 ERROR_FILE_NOT_FOUND = 2;
			internal const UInt32 ERROR_INVALID_NAME = 123;
			internal const UInt32 ERROR_ACCESS_DENIED = 5;
			internal const UInt32 ERROR_IO_PENDING = 997;
			internal const UInt32 ERROR_IO_INCOMPLETE = 996;

		//Constants for return value:
			internal const Int32 INVALID_HANDLE_VALUE = -1;

		//Constants for dwFlagsAndAttributes:
			internal const UInt32 FILE_FLAG_OVERLAPPED = 0x40000000;

		//Constants for dwCreationDisposition:
			internal const UInt32 OPEN_EXISTING = 3;

		//Constants for dwDesiredAccess:
			internal const UInt32 GENERIC_READ = 0x80000000;
			internal const UInt32 GENERIC_WRITE = 0x40000000;

		[DllImport("kernel32.dll")]
		internal static extern Boolean CloseHandle(IntPtr hObject);

		/// <summary>
		/// Manipulating the communications settings.
		/// </summary>

		[DllImport("kernel32.dll")]
		internal static extern Boolean GetCommState(IntPtr hFile, ref DCB lpDCB);

		[DllImport("kernel32.dll")]
		internal static extern Boolean GetCommTimeouts(IntPtr hFile, out COMMTIMEOUTS lpCommTimeouts);

		[DllImport("kernel32.dll")]
		internal static extern Boolean BuildCommDCBAndTimeouts(String lpDef, ref DCB lpDCB, ref COMMTIMEOUTS lpCommTimeouts);

		[DllImport("kernel32.dll")]
		internal static extern Boolean SetCommState(IntPtr hFile, [In] ref DCB lpDCB);

		[DllImport("kernel32.dll")]
		internal static extern Boolean SetCommTimeouts(IntPtr hFile, [In] ref COMMTIMEOUTS lpCommTimeouts);

		[DllImport("kernel32.dll")]
		internal static extern Boolean SetupComm(IntPtr hFile, UInt32 dwInQueue, UInt32 dwOutQueue);

		[StructLayout( LayoutKind.Sequential )] internal struct COMMTIMEOUTS 
		{
			//JH 1.1: Changed Int32 to UInt32 to allow setting to MAXDWORD
			internal UInt32 ReadIntervalTimeout;
			internal UInt32 ReadTotalTimeoutMultiplier;
			internal UInt32 ReadTotalTimeoutConstant;
			internal UInt32 WriteTotalTimeoutMultiplier;
			internal UInt32 WriteTotalTimeoutConstant;
		}
		//JH 1.1: Added to enable use of "return immediately" timeout.
		internal const UInt32 MAXDWORD = 0xffffffff;

		[StructLayout( LayoutKind.Sequential )] internal struct DCB 
		{
			internal Int32 DCBlength;
			internal Int32 BaudRate;
			internal Int32 PackedValues;
			internal Int16 wReserved;
			internal Int16 XonLim;
			internal Int16 XoffLim;
			internal Byte  ByteSize;
			internal Byte  Parity;
			internal Byte  StopBits;
			internal Byte XonChar;
			internal Byte XoffChar;
			internal Byte ErrorChar;
			internal Byte EofChar;
			internal Byte EvtChar;
			internal Int16 wReserved1;

			internal void init(bool parity, bool outCTS, bool outDSR, int dtr, bool inDSR, bool txc, bool xOut,
				bool xIn, int rts)
			{
				//JH 1.3: Was 0x8001 ans so not setting fAbortOnError - Thanks Larry Delby!
				DCBlength = 28; PackedValues = 0x4001;
				if (parity) PackedValues |= 0x0002;
				if (outCTS) PackedValues |= 0x0004;
				if (outDSR) PackedValues |= 0x0008;
				PackedValues |= ((dtr & 0x0003) << 4);
				if (inDSR) PackedValues |= 0x0040;
				if (txc) PackedValues |= 0x0080;
				if (xOut) PackedValues |= 0x0100;
				if (xIn) PackedValues |= 0x0200;
				PackedValues |= ((rts & 0x0003) << 12);

			}
		}

		/// <summary>
		/// Reading and writing.
		/// </summary>
		[DllImport("kernel32.dll", SetLastError=true)]
		internal static extern Boolean WriteFile(IntPtr fFile, Byte[] lpBuffer, UInt32 nNumberOfBytesToWrite,
			out UInt32 lpNumberOfBytesWritten, IntPtr lpOverlapped);

		[StructLayout( LayoutKind.Sequential )] internal struct OVERLAPPED 
		{
			internal UIntPtr Internal;
			internal UIntPtr InternalHigh;
			internal UInt32 Offset;
			internal UInt32 OffsetHigh;
			internal IntPtr hEvent;
		}

		[DllImport("kernel32.dll")]
		internal static extern Boolean SetCommMask(IntPtr hFile, UInt32 dwEvtMask);

		// Constants for dwEvtMask:
			internal const UInt32 EV_RXCHAR = 0x0001;
			internal const UInt32 EV_RXFLAG = 0x0002;
			internal const UInt32 EV_TXEMPTY = 0x0004;
			internal const UInt32 EV_CTS = 0x0008;
			internal const UInt32 EV_DSR = 0x0010;
			internal const UInt32 EV_RLSD = 0x0020;
			internal const UInt32 EV_BREAK = 0x0040;
			internal const UInt32 EV_ERR = 0x0080;
			internal const UInt32 EV_RING = 0x0100;
			internal const UInt32 EV_PERR = 0x0200;
			internal const UInt32 EV_RX80FULL = 0x0400;
			internal const UInt32 EV_EVENT1 = 0x0800;
			internal const UInt32 EV_EVENT2 = 0x1000;

		[DllImport("kernel32.dll", SetLastError=true)]
		internal static extern Boolean WaitCommEvent(IntPtr hFile, IntPtr lpEvtMask, IntPtr lpOverlapped);

		[DllImport("kernel32.dll")]
		internal static extern Boolean CancelIo(IntPtr hFile);
		
		[DllImport("kernel32.dll", SetLastError=true)]
		internal static extern Boolean ReadFile(IntPtr hFile, [Out] Byte[] lpBuffer, UInt32 nNumberOfBytesToRead,
			out UInt32 nNumberOfBytesRead, IntPtr lpOverlapped);

		[DllImport("kernel32.dll")]
		internal static extern Boolean TransmitCommChar(IntPtr hFile, Byte cChar);

		/// <summary>
		/// Control port functions.
		/// </summary>
		[DllImport("kernel32.dll")]
		internal static extern Boolean EscapeCommFunction(IntPtr hFile, UInt32 dwFunc);

		// Constants for dwFunc:
			internal const UInt32 SETXOFF = 1;
			internal const UInt32 SETXON = 2;
			internal const UInt32 SETRTS = 3;
			internal const UInt32 CLRRTS = 4;
			internal const UInt32 SETDTR = 5;
			internal const UInt32 CLRDTR = 6;
			internal const UInt32 RESETDEV = 7;
			internal const UInt32 SETBREAK = 8;
			internal const UInt32 CLRBREAK = 9;
		
		[DllImport("kernel32.dll")]
		internal static extern Boolean GetCommModemStatus(IntPtr hFile, out UInt32 lpModemStat);

		// Constants for lpModemStat:
			internal const UInt32 MS_CTS_ON = 0x0010;
			internal const UInt32 MS_DSR_ON = 0x0020;
			internal const UInt32 MS_RING_ON = 0x0040;
			internal const UInt32 MS_RLSD_ON = 0x0080;

		/// <summary>
		/// Status Functions.
		/// </summary>
		[DllImport("kernel32.dll", SetLastError=true)]
		internal static extern Boolean GetOverlappedResult(IntPtr hFile, IntPtr lpOverlapped,
			out UInt32 nNumberOfBytesTransferred, Boolean bWait);

		[DllImport("kernel32.dll")]
		internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, IntPtr lpStat);
		[DllImport("kernel32.dll")]
		internal static extern Boolean ClearCommError(IntPtr hFile, out UInt32 lpErrors, out COMSTAT cs);

		//Constants for lpErrors:
			internal const UInt32 CE_RXOVER = 0x0001;
			internal const UInt32 CE_OVERRUN = 0x0002;
			internal const UInt32 CE_RXPARITY = 0x0004;
			internal const UInt32 CE_FRAME = 0x0008;
			internal const UInt32 CE_BREAK = 0x0010;
			internal const UInt32 CE_TXFULL = 0x0100;
			internal const UInt32 CE_PTO = 0x0200;
			internal const UInt32 CE_IOE = 0x0400;
			internal const UInt32 CE_DNS = 0x0800;
			internal const UInt32 CE_OOP = 0x1000;
			internal const UInt32 CE_MODE = 0x8000;

		[StructLayout( LayoutKind.Sequential )] internal struct COMSTAT 
		{
			internal const uint fCtsHold = 0x1;
			internal const uint fDsrHold = 0x2;
			internal const uint fRlsdHold = 0x4;
			internal const uint fXoffHold = 0x8;
			internal const uint fXoffSent = 0x10;
			internal const uint fEof = 0x20;
			internal const uint fTxim = 0x40;
			internal UInt32 Flags;
			internal UInt32 cbInQue;
			internal UInt32 cbOutQue;
		}
		[DllImport("kernel32.dll")]
		internal static extern Boolean GetCommProperties(IntPtr hFile, out COMMPROP cp);

		[StructLayout( LayoutKind.Sequential )] internal struct COMMPROP
		{
			internal UInt16 wPacketLength; 
			internal UInt16 wPacketVersion; 
			internal UInt32 dwServiceMask; 
			internal UInt32 dwReserved1; 
			internal UInt32 dwMaxTxQueue; 
			internal UInt32 dwMaxRxQueue; 
			internal UInt32 dwMaxBaud; 
			internal UInt32 dwProvSubType; 
			internal UInt32 dwProvCapabilities; 
			internal UInt32 dwSettableParams; 
			internal UInt32 dwSettableBaud; 
			internal UInt16 wSettableData; 
			internal UInt16 wSettableStopParity; 
			internal UInt32 dwCurrentTxQueue; 
			internal UInt32 dwCurrentRxQueue; 
			internal UInt32 dwProvSpec1; 
			internal UInt32 dwProvSpec2; 
			internal Byte wcProvChar; 
		}
	
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -