CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586

    Serial port WaitForMultipleObjects() problem

    The call to WaitForMultipleObjects() does not return, it seems the event for the serial port does not get signalled. I was under the impression that sending data to the port will cause the event to be signalled. Am i doing something wrong here?

    Code:
    UINT CMyserialportView::ReaderThread(LPVOID p)
    {
    	TRACE("\nThread ReaderThread() >");
    
    	CSerialParameters* parms = (CSerialParameters *)p;
    	OVERLAPPED ovl = {0};
    	ovl.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
    	if(ovl.hEvent == NULL)
    	{ /* failed */
    		DWORD err = ::GetLastError();
    		parms->m_pWndNotifyee->PostMessage(UWM_READER_SHUTTING_DOWN, (WPARAM)err);
    		return 0;
    	} /* failed */
    
    	DWORD shutdown;  // reason for shutdown
    	HANDLE waiters[2];
    	waiters[0] = parms->m_hShutdown;
    	waiters[1] = ovl.hEvent;
    	
    #define MAX_BUFFER_SIZE 100
        BOOL running = TRUE;
        DWORD bytesRead;
        while(running)
           { /* read loop */
            BYTE buffer[MAX_BUFFER_SIZE];
            BOOL ok = ::ReadFile(parms->m_hCom, buffer, MAX_BUFFER_SIZE - 1, &bytesRead, &ovl);
            if(!ok)
            { /* error */
               DWORD err = ::GetLastError();
               if(err != ERROR_IO_PENDING)
               { /* read error */
    				shutdown = err;
    				running = FALSE;
    				continue;
               } /* read error */
               
    		   // otherwise, it is ERROR_IO_PENDING
               DWORD result = ::WaitForMultipleObjects(2, waiters, FALSE, INFINITE);
    		   //DWORD result = ::WaitForSingleObject(ovl.hEvent, INFINITE);
               switch(result)
               { /* wait */
    				case WAIT_OBJECT_0:  // shutdown
    					::CancelIo(parms->m_hCom);
    					shutdown = ERROR_SUCCESS;  // clean shutdown
    					running = FALSE;
    					continue;
    				case WAIT_OBJECT_0 + 1: // I/O complete
    					ok = ::GetOverlappedResult(parms->m_hCom, &ovl, &bytesRead, TRUE);  
    					if(!ok)
    					{ /* GetOverlappedResult failed */
    						DWORD err = ::GetLastError();
    						running = FALSE;
    						continue;
    					} /* GetOverlappedResult failed */
    					break;
    				default:
    				{ /* trouble */
    					 shutdown = ::GetLastError();
    					 ASSERT(FALSE); // failure
    					 running = FALSE;
    					 continue;
    				} /* trouble */
                } /* wait */  
            } /* error */
    
            // if we get here, either the ReadFile worked immediately, or we waited for completion
            if(bytesRead == 0)
               continue; // nothing was read
            buffer[bytesRead] = '\0'; // assumes 8-bit characters without embedded NUL
            CString* s = new CString((LPCSTR)buffer);
            parms->m_pWndNotifyee->PostMessage(UWM_DATA_READ, (WPARAM)s);
        } /* read loop */
    
        parms->m_pWndNotifyee->PostMessage(UWM_READER_SHUTTING_DOWN, (WPARAM)shutdown);
        ::CloseHandle(ovl.hEvent);
        return 0;  // we're gone. You may choose to do something different
    } // CMyClass::ReaderThread
    Time is fun when you're having flies

  2. #2
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Serial port WaitForMultipleObjects() problem

    WaitForMultipleObjects waits for all objects, so perhaps it is the other event, parms->m_hShutdown, that is not signalled?

    Regards / Z
    Nobody cares how it works as long as it works

  3. #3
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586

    Re: Serial port WaitForMultipleObjects() problem

    No i pass in FALSE as one of the parameters which means if one of the parameters is signalled the WaitForMultipleObjects() returns.

    bWaitAll
    [in] If this parameter is TRUE, the function returns when the state of all objects in the lpHandles array is signaled. If FALSE, the function returns when the state of any one of the objects is set to signaled. In the latter case, the return value indicates the object whose state caused the function to return.
    Time is fun when you're having flies

  4. #4
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Serial port WaitForMultipleObjects() problem

    And you did open the com port with FILE_FLAG_OVERLAPPED ?

    Regards / Z
    Nobody cares how it works as long as it works

  5. #5
    Join Date
    Mar 2003
    Location
    The Netherlands
    Posts
    586

    Re: Serial port WaitForMultipleObjects() problem

    This is the OnInitialUpdate() in which i open the serial port and create/start the threads.....

    Code:
    void CMyserialportView::OnInitialUpdate() 
    {
    	CView::OnInitialUpdate();
    	
    	m_hCom = ::CreateFile(	"\\\\.\\COM2",		// filename
    			GENERIC_READ|GENERIC_WRITE,	// desired access
    			0,							// exclusive
    			NULL,						// security irrelevant
    			OPEN_EXISTING,				// it has to be there
    			FILE_FLAG_OVERLAPPED,		// open asynchronous
    			NULL);						// template file
    	
    	if(m_hCom == NULL)
    	{
    		AfxMessageBox("Failed to open COM port", 0);
    		return;
    	}
    
    	// Create writer thread
    	m_pSerialWriter = (CSerialWriter*)AfxBeginThread(	
    		RUNTIME_CLASS(CSerialWriter),	
    		THREAD_PRIORITY_NORMAL,			// priority
    		0,								// default stack size
    		CREATE_SUSPENDED);				// don't run right away
    
    	if(m_pSerialWriter == NULL)
    	{
    		AfxMessageBox("Could not create writer thread",0);
    		return;
    	}
    
    	HANDLE m_hShutDown = ::CreateEvent(NULL, TRUE, FALSE, NULL);
    	if(m_hShutDown == NULL)
    	{
    		AfxMessageBox("Could not create shutdown event",0);
    		return;
    	}
    
    	m_pSerialWriter->m_pParameters = new CSerialParameters(m_hCom, this, m_hShutDown);
    	m_pSerialWriter->ResumeThread();
    
    	CString* myS = new CString("010203040506070809A0010203040506070808");
    	m_pSerialWriter->PostThreadMessage(UWM_DATA_SEND, (WPARAM)myS, (LPARAM)0);
    
    	// Create reader thread
    	AfxBeginThread(ReaderThread, m_pSerialWriter->m_pParameters);
    
    }
    Time is fun when you're having flies

  6. #6
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: Serial port WaitForMultipleObjects() problem

    After opening the port (::CreateFile(...) ) you have to set the DCB (GetCommState/SetCommState) and port TIMEOUTs (GetCommTimeouts/SetCommTimeouts), something like:
    Code:
    // declared in header:    	COMMTIMEOUTS m_CommTimeOuts;
    	.......
    	if(::GetCommTimeouts(m_hCom, &m_CommTimeOuts))
    	{
    		COMMTIMEOUTS TimeOuts(m_CommTimeOuts);
    		//	correct these values
    		TimeOuts.ReadIntervalTimeout		= 100;
    		TimeOuts.ReadTotalTimeoutConstant	= 100;
    		TimeOuts.ReadTotalTimeoutMultiplier	= 10;
    		TimeOuts.WriteTotalTimeoutConstant	= 10;
    		TimeOuts.WriteTotalTimeoutMultiplier= 100;
    		if(::SetCommTimeouts(m_hCom, &TimeOuts))
    		{
    		      // ready to work with the port to read...
    Otherwise, your reader thread might hang on waiting for the next character.

  7. #7
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Serial port WaitForMultipleObjects() problem

    If VictorN's suggestion does not help, plz post code for CSerialWriter also
    Nobody cares how it works as long as it works

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured