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 IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to know there is no Data @ Serial Port 1

Status
Not open for further replies.

seeplusplusnewbie

Programmer
Nov 14, 2004
9
US
This is actually a generalized question, but I am writing in C++, so I am putting it here:

In regards to Reading from the serial port in C++ using the Win32 API: Is there a way to know when there is no data to be read from the port without using flow control? Basically my situation is this: I am just passively reading from the serial port, I never send any data, just receive it. So I just want to read from the port until there is nothing more to be read, then go do something with the data I read, then go back and read some more. Currently, I was using a timer (specifically SetTimer()) to call the read function every 100ms, however, I was missing a lot of data this way, so I am looking for a way that would allow for all data to be receieved and buffered correctly. My connection is 115200 baud with 0% error rate, so it is simply my read function that is causing the missed data.

If anyone could lend some suggestions it will be greatly appreciated.

thanks
 
Try multi-thread solution: make COM reader thread on COM file...
 
...or overlapped i/o (see MSDN article Serial Communications in Win32, for example)...
 
thanks for the post ArkM, I had looked at that Old Post on the Win32 Serial Communication, but your post reminded me to go back and look and low and behold I found a good option. I could use CommEvents to know when there is no more data to be read from the port. I tried to implement by reading one byte at a time until the internal buffer was empty and it worked however, it is difficult to "properly" identify when the end of the data is since sometimes a byte will take a while to get there and the routine thinks thats the end of the data.

I am thinking of using the alternative to this which is the ClearCommError() function which includes a comStat structure which holds the # of byte held in the internal buffer that are yet to be read. This seems to be a good way to do it, however, I have yet to figure out how to implement it, so if anyone has used this function before, any help is appreciated.
 
Here is my current Read routine. it is called from a loop:

Code:
void CflowlogDlg::Read()
{
	HRESULT hResult = S_OK;
	DWORD dwEventMask;
	

	if(!SetCommMask(hComm, EV_RXCHAR)) hResult = S_OK;
	if(WaitCommEvent(hComm, &dwEventMask, NULL))
	{
		BYTE szBuf;
		DWORD dwIncommingReadSize;

		do
		{
			if(ReadFile(hComm, &szBuf, 1, &dwIncommingReadSize, NULL) != 0)
			{
				if(dwIncommingReadSize > 0)
				{
					dwSize += dwIncommingReadSize;
					fprintf(SerialRead, "%02X ", szBuf);
					fflush(SerialRead);
				}
			}

			else break;

		} while(dwIncommingReadSize > 0);
	}
	else {}
	fprintf(SerialRead, "\n");
}

The "break line" statement at the end of the function is designed to only execute when there is no more data left in the buffer. Here is an example of output I am getting:

48
5C 05 00 04 5C

00 00 00 00 90 00

this looks fine on the level however, I want the data to be all one line as such:

48 5C 05 00 04 5C 00 00 00 00 90 00

So as you can see in the first example there are false positives for "end of data" or "no more data". So I'd like to fix that through using ClearCommError() if possible.
 
It seems you can't solve the problem with ClearCommError() because of your comm file may be OK (no errors) but the current portion was eaten and so read op ended.
The program is a very fast thing but comm port (even if 100 kbod) is not.
May be I'm wrong but it seems the best (and classic;) solution is to create comm reader thread with (ring?) buffer then ask him for data.
Of course, this solution introduces an additional complexity dimension but (I think) it's a good investment in your application quality.
Polling based solutions looks slightly old-fashioned and have its complexity problems (you see)...
 
fair enough. Would you suggest I SetCommMask() and wait for EV_RING (A ring indicator was detected.)

Also before I failed to mention one detail:

I am neither the DTE or DCE as nothing is communicating with me directly, What I am doing is snooping on the communication of 2 other machines and getting the data that goes to and from both the DTE and DCE.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top