Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C++ serialport
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
//////////////////////////////////////////////////////
// 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 12-Mar-13 5:48am
Edited 12-Mar-13 6:47am
v3
Comments
Jegan Thiyagesan at 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 at 12-Mar-13 11:49am
   
The article Serial Port I/O may help you.
Jochen Arndt at 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 at 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

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

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
  Permalink  
Comments
richcb at 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)

  Print Answers RSS
0 Maciej Los 310
1 OriginalGriff 285
2 Afzaal Ahmad Zeeshan 200
3 Sergey Alexandrovich Kryukov 195
4 BillWoodruff 180
0 OriginalGriff 6,499
1 Sergey Alexandrovich Kryukov 6,048
2 DamithSL 5,193
3 Manas Bhardwaj 4,657
4 Maciej Los 4,120


Advertise | Privacy | Mobile
Web03 | 2.8.1411022.1 | Last Updated 12 Mar 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100