Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Problem reading from the serial port.

Status
Not open for further replies.

HyperEngineer

Programmer
May 8, 2002
190
US
I'm having a problem reading from the comm port. It is Com3:. When trying to read from the serial port the WaitForSingleObject() times out. Any ideas?

Here is my code snipet.

Code:
HANDLE hCAN;
char CAN_Port[64];
DCB dcb;
OVERLAPPED olwrite  = { 0 },
	   olread   = { 0 },
           olstatus = { 0 };

DWORD byteswritten, bytesread;
bool fDone = false;
bool readingInput = false;	      // Read operation in process
bool fSuccess = false;
char rcvData[512], buf[512];

SecureZeroMemory(CAN_Port, sizeof(CAN_Port));
sprintf_s(CAN_Port, sizeof(CAN_Port), "COM%s:", eol->CAN_CommPort);

hCAN = CreateFile(CAN_Port, 
                  GENERIC_READ | GENERIC_WRITE,  
                  0, NULL, OPEN_EXISTING, 
                  FILE_FLAG_OVERLAPPED, 
                  NULL);

if (hCAN == INVALID_HANDLE_VALUE)
{
	// return with error
	strcat_s(m_print_fail_msg, sizeof(m_print_fail_msg), "\nFailed to open comm port to CAN");
	return TEST_FAIL;
}


// Set up comm port buffers
SetupComm(hCAN, 256, 256);

// Modify DCB and send.
GetCommState(hCAN, &dcb);

// Set the baud rate, dtr = 0, rts = 0, xonxoff = 0, rtscts = 0, dtrdsr = 0,
//   parity = none, databits = 8, stopbits = 1.
dcb.BaudRate = CBR_57600;	   // Baud rate for the CAN converter
dcb.ByteSize = 8;              // 8 bits / char
dcb.StopBits = ONESTOPBIT;     // One stop bit
dcb.DCBlength = sizeof(DCB);   // Need to set this
dcb.fBinary = true;            // This must be true; Microsoft does not support non-binary mode transfers
dcb.fOutX = false;             // XON/XOFF disabled for transmit
dcb.fInX = false;              // XON/XOFF disabled for receive
dcb.fOutxCtsFlow = false;      // CTS disabled
dcb.fOutxDsrFlow = false;      // DSR disabled
dcb.fParity = false;           // No parity
dcb.fDsrSensitivity = false;   // DSR disabled
dcb.fDtrControl = DTR_CONTROL_ENABLE;  // Enables DTR line when opened, and stays on
dcb.fRtsControl = RTS_CONTROL_ENABLE;  // Enables RTS line when opened, and stays on
dcb.fInX = false;              // Disable receive XON/XOFF control
dcb.fOutX = false;             // Disable transmit XON/XOFF control

SetCommState(hCAN, &dcb);

// Only look for arrival of a character
SetCommMask(hCAN, EV_RXCHAR);

// Set events for overlapped functions.
olwrite.hEvent = CreateEvent(NULL, true, false, NULL);
olread.hEvent = CreateEvent(NULL, true, false, NULL);

// Setup RCV handles
HANDLE hRcvHandles[2] = {olread.hEvent,
	                 olstatus.hEvent};

fDone = false;
DWORD result;

while(!fDone)
{
   SecureZeroMemory(buf, sizeof(buf));
   SecureZeroMemory(rcvData, sizeof(rcvData));
   if(!ReadFile(hCAN, buf, sizeof(buf), &bytesread, &olread))
   {
	// We have an error, and the only one accepted is
	//  ERROR_IO_PENDING.  Anything else means we are in
	//  trouble.
	if(GetLastError() == ERROR_IO_PENDING)
	{
		// We are reading the input
		print_status("Waiting for input");
		readingInput = true;

		result = WaitForSingleObject(olread.hEvent, 10000);
		switch (result)
		{
		// Read completed
		case WAIT_OBJECT_0:
			if(GetOverlappedResult(hCAN, &olread, &bytesread, false))
			{
				// We returned successfully
				if(bytesread > 0)
				{
					CString myReturned;
					myReturned.Format("%s", buf);
					AfxMessageBox((LPCTSTR)myReturned, MB_OK, 0);
				}
			}	
			else
			{
				// Failed to get a result
				print_status("Did not get a response");
			}
			break;
		case WAIT_TIMEOUT:
			// No yet finished. Later put in an IdleFunction.
			AfxMessageBox("Timed out", MB_OK, 0);
			break;
		default:
			// Could be a problem here.  Handle it.
			AfxMessageBox("Problem with overlapped");
			break;
		}
	}
	else
	{
		// We failed to read response
		strcat_s(m_print_fail_msg, FAIL_MESSAGE_SIZE, "\n");
		strcat_s(m_print_fail_msg, FAIL_MESSAGE_SIZE, "Failed to get a response.");
	}
  }
  .
  .
  .
  .

thanks,


HyperEngineer
If it ain't broke, it probably needs improvement.
 
In your call to CreateEvent(), the second parameter is "true" which creates a manual reset event. I think you have to explicitly call ResetEvent( hEvent ) right after CreateEvent() to set the event to non-signaled, otherwise WaitForSingleObject() just returns immediately. At least, I am quite sure I have seen this happen before.

HTH

Greg
 
Hi Greg,

The WaitForSingleObject() does not return immediately. It times out. In this case it waits 10 seconds.

The third parameter of the CreateEvent() sets the event to the non-signalled state. I believe when I call the ReadFile() function it sets the event to the non-signalled state as well.

But I know the data is there on the port, because I can put HyperTerminal on it and it will catch the data.

thanks,

HyperEngineer
If it ain't broke, it probably needs improvement.
 
Admittedly I have only limited experience programming with the COM port, so I hope I'm not wasting your time. That being said, would using the SetCommTimeouts() function have any impact? Setting the ReadTotalTimeoutConstant and ReadTotalTimeoutMultiplier may cause the overlapped event to become signalled earlier, although these may not be relevant in overlapped or asynchronous I/O. Could it be that there just aren't sizeof(buf) bytes in the COM receive buffer? Although, even if there are not, the bytesread parameter should be set to the count of whatever is in the buffer. Sorry for just thinking out loud.

Greg
 
Greg,

Thanks for the input, but the timeouts are not necessary in overlapped mode. I'm only getting back 32 bytes and I have the buffers set for 256 bytes. I should be OK there. I know that the data gets to the port. If I put HyperTerminal on it, all the data is recovered. I have to be doing something fundamentally wrong. I, so far, can't figure it out. I am going to try to use the ClearCommError() function to peek at the rcv buffer. It it has anything, I will execute the ReadFile() function. I'll let you know how it turns out.

thanks,

HyperEngineer
If it ain't broke, it probably needs improvement.
 
Using the ClearCommError() I peeked into the rcv buffer. There were 50 bytes. Originally, I thought I was only getting 32, but there actually is 50 bytes. But the ReadFile() function still can't read the port.

HyperEngineer
If it ain't broke, it probably needs improvement.
 
hi,
to begin, use synchronous cosmunication;
leave overlapped technics, for later.
bye
victor
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top