its kind of large but ok;
this is the class I wrote
//***********************************
using System;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
namespace Data_Logger_C
{
public class RS232: IDisposable
{
# region "Variables"
private int c_hCommPort;
private int c_nPort;
private int c_nTimeout;
private int c_nBaudRate;
private enDataParity c_enParity;
private enDataStopBit c_enStopBit;
private int c_nDataBit;
private int c_nBufferSize;
private byte[] c_arrRecieveBuffer;
public Thread c_oEvents;
private bool c_bDisposed;
private enMode c_enMode;
private bool c_bUseXonXoff;
private bool c_bEnableEvents;
private int c_nBufThreshold;
private OVERLAPPED c_OvlE;
private OVERLAPPED c_OvlW;
private OVERLAPPED c_OvlR;
# endregion
# region "Constants"
private const int c_conPURGE_RXABORT = 2;
private const int c_conPURGE_RXCLEAR = 8;
private const int c_conPURGE_TXABORT = 1;
private const int c_conPURGE_TXCLEAR = 4;
private const int c_conGENERIC_READ = int.MinValue;
private const int c_conGENERIC_WRITE = 1073741824;
private const int c_conOPEN_EXISTING = 3;
private const int c_conINVALID_HANDLE_VALUE = -1;
private const int c_conIO_BUFFER_SIZE = 1024;
private const int c_conFILE_FLAG_OVERLAPPED = 1073741824;
private const int c_conERROR_IO_PENDING = 997;
private const int c_conWAIT_OBJECT_0 = 0;
private const int c_conERROR_IO_INCOMPLETE = 996;
private const int c_conWAIT_TIMEOUT = 258;
private const int c_conINFINITE = -1;
public event CommEventHandler commEvent;
# endregion
# region "Enumerations"
public enum enDataParity
{
enParity_None = 0,
enPariti_Odd = 1,
enParity_Even = 2,
enParity_Mark = 3,
}
public enum enDataStopBit
{
enStopBit_1 = 1,
enStopBit_2 = 2,
}
private enum enPurgeBuffers
{
enRXAbort = 2,
enRXClear = 8,
enTxAbort = 1,
enTxClear = 4,
}
private enum enLines
{
enSetRts = 3,
enClearRts = 4,
enSetDtr = 5,
enClearDtr = 6,
enResetDev = 7,
enSetBreak = 8,
enClearBreak = 9
}
[FlagsAttribute()]
public enum enModemStatusBits
{
enClearToSendOn = 16,
enDataSetReadyOn = 32,
enRingIndicatorOn = 64,
enCarrierDetect = 128
}
public enum enMode
{
enNonOverlapped = 0,
enOverlapped = 1,
}
[FlagsAttribute()]
public enum enEventMasks
{
enRxChar = 1,
enRXFlag = 2,
enTxBufferEmpty = 4,
enClearToSend = 8,
enDataSetReady = 16,
enCarrierDetect = 32,
enBreak = 64,
enStatusError = 128,
enRing = 256,
}
# endregion
# region "Structures"
[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]
private struct DCB
{
public int DCBlength;
public int BaudRate;
public int Bits1;
public short wReserved;
public short XonLim;
public short XoffLim;
public byte ByteSize;
public byte Parity;
public byte StopBits;
public char XonChar;
public char XoffChar;
public char ErrorChar;
public char EofChar;
public char EvtChar;
public short wReserved2;
}
[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]
private struct COMMTIMEOUTS
{
public int ReadIntervalTimeout;
public int ReadTotalTimeoutMultiplier;
public int ReadTotalTimeoutConstant;
public int WriteTotalTimeoutMultiplier;
public int WriteTotalTimeoutConstant;
}
[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]
public struct OVERLAPPED
{
public int Internal;
public int InternalHigh;
public int Offset;
public int OffsetHigh;
public int hEvent;
}
[StructLayoutAttribute(LayoutKind.Sequential, Pack=1, Size=0)]
private struct COMSTAT
{
public int fBitFields;
public int cbInQue;
public int cbOutQue;
}
# endregion
# region "Properties"
public virtual string InputStreamString
{
get
{
return new ASCIIEncoding().GetString(InputStream);
}
}
public int RecieveBufferSize
{
get
{
return c_nBufferSize;
}
set
{
c_nBufferSize = value;
}
}
public bool UseXonXoff
{
get
{
return c_bUseXonXoff;
}
set
{
c_bUseXonXoff = value;
}
}
public virtual byte[] InputStream
{
get
{
return c_arrRecieveBuffer;
}
}
public int RxBufferThreshold
{
get
{
return c_nBufThreshold;
}
set
{
c_nBufThreshold = value;
}
}
public enModemStatusBits ModemStatus
{
get
{
enModemStatusBits local0;
int local1 = 0;
if (c_hCommPort == -1)
{
throw new ApplicationException("Please initialize and open port before using
this method");
}
if (!GetCommModemStatus(c_hCommPort, ref local1))
{
throw new ApplicationException("Unable to get modem status");
}
else
{
local0 = (enModemStatusBits)local1;
return local0;
}
}
}
public bool Dtr
{
set
{
if (c_hCommPort != -1)
{
if (value)
{
EscapeCommFunction(c_hCommPort, 5);
}
else
{
EscapeCommFunction(c_hCommPort, 6);
}
}
}
}
public bool Rts
{
set
{
if (c_hCommPort != -1)
{
if (value)
{
EscapeCommFunction(c_hCommPort, 3);
}
else
{
EscapeCommFunction(c_hCommPort, 4);
}
}
}
}
public bool IsOpen
{
get
{
return c_hCommPort == -1 == false;
}
}
public virtual int Timeout
{
get
{
return c_nTimeout;
}
set
{
if (value == 0)
{
c_nTimeout = 500;
}
else
{
c_nTimeout = value;
}
SetTimeout();
}
}
public enDataParity Parity
{
get
{
return c_enParity;
}
set
{
c_enParity = value;
}
}
public int Port
{
get
{
return c_nPort;
}
set
{
c_nPort = value;
}
}
public int BaudRate
{
get
{
return c_nBaudRate;
}
set
{
c_nBaudRate = value;
}
}
public int DataBit
{
get
{
return c_nDataBit;
}
set
{
c_nDataBit = value;
}
}
public enDataStopBit StopBit
{
get
{
return c_enStopBit;
}
set
{
c_enStopBit = value;
}
}
# endregion
#region "API CALLS"
[DllImportAttribute("kernel32.dll")]
private static extern int SetCommState(int hCommDev, ref DCB lpDCB);
[DllImportAttribute("kernel32.dll")]
private static extern int GetCommState(int hCommDev, ref DCB lpDCB);
[DllImportAttribute("kernel32.dll")]
private static extern int BuildCommDCB(string lpDef, ref DCB lpDCB);
[DllImportAttribute("kernel32.dll")]
private static extern int SetupComm(int hFile, int dwInQueue, int
dwOutQueue);
[DllImportAttribute("kernel32.dll")]
private static extern int SetCommTimeouts(int hFile, ref COMMTIMEOUTS
lpCommTimeouts);
[DllImportAttribute("kernel32.dll")]
private static extern int GetCommTimeouts(int hFile, ref COMMTIMEOUTS
lpCommTimeouts);
[DllImportAttribute("kernel32.dll")]
private static extern int ClearCommError(int hFile, int lpErrors, ref
COMSTAT lpComStat);
[DllImportAttribute("kernel32.dll")]
private static extern int PurgeComm(int hFile, int dwFlags);
[DllImportAttribute("kernel32.dll")]
private static extern bool EscapeCommFunction(int hFile, long ifunc);
[DllImportAttribute("kernel32.dll")]
private static extern int WaitCommEvent(int hFile, ref enEventMasks Mask,
ref OVERLAPPED lpOverlap);
[DllImportAttribute("kernel32.dll")]
private static extern int WriteFile(int hFile, byte[] Buffer, int
nNumberOfBytesToWrite, ref int lpNumberOfBytesWritten, ref OVERLAPPED
lpOverlapped);
[DllImportAttribute("kernel32.dll")]
private static extern int ReadFile(int hFile, byte[] Buffer, int
nNumberOfBytesToRead, ref int lpNumberOfBytesRead, ref OVERLAPPED
lpOverlapped);
[DllImportAttribute("kernel32.dll")]
private static extern int CreateFile([MarshalAs(UnmanagedType.LPStr)] string
lpFileName, int dwDesiredAccess, int dwShareMode, int lpSecurityAttributes,
int dwCreationDisposition, int dwFlagsAndAttributes, int hTemplateFile);
[DllImportAttribute("kernel32.dll")]
private static extern int CloseHandle(int hObject);
[DllImportAttribute("kernel32.dll")]
private static extern int FormatMessage(int dwFlags, int lpSource, int
dwMessageId, int dwLanguageId, [MarshalAs(UnmanagedType.LPStr)] string
lpBuffer, int nSize, int Arguments);
[DllImportAttribute("kernel32.dll")]
public static extern bool GetCommModemStatus(int hFile, ref int
lpModemStatus);
[DllImportAttribute("kernel32.dll")]
private static extern bool SetEvent(int hEvent);
[DllImportAttribute("kernel32.dll")]
private static extern int CreateEvent(int lpEventAttributes, int
bManualReset, int bInitialState, [MarshalAs(UnmanagedType.LPStr)] string
lpName);
[DllImportAttribute("kernel32.dll")]
private static extern int GetLastError();
[DllImportAttribute("kernel32.dll")]
private static extern int WaitForSingleObject(int hHandle, int
dwMilliseconds);
[DllImportAttribute("kernel32.dll")]
private static extern int GetOverlappedResult(int hFile, ref OVERLAPPED
lpOverlapped, ref int lpNumberOfBytesTransferred, int bWait);
[DllImportAttribute("kernel32.dll")]
private static extern int SetCommMask(int hFile, int lpEvtMask);
[DllImportAttribute("kernel32", EntryPoint="FormatMessageA",
ExactSpelling=true, CharSet=CharSet.Ansi, SetLastError=true)]
private static extern int FormatMessage(int dwFlags, int lpSource, int
dwMessageId, int dwLanguageId, StringBuilder lpBuffer, int nSize, int
Arguments);
#endregion
# region "Constructor"
public RS232()
{
c_hCommPort = -1;
c_nPort = 1;
c_nTimeout = 70;
c_nBaudRate = 38400;
c_enParity = enDataParity.enParity_None;
c_enStopBit = (enDataStopBit)0;
c_nDataBit = 8;
c_nBufferSize = 512;
c_nBufThreshold = 1;
}
# endregion
# region "Public Methods"
//**************************************************************************
*************
// public void Open()
// Purpose : Initializes and Opens comunication port
// Pre-conditions : None
// Arguments : None
// Returns : None
// Post-conditions : None
//**************************************************************************
*************
public void Open()
{
int iRc = 0;
DCB uDcb = new DCB();
//set the working mode
c_enMode = enMode.enOverlapped;
int intMode;
if(c_enMode == enMode.enOverlapped)
{
intMode = (int)c_conFILE_FLAG_OVERLAPPED;
}
else
{
intMode = (int)0;
}
//init com port
if (c_nPort <= 0)
{
throw new ApplicationException("COM Port not defined,use Port property to
set it before invoking InitPort");
}
//create the com port stream handle
try
{
c_hCommPort = CreateFile("\\\\.\\COM" + c_nPort.ToString(),c_conGENERIC_READ
| c_conGENERIC_WRITE, 0, 0, c_conOPEN_EXISTING, intMode, 0);
if (c_hCommPort == -1)
{
//Raise init problems
throw new clsRS232Exception(String.Concat("Unable to open COM",
c_nPort.ToString()));
}
//Clear all previous Comm Errors
int intErrorCode = 0;
COMSTAT oComstat = new COMSTAT();
iRc = ClearCommError(c_hCommPort, intErrorCode, ref oComstat);
//Clear any IO buffers
iRc = PurgeComm(c_hCommPort, (int)(enPurgeBuffers.enRXClear |
enPurgeBuffers.enTxClear));
//Get current Com Settings
iRc = GetCommState(c_hCommPort,ref uDcb);
//update com settings
string strParity = "NOEM";
strParity = strParity.Substring((int)c_enParity, 1);
//set DBC state
string strDBCState = String.Format("baud={0} parity={1} data={2} stop={3}",
c_nBaudRate, strParity, c_nDataBit,(int)c_enStopBit);
iRc = BuildCommDCB(strDBCState,ref uDcb);
uDcb.Parity = (byte)c_enParity;
//set Xon/Xoff state
if (c_bUseXonXoff)
{
uDcb.Bits1 = 768;
}
else
{
uDcb.Bits1 = 0;
}
iRc = SetCommState(c_hCommPort, ref uDcb);
if (iRc == 0)
{
string strErrorText = Err2Text(GetLastError());
throw new clsRS232Exception(String.Concat("Unable to set COM state ",
strErrorText));
}
//setup TxRx buffers
iRc = SetupComm(c_hCommPort, c_nBufferSize, c_nBufferSize);
//now set the timeouts
SetTimeout();
//If we need events, enable them
if (c_bEnableEvents)
{
this.EnableEvents();
}
}
catch (Exception e)
{
throw new clsRS232Exception(e.Message, e);
}
}
//**************************************************************************
*************
// public void Open(int Port, int BaudRate, int DataBit, enDataParity
Parity, enDataStopBit StopBit, int BufferSize)
// Purpose : Initializes comunication port and calls Open()
// Pre-conditions : None
// Arguments : None
// Returns : None
// Post-conditions : None
//**************************************************************************
*************
public void Open(int Port, int BaudRate, int DataBit, enDataParity Parity,
enDataStopBit StopBit, int BufferSize)
{
this.Port = Port;
this.BaudRate = BaudRate;
this.DataBit = DataBit;
this.Parity = Parity;
this.StopBit = StopBit;
this.RecieveBufferSize = BufferSize;
Open();
}
//**************************************************************************
*************
// public void Close()
// Purpose : closes communications port
// Pre-conditions : None
// Arguments : None
// Returns : None
// Post-conditions : None
//**************************************************************************
*************
public void Close()
{
if (c_hCommPort != -1)
{
if (c_bEnableEvents == true)
{
this.DisableEvents();
c_bEnableEvents = true;
}
CloseHandle(c_hCommPort);
c_hCommPort = -1;
}
}
public void Write(byte[] Buffer)
{
c_OvlW = new OVERLAPPED();
int intBytesWritten = 0;
int iRc = 0;
if (c_hCommPort == -1)
{
throw new ApplicationException("Please initialize and open port before using
this method");
}
try
{
// creates the event
c_OvlW.hEvent = CreateEvent(0, 1, 0, null);
if (c_OvlW.hEvent == 0)
{
throw new ApplicationException("Error creating event for overlapped
writing");
}
//clears the IO buffers and sends the data
PurgeComm(c_hCommPort, c_conPURGE_TXCLEAR);
int intTemp = 0;
iRc = WriteFile(c_hCommPort, Buffer, Buffer.Length,ref intTemp,ref c_OvlW);
if(iRc == 0)
{
if(GetLastError() != c_conERROR_IO_PENDING)
{
throw new ApplicationException("Write command error");
}
else
{
//check tX results
if(GetOverlappedResult((int)c_hCommPort, ref c_OvlW, ref intBytesWritten, 1)
== 0)
{
throw new ApplicationException("Write pending error");
}
else
{
//are all bytes sent?
if(intBytesWritten != Buffer.Length)
{
throw new ApplicationException("Write Error - Bytes Written: " +
intBytesWritten.ToString() + " of " + Buffer.Length.ToString());
}
}
}
}
}
finally
{
CloseHandle(c_OvlW.hEvent);
}
}
public void Write(string Buffer)
{
// ASCIIEncoding aSCIIEncoding = new ASCIIEncoding();
// byte[] bs = Encoding.GetEncoding(1252).GetBytes(Buffer);
// Write(bs);
//ASCIIEncoding oEncoder = new ASCIIEncoding();
Encoding oEnc = ASCIIEncoding.GetEncoding(1252);
byte[] arrBytesToWrite = oEnc.GetBytes(Buffer);
this.Write(arrBytesToWrite);
}
public int Read(int Bytes2Read)
{
int iRc = 0;
int intReadChars = 0;
//bool bolReading;
if (Bytes2Read == 0)
{
Bytes2Read = c_nBufferSize;
}
c_OvlR = new OVERLAPPED();
if (c_hCommPort == -1)
{
throw new ApplicationException("Please initialize and open port before using
this method");
}
try
{
//get bytes from port
c_OvlR.hEvent = CreateEvent(0, 1, 0, null);
if (c_OvlR.hEvent == 0)
{
throw new ApplicationException("Error creating event for overlapped
reading");
}
//clear io buffer and read the data
PurgeComm(c_hCommPort, c_conPURGE_RXCLEAR);
c_arrRecieveBuffer = new byte[Bytes2Read - 1];
iRc = ReadFile(c_hCommPort, c_arrRecieveBuffer, Bytes2Read, ref
intReadChars, ref c_OvlR);
if (iRc == 0)
{
if(GetLastError() != c_conERROR_IO_PENDING)
{
throw new ApplicationException("Read Pending Error");
}
else
{
//Wait for chars
iRc = WaitForSingleObject(c_OvlR.hEvent, c_nTimeout);
switch(iRc)
{
case c_conWAIT_OBJECT_0:
{
//We have some data received
if(GetOverlappedResult(c_hCommPort,ref c_OvlR, ref intReadChars, 0) == 0)
{
throw new ApplicationException("Read Pending Error.");
}
else
{
return intReadChars;
}
}
case c_conWAIT_TIMEOUT:
{
throw new clsRS232Exception("Read Timeout");
}
default:
{
throw new ApplicationException("General Read Error");
}
}
}
}
else
{
return intReadChars;
}
}
finally
{
CloseHandle(c_OvlR.hEvent);
}
}
public void ClearInputBuffer()
{
if (c_hCommPort != -1)
{
PurgeComm(c_hCommPort, c_conPURGE_RXCLEAR);
}
}
public bool CheckLineStatus(enModemStatusBits Line)
{
return Convert.ToBoolean(ModemStatus & Line);
}
public void EnableEvents()
{
if (c_hCommPort == -1)
{
throw new ApplicationException("Please initialize and open port before using
this method");
}
if (c_oEvents == null)
{
c_bEnableEvents = true;
c_oEvents = new Thread(new ThreadStart(this.EventsWatcher));
//c_oEvents.Priority = ThreadPriority.Highest;
c_oEvents.Start();
}
}
public void DisableEvents()
{
if (c_bEnableEvents == true)
{
RS232 rs232 = this;
Monitor.Enter(rs232);
try
{
c_bEnableEvents = false;
}
finally
{
Monitor.Exit(rs232);
}
if (c_OvlE.hEvent != 0)
{
SetEvent(c_OvlE.hEvent);
}
c_oEvents = null;
}
}
public virtual void Dispose()
{
if (this.c_bDisposed || this.c_hCommPort == -1)
{
try
{
this.Close();
}
finally
{
this.c_bDisposed = true;
GC.SuppressFinalize(this);
}
}
}
# endregion
# region "Private Methods"
private void SetTimeout()
{
COMMTIMEOUTS uCTM;
if (c_hCommPort != -1)
{
uCTM.ReadIntervalTimeout = 0;
uCTM.ReadTotalTimeoutMultiplier = 0;
uCTM.ReadTotalTimeoutConstant = c_nTimeout;
uCTM.WriteTotalTimeoutMultiplier = 10;
uCTM.WriteTotalTimeoutConstant = 100;
SetCommTimeouts(c_hCommPort, ref uCTM);
}
}
private string Err2Text(int lCode)
{
string str;
StringBuilder stringBuilder = new StringBuilder(256);
if (FormatMessage(4096, 0, lCode, 0, stringBuilder, 256, 0) > 0)
{
str = stringBuilder.ToString();
}
else
{
str = "Error not found.";
}
return str;
}
//**************************************************************************
*************
// private void EventsWatcher()
// Purpose : Watches for all events raising events when they arrive to the
port
// Pre-conditions : None
// Arguments :
// Returns :
// Post-conditions : None
//**************************************************************************
*************
private void EventsWatcher()
{
//events to watch
enEventMasks lMask = enEventMasks.enRxChar | enEventMasks.enRXFlag |
enEventMasks.enClearToSend | enEventMasks.enDataSetReady |
enEventMasks.enCarrierDetect | enEventMasks.enBreak |
enEventMasks.enStatusError | enEventMasks.enRing;
int intBytesRead = 0;
int intTotBytes = 0;
int intErrMask = 0;
ArrayList arrBuf = new ArrayList();
COMSTAT uComStat = new COMSTAT();
c_OvlE = new OVERLAPPED();
//create the event
c_OvlE.hEvent = CreateEvent(0 , 1, 0, null);
if (c_OvlE.hEvent == 0)
{
throw new ApplicationException("Error creating event for overlapped
reading");
}
//set the mask
RS232.SetCommMask(c_hCommPort, (int)lMask);
//Look for the RxChar
while(c_bEnableEvents==true)
{
WaitCommEvent(c_hCommPort,ref lMask, ref c_OvlE);
switch(WaitForSingleObject(c_OvlE.hEvent, c_conINFINITE))
{
case c_conWAIT_OBJECT_0:
{
//Abort detected
if(c_bEnableEvents == false)
{
//break out of while loop
break;
}
if((lMask & enEventMasks.enRxChar) > 0)
{
//read incomming data
ClearCommError(c_hCommPort, intErrMask, ref uComStat);
if(intErrMask == 0)
{
//we've got to resize the array
if(uComStat.cbInQue > 0)
{
c_arrRecieveBuffer = null;
c_arrRecieveBuffer = new byte[uComStat.cbInQue - 1];
}
if(ReadFile(c_hCommPort, c_arrRecieveBuffer, uComStat.cbInQue, ref
intBytesRead, ref c_OvlE) > 0)
{
if(intBytesRead > 0)
{
//Bytes have been read, put in temporary buffer
if(intTotBytes < c_nBufThreshold)
{
arrBuf.AddRange(c_arrRecieveBuffer);
intTotBytes += intBytesRead;
}
//if the threshhold is reached, raise the event
if(intTotBytes >= c_nBufThreshold)
{
//copy the temp buffer into array
//we've got to resize the array
c_arrRecieveBuffer = new byte[intTotBytes - 1];
arrBuf.CopyTo(c_arrRecieveBuffer);
//now raise the event
try
{
RS232_CommEvent(this, lMask);
}
finally
{
intTotBytes = 0;
arrBuf.Clear();
}
}
}
}
}
}
else
{
//just raise the event
RS232_CommEvent(this, lMask);
}
break;
}//end case
default:
{
throw new ApplicationException(Err2Text(GetLastError()));
}
}//end switch
}//end while
//release hold on event
CloseHandle(c_OvlE.hEvent);
c_OvlE.hEvent = 0;
}//end eventswatcher
private void RS232_CommEvent(RS232 source, enEventMasks Mask)
{
commEvent(source, Mask);
}
# endregion
# region "Destructor"
~RS232()
{
try
{
if (!c_bDisposed)
{
if (c_bEnableEvents)
{
DisableEvents();
}
Close();
}
}
finally
{
this.Dispose();
}
}
# endregion
}
}
Any help is appreciated thanks
Marco
message news:
[email protected]...
Marco,
There are a number of things that can be going on here. Can you show
some of the code you are using to access the serial port?
--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)
Marco Martin said:
Hi,
I'm writing an application that reads a serial port and 1)updates a
list
and
sends data to a graph.
When I run the application, nothing happens unless I put a break point
anywhere in my code. then I can see the data and everything gets updated,
until the next time I put a break in the code. Otherwise, I have to
put