Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

How to make Threads and how to use them in a serial communication program

Posted on 1998-01-13
5
Medium Priority
?
251 Views
Last Modified: 2013-11-20
I 'm trying to make a ReadThread for reading from port COM3 butit does not work. I want to use the WaitCommEvent,read the buffer and save in to a file or display to the monitor.
Can someone explain me how to do it?
0
Comment
Question by:hercules120197
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 

Author Comment

by:hercules120197
ID: 1313965
Adjusted points to 50
0
 
LVL 1

Expert Comment

by:JamieR
ID: 1313966
You need to:

Open the comm port using CreateFile
Then create the read thread.
return

The thread procedure should:

(loop while not exiting)
{
  Starting reading a single byte from the port.
  Do whatever you want to do with the data
}

I would suggest that you don't use WaitCommEvent as you can just do a blocking read from your read thread.

Jamie
0
 

Author Comment

by:hercules120197
ID: 1313967
I need an example because i tried to make a read thread but i does not work.
0
 
LVL 1

Accepted Solution

by:
JamieR earned 200 total points
ID: 1313968
There's an example called TTY in the Win32 SDK samples but it's fairly crude.

0
 

Expert Comment

by:mdaly
ID: 1313969
Hello,  I am an embedded systems and Visual C++ programmer.  I had to make a thread that was able to take transmit requests and then receive a response. The tricky part was that this thread also had to receive unsolicited data (unexpected data). Here is a load of code that is currently running very efficiently on my system.  Also,  I had alot of trouble making this work, not because of MFC but simply because communications is very specialized and takes alot of designed and thought(timming issues can be murderous).  Good luck.

