The previous game saw a class that manages the serial port from the foreign website. Download and tried it, I feel good. Share it.
/ *
* Author: Marcus Lorentzon, 2001
* D98malor@dtek.chalmers.se
*
* FREEWARE: PLEASE DO NOT REMOVE THIS HEADER
*
* File: SerialStream.cs
*
* Description: Implements a stream for asynchronous
* Transfers and common. stream version.
*
* Version: 2.4
*
* /
#Region Using
Using system;
Using system.io;
Using system.threading;
Using system.Runtime.InteropServices;
Using system.componentmodel;
#ndregion 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 (! getcommodemstatus (m_hfile, out status) {
Throw new win32exception ();
}
Return (Status & MS_DSR_ON)> 0;
}
}
Public bool ring {
Get {
Uint status;
IF (! getcommodemstatus (m_hfile, out status) {
Throw new win32exception ();
}
Return (Status & MS_RING_ON)> 0;
}
}
Public bool rlsd {
Get {
Uint status;
IF (! getcommodemstatus (m_hfile, out status) {
Throw new win32exception ();
}
Return (status & ms_rlsd_on)> 0;
}
}
#ndregion property
#Region Constructionors
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 ocompletioncallback; asyncfscallback;
}
}
Public SerialStream (String Port): this (fileAccess.readwrite) {
Open (port);
}
Public SerialStream (String Port, FileAccess Access): this (access) {
Open (port);
}
#ndregion constructors
#Region Methods
Public void open (string port) {
IF (m_hfile! = INTPTR.ZERO) {
Throw new oException ("stream already opened.");
}
m_sport = port;
M_HFILE = CREATEFILE (port, (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, NUFL);
}
Public Override IasyncResult Beginread (Byte [] Buffer, Int Offset, Int Count, AsyncCallback Callback, Object State {
Gchandle gchbuffer = gchaldle.alloc (buffer, gchandletype.pinned);
SerialasyncResult Sar = New SerialAlasyncResult (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_BCOMPLETEDSYNCHRONOMSLY = 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, NUFFER);
}
Public Override IasyncResult Beginwrite (Byte [] Buffer, Int Offset, Int Count, AsyncCallback Callback, Object State {
Gchandle gchbuffer = gchaldle.alloc (buffer, gchandletype.pinned);
SerialasyncResult Sar = New SerialAlasyncResult (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_BCOMPLETEDSYNCHRONOMSLY = 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 (isresult asyncRESult, Bool IsRead) {
SERIALASYNCRESULT SAR = (serialasyncResult) asyncResult;
IF (SAR.M_BISREAD! = Isread)
Throw New IOException ("INVALID Parameter: IASYNCRESULT IS NOT FROM A (IsRead?" ied ":" write ");
IF (sar.endotoperationcalled) {
THROW NEW IOEXCEPTION ("END" (IsRead? "r": "WRITE") "Called TWICE for the Same Operation.");}
Else {
SAR.M_BENDOPERATIONCALLED = TRUE;
}
While (! SAR.M_BCOMPLED) {
Sar.asyncwaithandle.waitone ();
}
SAR.Dispose ();
IF (SAR.M_NERRORCODE! = Error_Success && Sar.m_NerrorCode! = Error_Operation_aborted) {
Throw new oException ("Operation Finished with ErrorCode:" SAR.M_NERRORCODE);
}
Return sar.m_nreadwritten;
}
Public override int end (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 {(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 (Buffer, Offset, Count, Null, Null);
}
Public int writeex (byte [] buffer, int offset, int count) {
Return EndwriteEx (Buffer, Offset, Count, Null, NULL);
}
Public int {(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 nongth) {
Throw New NotSupportedException ("SETLENGTH ISN '@");
}
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 WRITETOTIMEOUTCONSTANT) {
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 DataS, 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 == fluontrol.hardware)? 1U: 0U;
Dcb.foutx = dcb.finx = (flowcontrol == fluontrol.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 EscapeCommfunction (M_HFILE, SETXON);
}
Public bool setxoff () {
Return EscapeCommfunction (M_HFILE, SETXOFF);
}
Private unsafe void asyncfscallback (uint error ", nativeoverlapped * poounts) {
SerialasyncResult SAR = (SerialAlasyncResult) overlapped.unpack (PoverLapped) .asyncResult;
SAR.M_NERRORCODE = ErrorCode;
SAR.M_NREADWRITEN = (int) Numbytes;
SAR.M_BCOMPLETED = TRUE;
IF (SAR.CALLBACK! = NULL)
Sar.callback.invoke (sar);
Overlapped.free (Poverlapped);
}
#ndregion methods
#Region Constants
Private const uint purge_txabort = 0x0001; // kill the pending / current Writes to the CommM port.
Private const uint purge_rxabort = 0x0002; // kill the pending / current reads to the commit.
Private const uint purge_txclear = 0x0004; // kill the transmit queue if there.
Private const uint purge_rxclear = 0x0008; // Kill The Typeahead Buffer if There.
Private const uint setXoff = 1; // simulate xoff received
Private const uint setxon = 2; // simulate xon receivedprivate const uint set = 3; // set rts high
Private const uint crarts = 4; // set RTS Low
Private const uint setdtr = 5; // set DTR HIGH
Private const uint clrdtr = 6; // set DTR Low
Private const uint setbreak = 8; // set the device break line.
Private const uint clrbreak = 9; // Clear The Device Break line.
PRIVATE CONST UINT MS_CTS_ON = 0x0010;
PRIVATE CONST uint MS_DSR_ON = 0x0020;
Private const uint MS_RING_ON = 0x0040;
PRIVATE CONST UINT MS_RLSD_ON = 0x0080;
Private const uint file_flag_overlapped = 0x40000000;
PRIVATE CONST uint open_existing = 3;
Private const INT INVALID_HANDLE_VALUE = -1;
Private const uint generic_read = 0x80000000;
Private const uint generic_write = 0x40000000;
Private const uint error_success = 0;
Private const uint error_operation_aborted = 995;
Private const uint error_io_pending = 997;
#ndregion constants
#Region enums
Public Enum Parity {None, ODD, Even, Mark, Space};
Public enum stopbits {one, oneandhalf, two};
Public enum flowcontrol {none, xonxoff, hardware};
#ndregion enums
#Region Classes
[Structlayout (layoutkind.sequential)]
Public struct dcb {
#Region Attributes
Public int dcblength;
Public uint baudrate;
Public uint flags;
Public ushort wreserved;
Public ushort xonlim;
Public ushort xofflim;
Public Byte bytesize;
Public Byte Parity;
Public Byte Stopbits;
Public sbyte xonchar;
Public sbyte xoffchar;
Public sbyte errorchar;
Public Sbyte EOFCHAR;
Public sbyte evtchar;
Public Ushort Wreserved1;
#ENDREGION Attributes
#Region Properties
Public uint fbinary {get {return flags & 0x0001;
Set {Flags = Flags & ~ 1u | Value;}} public uint fparity {get {return (flags >> 1) & 1;}
Set {Flags = Flags & ~ (1U> 2) & 1;}
Set {Flags = Flags & ~ (1U> 3) & 1;}
Set {Flags = Flags & ~ (1U> 4) & 3;
Set {Flags = Flags & ~ (3U> 6) & 1;}
Set {Flags = Flags & ~ (1U> 7) & 1;
Set {Flags = Flags & ~ (1U> 8) & 1;
Set {Flags = Flags & ~ (1U> 9) & 1;}
Set {Flags = Flags & ~ (1U> 10) & 1;}
Set {Flags = Flags & ~ (1U> 11) & 1;}
Set {Flags = Flags & ~ (1U> 12) & 3;
Set {Flags = Flags & ~ (3U> 14) & 1;
SET {Flags = Flags & ~ (1u << 14) | (Value << 14);}}
#ndregion property
#Region Methods
Public Override string toString () {
Return "DCBLENGTH:" DCBLENGTH "/ R / N"
"Baudrate:" BAUDRATE "/ R / N"
"Fbinary:" FBINARY "/ R / N"
"FPARITY: FPARITY " / R / N "
"foutxctsflow:" foutxctsflow "/ r / n"
"foutxdsrflow:" foutxdsrflow "/ r / n"
"FDTRCONTROL: FDTRCONTROL " / R / N "
FDSRSENSITIVITY: FDSRSENSITIVITY "/ R / N"
"ftxcontinueonxoff:" ftxcontinueonxoff "/ r / n"
"foutx:" foutx "/ r / n"
"FINX:" FINX "/ R / N"
FerrorChar: " FerrorChar " / R / N "
"Fnull:" Fnull "/ R / N"
"FRTSCONTROL:" FRTSCONTROL "/ R / N" "Fabortonerror:" Fabortonerror "/ R / N"
"XONLIM:" XONLIM "/ R / N"
"Xofflim:" XOfflim "/ r / n"
"BYTESIZE:" BYTESIZE "/ R / N"
"Parity:" Parity "/ R / N"
"Stopbits:" StopBits "/ R / N"
"Xonchar:" Xonchar "/ r / n"
Xoffchar: " Xoffchar " / R / N "
"EOFCHAR:" EOFCHAR "/ R / N"
"Evtchar:" evtchar "/ r / n";
}
#ndregion methods
}
Private Class SerialAlasyncResult: IASYNCRESULT, IDISPOSABLE {
#Region Attributes
INTERNAL BOOL M_BENDOPERATIONCALLED = FALSE;
INTERNAL BOOL M_BISREAD;
INTERNAL INT M_NREADWRITTEN = 0;
INTERNAL BOOL M_BCOMPLETED = FALSE;
INTERNAL BOOL M_BCOMPLETEDSYNCHRONOSLY = FALSE;
INTERNAL UINT M_NERRORCODE = Error_Success;
PRIVATE OBJECT M_ASYNCOBJECT;
PRIVATE OBJECT M_STATEOBJECT;
Private manualReveTevent M_WaitHandle = New ManualRetevent (false);
Private asyncCallback m_callback;
PRIVATE GCHANDLE M_GCHBUFFER;
#ENDREGION Attributes
#Region Properties
INTERNAL BOOL endOperationcalled {get {return m_bendopertycalled;}}
Public bool iscompleted {get {return m_bcompleted;}}
Public Bool CompletedSynchronously {Get {Return M_BcompletedSynchronously;}}
Public Object AsyncObject {get {return m_asyncobject;}}
Public Object asyncState {get {return m_stateObject;}}
Public WaitHandle AsyncWaithandle {get {return m_waithandle;}}
INTERNAL MANUALRESEVENT WAITHANDLE {Get {Return M_WaitHandle;}} PUBLIC AsyncCallback Callback {get {return m_callback;}}
#ndregion property
#Region Constructionors
Public SerialAlasyncResult (Object AsyncObject,
Object StateObject,
AsyncCallback Callback,
Bool Bisread,
Gchandle gchbuffer {
m_asyncObject = asyncObject;
m_stateObject = stateObject;
M_Callback = Callback;
m_bisread = bisread;
m_gchbuffer = gchbuffer;
}
#ndregion constructors
#Region Methods
Public void dispose () {
m_WaitHandle.Close ();
m_gchbuffer.free ();
}
#ndregion methods
}
#ndregion classes
#Region Imports
[DLLIMPORT ("kernel32.dll", entrypoint = "createfilew", setLastError = true,
Charset = charset.unicode, exactspelling = true)]
Static Extern INTPTR CREATEFILE (STRING FILENAME, UINT Access, Uint Sharemode, Uint Security_Attributes, Uint Creation, Uint Flags, Uint Template);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool CloseHandle (INTPTR HANDLE);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern UNSAFE BOOLE (INTPTR HFILE, BYTE * LPBuffer, uint nnumberofbyteoread, out uint lpnumberofbytesread, nativeoverlapped * lpoverlapped);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern UNSAFE BOOL WRITEFILE (INTPTR HFILE, BYTE * LPBUFFER, UINT NNUMBYTESTOWRITE, OUT UINT LPNUMBYTESWRITEN, NATIVEOVERLAPPED * LPOVERLAPPED);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool Setcommtimeouts (INTPTR HFILE, REF SerialTimeouts);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool SetCommState (INTPTR HFILE, RECB LPDCB);
[DLLIMPORT ("kernel32.dll", setLastError = true)] static extern bool getcommstate (INTPTR HFILE, REF DCB LPDCB);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool Buildcommdcb (String DEF, REF DCB LPDCB);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Int getLastError ();
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool FlushfileBuffers (INTPTR HFILE);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool PurgeComm (INTPTR HFILE, UINT DWFLAGS);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool EscapeCommfunction (INTPTR HFILE, UINT DWFUNC);
[DLLIMPORT ("kernel32.dll", setLastError = true)]
Static Extern Bool getcommmodemStatus (INTPTR HFILE, OUT UINT MODEMSTAT);
#ndregion imports
}
[Structlayout (layoutkind.sequential)]
Public struct serialtimeouts {
#Region Attributes
Public int tentintervaltimeout;
Public int tenttotaltimeoutmultiplier;
Public int intTotalTimeoutConstant;
Public int WriteTotalTimeoutmultiplier;
Public int WriteTotalTimeoutConstant;
#ENDREGION Attributes
#Region Constructionors
Public SerialTimeouts (int R1, Int R2, Int R3, INT W1, INT W2) {
ReadintervalTimeout = R1;
ReadtotalTimeOutmultiplier = r2;
ReadtotalTimeoutConstant = R3;
WriteTotalTimeOutmultiplier = W1;
WriteTotalTimeoutConstant = W2;
}
#ndregion constructors
#Region Methods
Public Override string toString () {
Return "ReadintervalTimeout:" ReadintervalTimeout "/ R / N"
"ReadtotalTimeOutmultiplier:" ReadtotalTimeoutMultiplier "/ R / N"
"ReadtotalTimeoutConstant:" ReadtotalTimeoutConstant "/ R / N" "WriteTotalTimeoutMultiplier:" WriteTotalTimeoutMultiplier "/ R / N"
"WriteTotalTimeoutConstant:" WriteTotalTimeoutConstant "/ R / N";
}
#ndregion methods
}
}
Using system;
Using system.io;
Using system.threading;
USING LOMAN.IO;
Namespace SerialStreamReader {
Class app {
// the main serial stream
Static SerialStream SS;
[Stathread]
Static void main (string [] args) {
// Create a serial port
SS = new serialstream ();
Try {
SS.Open ("COM4"); // I called the cat
}
Catch (Exception E) {
Console.writeline ("Error:" E.MESSAGE);
Return;
}
// set port settings
SS.SETPORTSETTINGS (9600);
// set Timeout So Reads After 20ms of Silence After A Response
ss.settimeouts (20, 0, 0, 0, 0);
// Create the streamwriter used to send commands
StreamWriter SW = New StreamWriter (SS, System.Text.Encoding.ascii);
// Create The Thread Used to Read Responses
Thread responseReaderthread = new thread (New Threadstart (ReadResponseTHRead);
ResponseReaderthread.start ();
// read all returned Lines
For (;;) {
// r r c f
String command = console.readline ();
// Check for EXIT COMMAND
IF (Command.trim (). TOLOWER () == "exit") {
ResponseReaderthread.abort ();
Break;
}
// Write Command to Modem
SW.WRITELINE (Command);
Sw.flush ();
}
}
// main loop forreading responses
Static void readResponsethread () {
StreamReader SR = New StreamReader (SS, System.Text.Encoding.ascii);
Try {
For (;;) {
// read response from modem
String response = sr.readline ();
Console.writeline ("Response:" response);
}
Catch (threadabortexception) {
}
}
}
}
Once the program is run, you can instruct the device to operate. (Directive accepted by specific equipment)