Click here to Skip to main content
15,884,739 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi All,
Hopefully someone can point out the error of my ways. Below is the code I have for opening and writing data to a serial port. I know its propbably nowhere near perfect but its where I am!.
I have checked the serial port is working correctly with a serial port monitor tool.
There are no compilation or linking errors with the code, I also do not get any errors reported using GetLast Error.

I think I have narrowed the error down to there area marked in BOLD below in the WriteData function.
There is data in the out buffer of size [58], but the dwBytesSent when looked at after the call to ComStat.cbInQue, equals 0, so no data is then tramsmited.

I'm totally guessing that theres some error in the overlapped operation as if I delete this section I get error code 997.

Any help to rectify this or a way round it would be most appreciated. I have looked at many examples on the internet, forums and MSDN but cannot see where the error may be. Most other examples look the same.

cheers for looking.
Daz
C#
//////////////////////////////////////////////////////
// Opens specified com port at specified rate
//////////////////////////////////////////////////////
BOOL CSerial::OpenComPort( const char* nPort, int nBaud )
{

	if( m_bOpened ) return( TRUE );

	DCB dcb;

	comport = CreateFile( nPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 
		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );

	if( comport == NULL ) 
		return( FALSE );
	if (comport == INVALID_HANDLE_VALUE)
	{
		printf("Create file failed with error %d.\n", GetLastError());
		return (FALSE);
	}

	memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
 	memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

	COMMTIMEOUTS CommTimeOuts;
	CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 0;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
	CommTimeOuts.WriteTotalTimeoutConstant = 0;
	SetCommTimeouts( comport, &CommTimeOuts );

	m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
	
	dcb.DCBlength = sizeof( DCB );
	GetCommState( comport, &dcb );
	dcb.BaudRate = nBaud;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.fParity = FALSE;
	dcb.StopBits = ONESTOPBIT;
	unsigned char ucSet;
	ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
	ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
	ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );

	if( !SetCommState( comport, &dcb ) || !SetupComm( comport, 10000, 10000) ||	
		m_OverlappedRead.hEvent == NULL ||	m_OverlappedWrite.hEvent == NULL ) 		
		{
			DWORD dwError = GetLastError();
			if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
			if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
				CloseHandle( comport );
			printf("SetCommState file failed with error %d.\n", GetLastError());
			return( FALSE );
		}

	m_bOpened = TRUE;

	printf(TEXT("baud = %d, databits = %d, Parity = %d, Stop = %d\n"), 
		dcb.BaudRate, dcb.ByteSize, dcb.fParity, dcb.StopBits);
	printf(TEXT("Port = %s\n"), nPort);
	return( m_bOpened );

}


//////////////////////////////////////////////////////
// Write data output
//////////////////////////////////////////////////////

int CSerial::WriteData( void *OutBuffer, int limit )
{
	if( !m_bOpened || comport == NULL ) return( 0 );

	BOOL bWriteStatus;
	DWORD dwBytesSent, dwErrorFlags;
	COMSTAT ComStat;

	ClearCommError( comport, &dwErrorFlags, &ComStat );
	printf("limit in is = %i\n", limit);

	if( !ComStat.cbInQue) 
	{
		dwBytesSent = (DWORD) ComStat.cbInQue;
	}
	if( limit < (int) dwBytesSent ) 
	{
		dwBytesSent = (DWORD) limit;
	}	printf("data buffer to be sent is = %s\n", OutBuffer);
	printf("dwBytesSent = %i\n", dwBytesSent);

	bWriteStatus = WriteFile (comport, OutBuffer, dwBytesSent, &dwBytesSent, &m_OverlappedWrite);

	GetOverlappedResult(comport, &m_OverlappedWrite, &dwBytesSent, TRUE);
		
	if( !bWriteStatus )
	{
		printf("writestatus  failed with error %d.\n", GetLastError());
	}
	else
	{
		if( GetLastError() == ERROR_IO_PENDING )
		{
			WaitForSingleObject( m_OverlappedRead.hEvent, 17 );
			printf("writestatus  failed with error %d.\n", GetLastError());
			return( (int) dwBytesSent );
			return( 0 );
		}
	}

	printf("dwBytesSent is %i\n", dwBytesSent);
	
	return( (int) dwBytesSent );
}
Posted
Updated 12-Mar-13 5:47am
v3
Comments
Jegan Thiyagesan 12-Mar-13 11:45am    
If you tag this as C++, you might get effective answer. I wonder how many C#ers know c++ :).
Richard MacCutchan 12-Mar-13 11:49am    
The article Serial Port I/O may help you.
Jochen Arndt 12-Mar-13 15:31pm    
Why you are setting dwBytesSend to zero when ComStat.cbInQue is zero?
ComStat.cbInQue is the number of bytes that are available for retreiving (has been received but not yet been read). If there are none, you will call WriteFile() with zero for the number of bytes. If ComStat.cbInQue is not zero, dwBytesSend is not initialized.

With overlapped IO, WriteFile() will return FALSE due to ERROR_IO_PENDING. In this case you should wait and then call GetOverlappedResult() (after waiting, not before):
if (WriteFile())
// success, data has been written immediately, dwBytesSend is valid
else if (ERROR_IO_PENDING == GetLastError())
{
if (WAIT_OBJECT1 == WaitForSingleObject())
{
GetOverlappedResult();
// Success, dwBytesSend contains now the number of bytes
}
}
Member 9761090 13-Mar-13 6:06am    
many thanks for your inputs, using this and another trawl though the net I now have data transmitting from the serial port. There are many other issues I have so I maybe back later, but thanks again, cheers

1 solution

Thanks for your input, I have added the initailisation but the problem still exists. I have debugged the code slightly further, and it appears to enter the code you point out, so there is a problem with Comstat.cbInQue, which is then making dwBytesSent = 0.
What is it that could fail Comstat.cbInQue?, apologies if this is simple stuff.
Also should it be cbOutQue for a write function, which also doesnt work?
cheers
 
Share this answer
 
Comments
Richard C Bishop 12-Mar-13 12:22pm    
Use the "Have a Question or Comment?" button to ask questions or post comments. You posted this as a solution.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900