/////////////////////////////////////////////////////////////////////
// Name:  CommThread
// Args:
// Rets:
// Info:  Thread used to handle the actual communications with
//        the external device
/////////////////////////////////////////////////////////////////////
void CommThread( void *ch )
{


   /* Open the Comm Port */
   Comm.hFile = CreateFile (
      "\\\\.\\COM2",     // address of name of the communications device
      GENERIC_READ | GENERIC_WRITE,          // access (read-write) mode
      0,                  // share mode
      NULL,               // address of security descriptor
      OPEN_EXISTING,      // how to create
      FILE_FLAG_OVERLAPPED,                  // file attributes
      NULL                // handle of file with attributes to copy
   );

   /* if open failed */
   if( Comm.hFile == INVALID_HANDLE_VALUE ) {
         FILE *test = fopen( "badhandle.txt", "w+" );
         fclose( test );

          _endthread();  /* exit thread - from _beginthread */
            return;
       
   }
   
     
   unsigned long   outnum;                  /* number of bytes sent */
   DWORD           dwEvtMask = EV_RXCHAR;  /* read characters mask */
   int             bytecnt = 0;       /* number of received bytes */
   char buf[10];                      /* store location for received bytes */
   unsigned long   bytes_read = 0;    /* number of bytes read on the last pass */
   unsigned long   pended_bytes = 0;  /* this var. has no definite use */
   DWORD           bresult;           /* return value of overlapped functions */
   char            dowait = 1;        /* flags used for a waitcommevent */
         

   /* reset the expected byte count */
   Comm.expected = 0;
   /* reset the number of bytes to transmit */
   Comm.numtx = 0;

   /* Create the comm interrupt event */
   Comm.o.hEvent = CreateEvent(0,1,0,"hevent");

   /* Set the Thread Active Event */
   SetEvent( Comm.upThread );

   /* Create the Wakeup Thread event */
   Comm.Wakeup = CreateEvent(0,1,0,"Wakeup");

   /* Create receive complete event */
   Comm.rxdone = CreateEvent(0,1,0,"rxdone");


   /* create data communications structure */
   DCB DataCom;
   /* get the current communications status */
   if( GetCommState( Comm.hFile, &DataCom ) != 0 )
   {
          /* fill the comm structure with baud-9600, Parity-N, Bits-8, StopBits-1 */
        DataCom.BaudRate = 9600;            // current baud rate
        DataCom.ByteSize = 8;             // number of bits/byte, 4-8
        DataCom.Parity = 0;               // 0-4=no,odd,even,mark,space
        DataCom.StopBits = 0;             // 0,1,2 = 1, 1.5, 2
      
        /* set the data communication structure to the current settings */
        if( SetCommState( Comm.hFile, &DataCom ) != 0 );
             
   }


   /* load array with events to wait for */
   HANDLE HArray[2];
   HArray[0] = Comm.o.hEvent;
   HArray[1] = Comm.Wakeup;


  /*----------------------------------------------------------------------------------------
   * Set the Communication timeouts - without this function a call to ReadFile or WriteFile
   * would lock up the Comm port indefinitly
   * - note:  this does not, thankfully, seem to effect the WaitCommEvent function
   *---------------------------------------------------------------------------------------- */
   COMMTIMEOUTS timeouts;

   timeouts.ReadIntervalTimeout = MAXDWORD;
   timeouts.ReadTotalTimeoutMultiplier = 0;
   timeouts.ReadTotalTimeoutConstant = 0;
   timeouts.WriteTotalTimeoutMultiplier = 0;
   timeouts.WriteTotalTimeoutConstant = 0;

      if (!SetCommTimeouts(Comm.hFile, &timeouts))
      {
         // Error setting timeouts.
            FILE *esc = fopen( "errsetcom.txt", "w+" );
            fclose( esc );
      }
   

   /* first while forever */
   while( 1 )
   {


        /* wait loop - second while forever */
            while (1)
            {
                  /* if the waitcommevent needs to posted */
                  if ( dowait )
                  {
                        /* set the wait-comm mask to kick when it sees an incomming character */
                        if( !SetCommMask( Comm.hFile, dwEvtMask ) )
                        {
                              /* report an error */
                              FILE *ecm = fopen( "errcomask.txt", "w+" );
                              fclose( ecm );
                        }

                        /* wait for the communications event */
                        if( !WaitCommEvent( Comm.hFile,       // handle of communications device
                                                       &dwEvtMask,  // address of variable for event that occurred
                                                      &Comm.o  // address of overlapped structure
 
                                                      ) )
                        {
                            /* nothing important here yet */                  
                        }
                  

                      /* Wait for a incoming data or a request for a Write data */
                      WaitForMultipleObjects( 2, HArray, FALSE, INFINITE );
                  }
      
                  /* if a request to send data */
                  if( WaitForSingleObject( Comm.Wakeup, 0 ) == WAIT_OBJECT_0 )
                              break;

              /* if the event was set by the wait-comm incoming data overlapped function */
                  if( WaitForSingleObject( Comm.o.hEvent, 0 ) == WAIT_OBJECT_0 )
                  {

                        /* see if the WaitCommEvent result was successfull, or an error occurred */
                        if( !GetOverlappedResult( Comm.hFile, &Comm.o, &pended_bytes, FALSE ) )
                        {
                                  /* report error */
                                    FILE *goot = fopen( "OverError.txt", "w+" );
                                    fclose( goot );

                        }

                        /* no solid reason for this functionallity, except to just keep track of
                         * what is happening - debug purposes */
                        if( pended_bytes > 0 )
                        {
                                  char bffs[20];
                                sprintf( bffs, "pendd%ld", pended_bytes );

                                    /* debug - report */
                                FILE *pbt = fopen( bffs, "w+" );
                                    fclose( pbt );
                        }

                        /* reset the WaitCommEvent event */
                        ResetEvent( Comm.o.hEvent );
                                                
                  }


                  /* set this so that the next pass post a new WaitCommEvent function */
                  dowait = 1;

                /* This loop will loop until no more bytes are left in the buffer.
                   * It will also direct the incomming data appropriately */
                  while( 1 )
                  {

                        /* Fetch one byte from the buffer */
                        if( !(bresult = ReadFile(
                           Comm.hFile,      // handle of file to read
                           buf,              // address of buffer that receives data  
                           1,              // number of bytes to read
                           &bytes_read,      // address of number of bytes read
                           &Comm.o           // address of structure for data
                           )) )  {
 

                              /* if in overlapped mode, then report an error.
                               * This should never happen because the comm timeout is 0 */
                              if(  (bresult = GetLastError()) == ERROR_IO_PENDING )
                              {
                                 /* wait a while for it to expire - although this should not happen
                                  * it could momentarily */
                                 if( WaitForSingleObject( Comm.o.hEvent, 1000 ) == WAIT_OBJECT_0 )
                                 {
                                       /* report what happened - debug reasons */
                                       FILE *wto = fopen( "waitout.txt", "w+" );
                                       fclose( wto );
                                 }
                                 else  {
                                    
                                       /* report error - overlapped should not have taken this long */
                                       FILE *uet = fopen( "unexpected.txt", "w+" );
                                       fclose( uet );

                                       continue;
                                 }
                              }

                              /* report some other error */
                              FILE *ste = fopen( "readerr.txt", "w+" );
                              fclose( ste );


                         }      
                    

                        /* if the byte was read from the buffer */
                         if( bytes_read >= 1 )
                         {
                              

                               /* buffer limit is 200 */
                               if( bytecnt <= 200 )
                                     /* store the received bytes */
                                     memcpy( &Comm.Recv_Buf[bytecnt], buf, bytes_read );
                           
                               /* add the number to the total number of received bytes */
                               bytecnt += bytes_read;
                               /* reset short term received bytes counter */
                               bytes_read = 0;

                               /* if this is unsolicited and the minimum amount has been received */
                               if( (Comm.expected == 0) & (bytecnt >= 7) )
                               {
                                     /* report for debug reasons */
                                     FILE *ftf = fopen( "unsolicited.txt", "w+" );
                                     fclose( ftf );

                                     /* more debug stuff */
                                     char resp[20];
                                     sprintf( resp, "rp%d,%d,%d,%d,%d,%d,%d", Comm.Recv_Buf[0], Comm.Recv_Buf[1], Comm.Recv_Buf[2], Comm.Recv_Buf[3], Comm.Recv_Buf[4], Comm.Recv_Buf[5], Comm.Recv_Buf[6] );
                                     FILE *ret = fopen( resp, "w+" );
                                     fclose( ret );

                                     /* shift bytes */
                                     //if (bytecnt <= 200) bytecnt = 200;
                                     //memmove( Comm.Recv_Buf+1, Comm.Recv_Buf, bytecnt );

                                     /* store the number of bytes received */
                                     Comm.numbytes = bytecnt;

                                     /* Check for a valid unsolicited message - do any processing  */
                                     Comm.CheckResponse();
                                     bytecnt = 0;  /* reset total bytecount */

                               }
                               /* if all the bytes have been received */
                               else if( (bytecnt >= (Comm.expected-1) ) & (Comm.expected > 0) )
                               {

                                     /* report full response count */
                                     FILE *ttg = fopen( "FullResponse.txt", "w+" );
                                     fclose( ttg );

                                     
                                     //if (bytecnt >= 200)  bytecnt = 200;
                                     //memmove( Comm.Recv_Buf+1, Comm.Recv_Buf, bytecnt );

                                     /* store the number of bytes received */
                                     Comm.numbytes = bytecnt;

                                     /* let whoever know that the message is in the bag */
                                     SetEvent( Comm.rxdone );

                                     /* reset counters */
                                     bytecnt = 0;
                                     Comm.expected = 0;
                                                                        
                               }
                                

                         } /* end if bytes_read > 0 */
                         else break;

                  }   /* end of third while forever */
                           
            } /* end second while forever */

            /* report the message is going out - debug */
            FILE *ytm = fopen( "gotowrite.txt", "w+" );
            fclose( ytm );

            /* Set the Communications mask for one purpose only - To stop the current
             * pending overlapped WaitCommEvent function - it will probably clash with
             * the WriteFile when it is called */
            dwEvtMask = EV_CTS;
            if( !SetCommMask( Comm.hFile, dwEvtMask ) )
            {
                  FILE *ecm = fopen( "errcomask.txt", "w+" );
                fclose( ecm );
            }
            dwEvtMask = EV_RXCHAR;

            /* wait for the WaitCommEvent function to signal its down */
            if( WaitForSingleObject( Comm.o.hEvent, 1000 ) != WAIT_OBJECT_0 )
            {
                  /* if WaitCommEvent never signaled,  WaitCommEvent will needed to be
                   * called again when the transmit is finished.  WriteFile will probably
                   * screw up the current WaitCommEvent.
                   * - This could cause unknown effects, but if it does happen we will
                   * at least recover */
                  dowait = 0;

                  /* report error - debug */
                  FILE *ecm = fopen( "nomask.txt", "w+" );
                fclose( ecm );
            }
            /* reset the WaitCommEvent */
            else ResetEvent( Comm.o.hEvent );

            /*----------------------------------------------------------------------------
             * Below is an algorithm flow used to send packets with a maximum size of
             * 24 bytes - if the requested transmit count is greater than split it up
             *---------------------------------------------------------------------------- */
            unsigned long nbytes = Comm.numtx;
            unsigned long byteoff = 0;

            /* if packet is larger then 24 bytes */
            if( nbytes > 24 ) Comm.numtx = 24;

            /* reset the wakeup event */
            ResetEvent( Comm.Wakeup );

            /* reorder bytes appropriately */
            DoByteOrder();
            
            /* this loop transmits large messages in packets of 24 */
            while( 1 )
            {
                  /* Transmit the request to the RTU */
                  if( !WriteFile( Comm.hFile, &Comm.outMsg[byteoff], Comm.numtx, &outnum, &Comm.o ) )
                  {
                        /* if WriteFile is pending */
                        if(  (bresult = GetLastError()) == ERROR_IO_PENDING )

                                /* Wait for it to finish */
                                if( WaitForSingleObject( Comm.o.hEvent, 30000 ) == WAIT_OBJECT_0 )
                                      ResetEvent( Comm.o.hEvent );
                  }

                  /* new offset in transmit buffer */
                  byteoff += Comm.numtx;
                  /* subtract from total bytes to send */
                  nbytes -= Comm.numtx;

                  /* if we are finished */
                  if( nbytes <= 0 )
                        break;  /* exit */

                  /* if there is still more then 24 bytes to transmit */
                  if( nbytes > 24 )
                        Comm.numtx = 24;  /* only send 24 */

                  /* otherwise just send the remaining number */
                  else Comm.numtx = nbytes;

                  
            }

            /* reset number of bytes to transmit - not really needed
             * I just put it there to protect the code from unexpected results */
            Comm.numtx = 0;

            /* Because of timing the timming issue, there is no time to go wait for an incoming
             * data event (WaitCommEvent).  The first part, if not all of the message has already
             * been received into the Comm buffer */
            dowait = 0;
            

   } /* end first while forever */
                  
   

   /* let every one else know that this thread is no longer active */
   CloseHandle(Comm.hFile);
   CloseHandle(Comm.o.hEvent);
   ResetEvent( Comm.upThread );
   CloseHandle( Comm.upThread );


   _endthread();
}




you have to organize all of the timing issues in your mind
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
Ready to get certified? Check out some courses that help you prepare for third-party exams.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Suggested Courses

596 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question