C#串口操作(国外网站看来的,共享一下)

前一阵,从国外网站看到一个用C#来操作串口的类。下载下来试了一下,觉得不错。共享一下。
/*

  • Author: Marcus Lorentzon, 2001
  • [email protected]
  • Freeware: Please do not remove this header
  • File: SerialStream.cs
  • Description: Implements a Stream for asynchronous
  • transfers and COMM. Stream version.
  • Version: 2.4

*/

#region Using

using System;
using System.IO;
using System.Threading;
using System.Runtime.InteropServices;
using System.ComponentModel;

#endregion Using

namespace LoMaN.IO {

public class SerialStream : Stream {

#region Attributes

private IOCompletionCallback m_IOCompletionCallback;
private IntPtr m_hFile = IntPtr.Zero;
private string m_sPort;
private bool m_bRead;
private bool m_bWrite;

#endregion Attributes

#region Properties

public string Port {
get {
return m_sPort;
}
set {
if (m_sPort != value) {
Close();
Open(value);
}
}
}

public override bool CanRead {
get {
return m_bRead;
}
}

public override bool CanWrite {
get {
return m_bWrite;
}
}

public override bool CanSeek {
get {
return false ;
}
}

public bool Closed {
get {
return m_hFile.ToInt32() 0 ;
}
}

public bool Dsr {
get {
uint status;
if ( ! GetCommModemStatus(m_hFile, out status)) {
throw new Win32Exception();
}
return (status & MS_DSR_ON) > 0 ;
}
}

public bool Ring {
get {
uint status;
if ( ! GetCommModemStatus(m_hFile, out status)) {
throw new Win32Exception();
}
return (status & MS_RING_ON) > 0 ;
}
}

public bool Rlsd {
get {
uint status;
if ( ! GetCommModemStatus(m_hFile, out status)) {
throw new Win32Exception();
}
return (status & MS_RLSD_ON) > 0 ;
}
}

#endregion Properties

#region Constructors

public SerialStream() : this (FileAccess.ReadWrite) {
}

public SerialStream(FileAccess access) {
m_bRead = (( int )access & ( int )FileAccess.Read) != 0 ;
m_bWrite = (( int )access & ( int )FileAccess.Write) != 0 ;
unsafe {
m_IOCompletionCallback = new IOCompletionCallback(AsyncFSCallback);
}
}

public SerialStream( string port) : this (FileAccess.ReadWrite) {
Open(port);
}

public SerialStream( string port, FileAccess access) : this (access) {
Open(port);
}

#endregion Constructors

#region Methods

public void Open( string port) {
if (m_hFile != IntPtr.Zero) {
throw new IOException( " Stream already opened. " );
}
m_sPort = port;
m_hFile = CreateFile(port, ( uint )((m_bRead ? GENERIC_READ: 0 ) | (m_bWrite ? GENERIC_WRITE: 0 )), 0 , 0 , OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0 );
if (m_hFile.ToInt32() == INVALID_HANDLE_VALUE) {
m_hFile = IntPtr.Zero;
throw new FileNotFoundException( " Unable to open " + port);
}

ThreadPool.BindHandle(m_hFile);

SetTimeouts( 0 , 0 , 0 , 0 , 0 );
}

public override void Close() {
CloseHandle(m_hFile);
m_hFile = IntPtr.Zero;
m_sPort = null ;
}

public IAsyncResult BeginRead( byte [] buffer) {
return BeginRead(buffer, 0 , buffer.Length, null , null );
}

public override IAsyncResult BeginRead( byte [] buffer, int offset, int count, AsyncCallback callback, object state) {
GCHandle gchBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
SerialAsyncResult sar = new SerialAsyncResult( this , state, callback, true , gchBuffer);
Overlapped ov = new Overlapped( 0 , 0 , sar.AsyncWaitHandle.Handle.ToInt32(), sar);
unsafe {
NativeOverlapped * nov = ov.Pack(m_IOCompletionCallback);
byte * data = ( byte * )(( int )gchBuffer.AddrOfPinnedObject() + offset);

uint read = 0 ;
if (ReadFile(m_hFile, data, ( uint )count, out read, nov)) {
sar.m_bCompletedSynchronously = true ;
return sar;
}
else if (GetLastError() == ERROR_IO_PENDING) {
return sar;
}
else
throw new Exception( " Unable to initialize read. Errorcode: " + GetLastError().ToString());
}
}

public IAsyncResult BeginWrite( byte [] buffer) {
return BeginWrite(buffer, 0 , buffer.Length, null , null );
}

public override IAsyncResult BeginWrite( byte [] buffer, int offset, int count, AsyncCallback callback, object state) {
GCHandle gchBuffer = GCHandle.Alloc(buffer, GCHandleType.Pinned);
SerialAsyncResult sar = new SerialAsyncResult( this , state, callback, false , gchBuffer);
Overlapped ov = new Overlapped( 0 , 0 , sar.AsyncWaitHandle.Handle.ToInt32(), sar);
unsafe {
NativeOverlapped * nov = ov.Pack(m_IOCompletionCallback);
byte * data = ( byte * )(( int )gchBuffer.AddrOfPinnedObject() + offset);

uint written = 0 ;
if (WriteFile(m_hFile, data, ( uint )count, out written, nov)) {
sar.m_bCompletedSynchronously = true ;
return sar;
}
else if (GetLastError() == ERROR_IO_PENDING) {
return sar;
}
else
throw new Exception( " Unable to initialize write. Errorcode: " + GetLastError().ToString());
}
}

private int EndOperation(IAsyncResult asyncResult, bool isRead) {
SerialAsyncResult sar = (SerialAsyncResult)asyncResult;
if (sar.m_bIsRead != isRead)
throw new IOException( " Invalid parameter: IAsyncResult is not from a " + (isRead ? " read " : " write " ));
if (sar.EndOperationCalled) {
throw new IOException( " End " + (isRead ? " Read " : " Write " ) + " called twice for the same operation. " );
}
else {
sar.m_bEndOperationCalled = true ;
}

while ( ! sar.m_bCompleted) {
sar.AsyncWaitHandle.WaitOne();
}

sar.Dispose();

if (sar.m_nErrorCode != ERROR_SUCCESS && sar.m_nErrorCode != ERROR_OPERATION_ABORTED) {
throw new IOException( " Operation finished with errorcode: " + sar.m_nErrorCode);
}

return sar.m_nReadWritten;
}

public override int EndRead(IAsyncResult asyncResult) {
return EndOperation(asyncResult, true );
}

public override void EndWrite(IAsyncResult asyncResult) {
EndOperation(asyncResult, false );
}

public int EndWriteEx(IAsyncResult asyncResult) {
return EndOperation(asyncResult, false );
}

public override int Read( byte [] buffer, int offset, int count) {
return EndRead(BeginRead(buffer, offset, count, null , null ));
}

public override void Write( byte [] buffer, int offset, int count) {
EndWrite(BeginWrite(buffer, offset, count, null , null ));
}

public int WriteEx( byte [] buffer, int offset, int count) {
return EndWriteEx(BeginWrite(buffer, offset, count, null , null ));
}

public int Read( byte [] buffer) {
return EndRead(BeginRead(buffer, 0 , buffer.Length, null , null ));
}

public int Write( byte [] buffer) {
return EndOperation(BeginWrite(buffer, 0 , buffer.Length, null , null ), false );
}

public override void Flush() {
FlushFileBuffers(m_hFile);
}

public bool PurgeRead() {
return PurgeComm(m_hFile, PURGE_RXCLEAR);
}

public bool PurgeWrite() {
return PurgeComm(m_hFile, PURGE_TXCLEAR);
}

public bool Purge() {
return PurgeRead() && PurgeWrite();
}

public bool CancelRead() {
return PurgeComm(m_hFile, PURGE_RXABORT);
}

public bool CancelWrite() {
return PurgeComm(m_hFile, PURGE_TXABORT);
}

public bool CancelAll() {
return CancelRead() && CancelWrite();
}

public override void SetLength( long nLength) {
throw new NotSupportedException( " SetLength isn't supported on serial ports. " );
}

public override long Seek( long offset, SeekOrigin origin) {
throw new NotSupportedException( " Seek isn't supported on serial ports. " );
}

public void SetTimeouts( int ReadIntervalTimeout,
int ReadTotalTimeoutMultiplier,
int ReadTotalTimeoutConstant,
int WriteTotalTimeoutMultiplier,
int WriteTotalTimeoutConstant) {
SerialTimeouts Timeouts = new SerialTimeouts(ReadIntervalTimeout,
ReadTotalTimeoutMultiplier,
ReadTotalTimeoutConstant,
WriteTotalTimeoutMultiplier,
WriteTotalTimeoutConstant);
unsafe { SetCommTimeouts(m_hFile, ref Timeouts); }
}

public bool SetPortSettings( uint baudrate) {
return SetPortSettings(baudrate, FlowControl.Hardware);
}

public bool SetPortSettings( uint baudrate, FlowControl flowControl) {
return SetPortSettings(baudrate, flowControl, Parity.None);
}

public bool SetPortSettings( uint baudrate, FlowControl flowControl, Parity parity) {
return SetPortSettings(baudrate, flowControl, parity, 8 , StopBits.One);
}

public bool SetPortSettings( uint baudrate, FlowControl flowControl, Parity parity, byte databits, StopBits stopbits) {
unsafe {
DCB dcb = new DCB();
dcb.DCBlength = sizeof (DCB);
dcb.BaudRate = baudrate;
dcb.ByteSize = databits;
dcb.StopBits = ( byte )stopbits;
dcb.Parity = ( byte )parity;
dcb.fParity = (parity > 0 ) ? 1U : 0U ;
dcb.fBinary = dcb.fDtrControl = dcb.fTXContinueOnXoff = 1 ;
dcb.fOutxCtsFlow = dcb.fAbortOnError = (flowControl == FlowControl.Hardware) ? 1U : 0U ;
dcb.fOutX = dcb.fInX = (flowControl == FlowControl.XOnXOff) ? 1U : 0U ;
dcb.fRtsControl = (flowControl == FlowControl.Hardware) ? 2U : 1U ;
dcb.XonLim = 2048 ;
dcb.XoffLim = 512 ;
dcb.XonChar = 0x11 ; // Ctrl-Q
dcb.XoffChar = 0x13 ; // Ctrl-S
return SetCommState(m_hFile, ref dcb);
}
}

public bool SetPortSettings(DCB dcb) {
return SetCommState(m_hFile, ref dcb);
}

public bool GetPortSettings( out DCB dcb) {
unsafe {
DCB dcb2 = new DCB();
dcb2.DCBlength = sizeof (DCB);
bool ret = GetCommState(m_hFile, ref dcb2);
dcb = dcb2;
return ret;
}
}

public bool SetXOn() {
return EscapeCommFun

Published At
Categories with Web编程
Tagged with
comments powered by Disqus