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

📄 serialport.cs

📁 SerialPort 串口通讯用
💻 CS
📖 第 1 页 / 共 3 页
字号:
		{ 
			get 
			{ 
				return rtsEnable;
			}
			set 
			{
				if (isOpen) 
					internalSerialStream.RtsEnable = value;
				rtsEnable = value;
			}
		}
		
		// StopBits represented in C# as StopBits enum type and in Win32 as an integer 1, 2, or 3.
		[Browsable(true), 
		DefaultValue(defaultStopBits),
		Description("The number of stop bits per transmitted/received byte.")]
		public StopBits StopBits 
		{ 
			get 
			{ 
				return stopBits;
			}
			set 
			{
				if (isOpen) 
					internalSerialStream.StopBits = value;
				stopBits = value;
			}
		}
		
		// timeout for all write operations.  May be set to SerialPort.InfiniteTimeout or any positive value
		[Browsable(true), 
		DefaultValue(defaultWriteTimeout),
		Description("Milliseconds after any write operation starts before timeout if no data transmitted.")]
		public int WriteTimeout
		{ 
			get 
			{ 
				return writeTimeout;
			}
			set 
			{
				if (isOpen) 
					internalSerialStream.WriteTimeout = value;
				writeTimeout = value;
			}
		}
		
		
	
		// -------- SECTION: constructors -----------------*
		public SerialPort(System.ComponentModel.IContainer container)
		{
			///
			/// Required for Windows.Forms Class Composition Designer support
			///
			container.Add(this);
		}
		
		public SerialPort()
		{
		}

		// Non-design SerialPort constructors here chain, using default values for members left unspecified by parameters 
		// Note: Calling SerialPort() does not open a port connection but merely instantiates an object.
		//     : A connection must be made using SerialPort's Open() method.
		public SerialPort(string resource) : this (resource, defaultBaudRate, defaultParity, defaultDataBits, defaultStopBits) 
		{
		}
		
		public SerialPort(string resource, int baudRate) : this (resource, baudRate, defaultParity, defaultDataBits, defaultStopBits) 
		{
		}

		public SerialPort(string resource, int baudRate, Parity parity) : this (resource, baudRate, parity, defaultDataBits, defaultStopBits) 
		{
		}

		public SerialPort(string resource, int baudRate, Parity parity, int dataBits) : this (resource, baudRate, parity, dataBits, defaultStopBits) 
		{
		}
		
		// all the magic happens in the call to the instance's .Open() method.
		// Internally, the SerialStream constructor opens the file handle, sets the device
		// control block and associated Win32 structures, and begins the event-watching cycle.
		public SerialPort(string resource, int baudRate, Parity parity, int dataBits, StopBits stopBits) 
		{
			// RAD paradigm allows us to set these to ANYTHING, so long as .Open() checks for 
			// invalid parameters.
			this.portName = resource;
			this.baudRate = baudRate;
			this.parity = parity;
			this.dataBits = dataBits;
			this.StopBits = stopBits;
		
		}
		
		// DEFAULT DESTRUCTOR used here.
		
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				
				internalSerialStream.Flush();
				
			}
			if (isOpen == false) Close();
			base.Dispose( disposing );
		}

	
	
	
		// ----- SECTION: public methods		
		
		public void ClearBreak()
		{
			if (!isOpen)
				throw new InvalidOperationException("ClearBreak - port not open");
			internalSerialStream.ClearBreak();
			inBreak = false;
		}
		
		
		// Calls internal Serial Stream's Close() method on the internal Serial Stream.
		public void Close() 
		{
			if (!isOpen)
				throw new InvalidOperationException("Serial Port - port already closed!");
			if (internalSerialStream != null) 
			{
				internalSerialStream.Close();
				internalSerialStream = null;
			}
			isOpen = false;
		}	

		public void DiscardInBuffer()
		{
			if (!isOpen)
				throw new InvalidOperationException("DiscardInBuffer - port not open");
			internalSerialStream.DiscardInBuffer();
		}
		
		public void DiscardOutBuffer()
		{
			if (!isOpen)
				throw new InvalidOperationException("DiscardOutBuffer - port not open");
			internalSerialStream.DiscardOutBuffer();
		}
		
		// SerialPort is open <=> SerialPort has an associated SerialStream.
		// The two statements are functionally equivalent here, so this method basically calls underlying Stream's
		// constructor from the main properties specified in SerialPort: baud, stopBits, parity, dataBits, 
		// comm resource, handshaking, and timeouts.
		public void Open() 
		{
			if (isOpen) 
				throw new InvalidOperationException("Serial Port - port already open!");
			// Equivalent error checking done here and in properties individually.				
			if (parity < Parity.None || parity > Parity.Space)
				throw new ArgumentOutOfRangeException("parity", InternalResources.GetResourceString("ArgumentOutOfRange_Enum"));
			if (dataBits < minDataBits || dataBits > maxDataBits)
				throw new ArgumentOutOfRangeException("dataBits", 
					InternalResources.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", minDataBits, maxDataBits));
			if (stopBits < StopBits.One || stopBits > StopBits.OnePointFive)
				throw new ArgumentOutOfRangeException("stopBits", InternalResources.GetResourceString("ArgumentOutOfRange_Enum"));
			if (baudRate <= 0)
				throw new ArgumentOutOfRangeException("baudRate", InternalResources.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
			if (portName == null) 
				throw new ArgumentNullException("resource", InternalResources.GetResourceString("ArgumentNull_String"));
			if (handshake < Handshake.None || handshake > Handshake.RequestToSendXOnXOff)
				throw new ArgumentOutOfRangeException("handshake", InternalResources.GetResourceString("ArgumentOutOfRange_Enum"));	
			if (readTimeout < 0 && readTimeout != SerialPort.InfiniteTimeout) 
				throw new ArgumentOutOfRangeException("readTimeout", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
			if (writeTimeout <= 0 && writeTimeout != SerialPort.InfiniteTimeout) 
				throw new ArgumentOutOfRangeException("writeTimeout", InternalResources.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
			// disallow access to device resources beginning with @"\\", instead requiring "COM2:", etc.
			// Note that this still allows freedom in mapping names to ports, etc., but blocks security leaks.
			if (portName.StartsWith("\\\\"))
				throw new ArgumentException("resource", InternalResources.GetResourceString("Arg_SecurityException"));
			
			internalSerialStream = new SerialStream(portName, baudRate, parity, dataBits, stopBits, readTimeout,
				writeTimeout, handshake, dtrEnable, rtsEnable, discardNull, parityReplace);
				
			internalSerialStream.ErrorEvent += new SerialEventHandler(CatchErrorEvents);
			internalSerialStream.PinChangedEvent += new SerialEventHandler(CatchPinChangedEvents);
			internalSerialStream.ReceivedEvent += new SerialEventHandler(CatchReceivedEvents); 
				
			isOpen = true;
		}

		// Read Design pattern:
		//	: Read() returns -1 on timeout, or the first available full char if found before.
		//  : Read(byte[] buffer..., int count) returns all data available before read timeout expires up to *count* bytes
		//  : Read(char[] buffer..., int count) returns all data available before read timeout expires up to *count* chars.
		//	:									Note, this does not return "half-characters".
		//  : ReadByte() is the binary analogue of the first one.
		//  : ReadLine(): returns null string on timeout, saves received data in buffer
		//  : ReadAvailable(): returns all full characters which are IMMEDIATELY available.
			
		public int Read(byte[] buffer, int offset, int count) 
		{
			if (!isOpen) 
				throw new InvalidOperationException("Serial Port Read - port not open");
			if (buffer==null)
				throw new ArgumentNullException("buffer", InternalResources.GetResourceString("ArgumentNull_Buffer"));
			if (offset < 0)
				throw new ArgumentOutOfRangeException("offset", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
			if (count < 0)
				throw new ArgumentOutOfRangeException("count", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
			if (buffer.Length - offset < count)
				throw new ArgumentException(InternalResources.GetResourceString("Argument_InvalidOffLen"));
			int beginReadPos = readPos;
			
			byte [] tempReturnBuffer = new byte[count];
			
			// if any bytes available in internal buffer, return those without calling any read ops.
			if (readLen - readPos >= 1)
			{
				int min = (readLen - readPos < count) ? readLen - readPos : count;
				Buffer.BlockCopy(inBuffer, readPos, buffer, 0, min);
				readPos += min;
				if (min == count) {
					if (readPos == readLen) readPos = readLen = 0;	// just a check to see if we can reset buffer
					return count;
				}
				
				// if we have read some bytes but there's none immediately available, return.
				if (InBufferBytes == 0) return min;
			}
			
			int bytesLeftToRead = count - (readPos - beginReadPos);
			
			// check that internal buffer is big enough to hold incoming bytes before requesting.	
			if (bytesLeftToRead + readLen >= inBuffer.Length) ResizeBuffer();
			
			// request to read the requested number of bytes to fulfill the contract,
			// doesn't matter if we time out.  We still return all the data we have available.
			int returnCount = internalSerialStream.Read(inBuffer, readLen, bytesLeftToRead);
	
			// Return all we have.  This will leave nothing left in the inbuffer, and will not be more than *count*.
			Buffer.BlockCopy(inBuffer, beginReadPos, buffer, offset, returnCount + (readPos - beginReadPos));
			readLen = readPos = 0; 
			return returnCount + readPos - beginReadPos; // return the number of bytes we threw into the buffer plus what we had.
		}

		// publicly exposed "ReadOneChar"-type: Read()
		// reads one full character from the stream
		public int Read() 
		{
			return ReadOneChar(readTimeout);
		}

		// gets next available full character, which may be from the buffer, the stream, or both.
		// this takes size^2 time at most, where *size* is the maximum size of any one character in an encoding.
		// The user can call Read(1) to mimic this functionality.
		
		private int ReadOneChar(int timeout) 
		{	
			int beginReadPos = readPos;
			int nextByte;
			int timeUsed = 0;
			Debug.Assert(isOpen, "ReadOneChar - port not open");
			
			// simply return if we have no time rather than throw exception, since we have 
			// to use this multiple times for one ReadLine() call, and our toes might end up
			// just over the edge.
			
			if (timeout < 0 && timeout != SerialPort.InfiniteTimeout) return -1;
			
			// case 1: we have >= 1 character in the internal buffer.
			if (encoding.GetCharCount(inBuffer, readPos, readLen - readPos) != 0) 
			{
				// get characters from buffer.
				do 
				{
					nextByte = (int) inBuffer[readPos++];
				} while (encoding.GetCharCount(inBuffer, beginReadPos, readPos - beginReadPos) < 1);
				encoding.GetChars(inBuffer, beginReadPos, readPos - beginReadPos, oneChar, 0);
				return oneChar[0];
			} 
			else 
			{
				
				// need to return immediately.
				if (timeout == 0) {
					// read all bytes in the serial driver in here.
					if (InBufferBytes + readPos >= inBuffer.Length) ResizeBuffer();
					int bytesRead = internalSerialStream.Read(inBuffer, readLen, InBufferBytes - (readLen - readPos)); // read all immediately avail.
					readLen += bytesRead;
					
					// check all we have in the buffer - if not enough, return -1
					if (ReadBufferIntoChars(oneChar, 0, 1) == 0) return -1;
					else return oneChar[0];
				}
				
				// case 2: we need to read from outside to find this.
				// timeout is either infinite or positive.
				int startTicks = SafeNativeMethods.GetTickCount();
				do 
				{
					timeUsed = SafeNativeMethods.GetTickCount() - startTicks;
					if (timeout != SerialPort.InfiniteTimeout && (timeout - timeUsed <= 0)) 
					{
						nextByte = -1;
						break;	// break for timeouts
					}
					nextByte = internalSerialStream.ReadByte((timeout == InfiniteTimeout) ? InfiniteTimeout : timeout - timeUsed);
					if (nextByte == -1) break;		// timed out
					if (readLen >= inBuffer.Length) ResizeBuffer();
					inBuffer[readLen++] = (byte) nextByte;	// we must add to the end of the buffer
					readPos++;
				} while (encoding.GetCharCount(inBuffer, beginReadPos, readPos - beginReadPos) < 1);
			}
			
			if (nextByte == -1) return -1;		// timed out, return -1
			
			encoding.GetChars(inBuffer, beginReadPos, readPos - beginReadPos, oneChar, 0);
			return oneChar[0];
		}
		

		
		// return value is either a valid byte from the buffer or stream, or -1 if a timeout occurs.
		// reads as many full characters as available
		public int Read(char[] buffer, int offset, int count)
		{
			if (buffer==null)
				throw new ArgumentNullException("buffer", InternalResources.GetResourceString("ArgumentNull_Buffer"));
			if (offset < 0)
				throw new ArgumentOutOfRangeException("offset", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
			if (count < 0)
				throw new ArgumentOutOfRangeException("count", InternalResources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
			if (buffer.Length - offset < count)
				throw new ArgumentException(InternalResources.GetResourceString("Argument_InvalidOffLen"));
			if (!isOpen) 
				throw new InvalidOperationException("Serial Port Read - port not open");
				
			if (count == 0) return 0;	// immediately return on zero chars desired.  This simplifies things later.
			
			// read everything else into internal buffer, which we know we can do instantly, and see if we NOW have enough.
			int bytesInDriver = InBufferBytes - (readLen - readPos);
			if (readLen + bytesInDriver >= inBuffer.Length) ResizeBuffer();
			internalSerialStream.Read(inBuffer, readLen, bytesInDriver);	// should execute instantaneously.
			readLen += bytesInDriver;
			
			int charsWeAlreadyHave = encoding.GetCharCount(inBuffer, readPos, readLen - readPos); // full chars already in our buffer	
			if (charsWeAlreadyHave >= count) 
			{
				return ReadBufferIntoChars(buffer, offset, count);
			}
			
			// else: we need to do incremental reads from the stream.
			// -----
			// our internal algorithm for finding exactly n characters is a bit complicated, but must overcome the 
			// hurdle of NEVER READING TOO MANY BYTES from the Stream, since we can time out.  A variable-length encoding
			// allows anywhere between minimum and maximum bytes per char times number of chars to be the exactly correct
			// target, and we have to take care not to overuse GetCharCount().  The problem is that GetCharCount() will never tell
			// us if we've read "half" a character in our current set of collected bytes; it underestimates.    
			// size = maximum bytes per character in the encoding.  n = number of characters requested.
			// Solution I: Use ReadOneChar() to read successive characters until we get to n. 

⌨️ 快捷键说明

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