// You need to include this procedure your project, and also outside of it, // you need these global variables, which you can set accordingly // - for an MSVC project of it and more details // see http://tunesmithy.co.uk/comportmonitor.htm int icom=1; char start_up=1; char use_existing_settings; HANDLE hEndComPortEvent; int BaudRate=2400; int ByteSize=8; int Parity=NOPARITY; // EVENPARITY // ODDPARITY // To start the thread use // _beginthread(MonitorComPort,0,NULL); // Whenever you change any settings, use the same call // - the thread will end any other copy of it that // is running before it starts, so there is no need // to do that yourself. // When finished, call SetEvent(hEndComPortEvent); // To test if it is still running, check to see // if hEndComPortEvent is non zero. void MonitorComPort(void *pvoid) { // minimal version with no error reporting or indications of // progress apart from data received. HANDLE hCom=0; BOOL bPortReady=0; DCB dcb; COMMTIMEOUTS CommTimeouts; OVERLAPPED overlapped; BOOL fSuccess=0; DWORD dwEvtMask=0; int nEvents=0; int ii=0; char szCom[STRMAX]; static char com_running; char szmsg[STRMAX]; sprintf(szCom,"com%d",icom); memset(&dcb,0,sizeof(DCB)); if(hEndComPortEvent) { SetEvent(hEndComPortEvent); Sleep(200); { int ii=0; for(ii=0;ii<20;ii++) { Sleep(50); if(hEndComPortEvent==0) break; } } if(hEndComPortEvent) // couldn't close the thread return; } hCom = CreateFile (szCom ,GENERIC_READ // | GENERIC_WRITE, ,0, // exclusive access NULL, // no security OPEN_EXISTING, FILE_FLAG_OVERLAPPED, // overlapped I/O NULL // null template ); if(hCom==INVALID_HANDLE_VALUE) { sprintf(szmsg,"Couldn't open Com port %d",icom); AddEvent(szmsg); return; } if(!hEndComPortEvent) hEndComPortEvent = CreateEvent ( NULL, // no security attributes TRUE, // auto reset event FALSE, // not signaled NULL // no name ); memset(&dcb,0,sizeof(dcb)); dcb.DCBlength=sizeof(dcb); SetupComm(hCom, MAX_BUFF, MAX_BUFF); // set buffer sizes GetCommState(hCom, &dcb); // 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. if(use_existing_settings) { Parity=dcb.Parity; BaudRate=dcb.BaudRate; ByteSize=dcb.ByteSize; } else { dcb.DCBlength = sizeof ( DCB ) ; dcb.BaudRate = BaudRate; dcb.ByteSize = (BYTE) ByteSize;// number of bits/byte, 4-8 dcb.Parity=Parity; dcb.fParity=Parity==NOPARITY?0:1; dcb.StopBits = ONESTOPBIT; // options are 0,1,2 = 1, 1.5, 2 - this is a matter of the amplitude of the stop bit signal // which is why you have fractional values dcb.fOutxCtsFlow = 0; dcb.fOutxDsrFlow = 0; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fDsrSensitivity = 0; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fOutX = 0; dcb.fInX = 0; dcb.fErrorChar = 0; dcb.fBinary = 1; dcb.fNull = 0; dcb.fAbortOnError = 0; dcb.wReserved = 0; dcb.XonLim = 2; dcb.XoffLim = 4; dcb.XonChar = 0x13; dcb.XoffChar = 0x19; dcb.EvtChar = 0; } SetCommState(hCom, &dcb); // Now do the time outs - use MAXDWORD if unsure 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. 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(fSuccess) { HANDLE hArray[2]; DWORD dwError=0; COMSTAT comState; hArray[0]=overlapped.hEvent; hArray[1]=hEndComPortEvent; ClearCommError(hCom,&dwError,&comState); sprintf(szmsg,"Com port %d opened and initialised successfully",icom); AddEvent(szmsg); // 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. for(;;) { int iBytesRead=0; char szData[MAX_BUFF]; int read_loops=0,read_loops_since_data=0; WaitCommEvent(hCom, &dwEvtMask,&overlapped); ClearCommError(hCom,&dwError,&comState); 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]); sprintf(szmsg,"Close request for Com port %d",icom); AddEvent(szmsg); goto end_thread; case WAIT_FAILED:; } if(end_com_threads) goto end_thread; for(;;) { int iBytesReadThisTime=0; int iBytesWas=iBytesRead; BOOL bRead; if(end_com_threads) goto end_thread; 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'; if(szData[0]!='\0') { // do whatever you like with the data } } } end_thread:; if(hCom) { PurgeComm(hCom,PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_TXABORT); CloseHandle(hCom); hCom=0; } if(hEndComPortEvent) CloseHandle(hEndComPortEvent); hEndComPortEvent=0; }