Inventive Software
For Windows
Home Music 3D Art Utilities Source Code Search Site Forums About Me Contact Accessibility
Mem Leak Check
Play Midi Lib
Com Ports Monitor
Win Ming
Pop Pal Fast
Gle with time out
Time64

Com Port Monitor

Updated June 27 2003

Intro, In a nutshell, Source code, MSVC project, Changes

Intro, In a nutshell, Source code, MSVC project

Intro

I recently had to do some programming to listen to a com port for the Lambdoma Keyboard interface for my Fractal Tune Smithy program. It took a lot of searching on the web to find out how to do it and I got the impression that there is a fair amount of confusion about how it is done.

So, here is an example to show how to program it, kept simple, so one can read it and easily understand how the code works.

It's for reading only, as that is all I've needed to do. However it seems from the documentation that writing is similar so I think one should have no problem converting it to do that as well once one understands this.

There really isn't much to it once one understands that it is overlapped i/o and one has to set and reset events to keep track of that - but rather a lot of false trails one can follow on the way to understanding that!.

top

In a Nutshell

In a nutshell, this is what you have to do:

When you start the thread, or before you start it,
you make an event which will be set to signalled to stop 
it if needed. 
hEndComPortEvent = CreateEvent
 (
  NULL,   // no security attributes 
  TRUE,  // auto reset event 
  FALSE,  // not signaled 
  NULL    // no name 
 );
Now in the thread, what you do is:

char *szComm[]= "com1"; // or "com2" etc.
HANDLE hCom;

 hCom = CreateFile
  (szComm,GENERIC_READ 
		 ,0, // exclusive access
		 NULL, // no security
		 OPEN_EXISTING,
		 FILE_FLAG_OVERLAPPED, // overlapped I/O
		 NULL  // null template 
  );

Has to be overlapped i.o. so that the com port monitor thread can
be closed without using TerminateThread - if you want
to stop and start it anyway - e.g. to change any of the settings 
while it is running.

if(hCom)
{
 DCB      dcb;
 SetupComm(hCom, MAX_BUFF, MAX_BUFF); // set buffer sizes
 GetCommState(hCom, &dcb);

 // Then set all the parameters in the dcb structure that you need to
 // set - if you want to use the existing values, don't need to do anything
 // here.

 // Now do the time outs - use MAXDWORD if unsure
 COMMTIMEOUTS CommTimeouts;

 SetCommState(hCom, &dcb);
 GetCommTimeouts(hCom, &CommTimeouts);
 CommTimeouts.ReadIntervalTimeout = MAXDWORD;//100;
 CommTimeouts.ReadTotalTimeoutConstant = 0;//100;
 CommTimeouts.ReadTotalTimeoutMultiplier =0;// 50;
 CommTimeouts.WriteTotalTimeoutConstant = 0;//100;
 CommTimeouts.WriteTotalTimeoutMultiplier = 0;//50;
 bPortReady = SetCommTimeouts(hCom, &CommTimeouts);

 // Make an overlapped structure for i.o.

 OVERLAPPED overlapped;
 // be sure to intialised all the fields of overlapped to 0 - if you don't
 // do this, it causes an error in XP - though it works fine in 9x.
 memset(&overlapped,0,sizeof(overlapped));
  overlapped.hEvent = CreateEvent(
   NULL,   // no security attributes 
   TRUE,  // auto reset event 
   FALSE,  // not signaled 
   NULL    // no name 
   );


 // Set the mask for the events you want to listen for
 fSuccess = SetCommMask
  (hCom,EV_RXCHAR | EV_RXFLAG);

  // If all is well, go into a loop looking for data

  // Now here the thing is that we read the data as overlapped.
  // So WaitCommEvent will return immediately - and set the
  // handle in its overlapped structure when data arrives.



  if(fSuccess)
  {
   DWORD dwError=0;
   COMSTAT comState;
   HANDLE hArray[2];// an array of events to pass to WaitForMultipleObjects 
   hArray[0]=overlapped.hEvent;
   hArray[1]=hEndComPortEvent;
   ClearCommError(hCom,&dwError,&comState); 
   for(;;)
   {
    WaitCommEvent(hCom, &dwEvtMask,&overlapped); // wait for data - but this
                                                 // will return immediately because
                                                 // it is overlapped
    ClearCommError(hCom,&dwError,&comState); 
    // wait for either of the two events to get signalled
    // - the one from WaitCommEvent or the one you set yourself
    // to end this thread
    switch(WaitForMultipleObjects(2,hArray,FALSE, INFINITE))
    {
     case WAIT_OBJECT_0:// input pending - this is the first of the array
                        // entries, i.e. overlapped.hEvent
      ResetEvent(hArray[0]);// reset the event to not signalled
      break;
     case WAIT_OBJECT_0+1:// this is the one to end the thread
      ResetEvent(hArray[1]);
      goto end_thread;
     case WAIT_FAILED:;
    }
    // now we can get the data
    for(;;)
    {
     int iBytesReadThisTime=0;
     int iBytesWas=iBytesRead;
     BOOL bRead;
     if(end_com_threads)
      goto end_thread;
     // you need to pass &overlapped again as the final argument to ReadFile
     bRead= ReadFile(hCom, &szData[iBytesRead], MAX_BUFF-iBytesRead-1, &iBytesReadThisTime,&overlapped);
     iBytesRead+=iBytesReadThisTime;
     if(bRead==FALSE&&GetLastError()==ERROR_IO_PENDING)
     {
      Sleep(2);
      read_loops++;
      continue;
     }
     else
     // we have got it all now
      break;
    }
    szData[iBytesRead]='\0';
   }
 // Clean up - just close the handle. PurgeCom just in case we
 // stopped it in the middle of something.

 end_thread:;
 if(hCom)
 {
  PurgeComm(hCom,PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_TXABORT);
  CloseHandle(hCom);
  hCom=0;
 }
top

Source code

So, here is the source code:

ComPortsMonitor.txt

top

 

MSVC project

Here you can download a zip of the example program using this procedure.

ComPortsMonitor.zip

top

 

Changes

June 27 2003

Changed the ADD_ERROR(...) macro to an AddError(...) routine.

ComPortsMonitor.zip

April 5 2003

Release

top

Disclaimer Acceptable Use Copyright Privacy  

Site Designed with advice from Sojo Media (Thanks!)

Popups by overLIB!