Archived

This topic is now archived and is closed to further replies.

doctorsixstring

Serial Port I/O

Recommended Posts

I have been checking out the forums and some websites for information on sending and receiving data through a communications port. I have a custom-built loop-back plug on my com ports, allowing any data I send to be received back into the same port. I wrote a simple function to open a com port and write a string to it, but it fails to produce any results (I use HyperTerminal to watch the com port). Here is my code that doesn''t work:
  
void OpenPort()
{
	HANDLE hCom2;
	DCB dcb;
	COMMTIMEOUTS timeouts;
	char strOutput[64];
	DWORD bytesWritten;

	hCom2 = CreateFile( "COM2", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	GetCommState(hCom2, &dcb);

	dcb.DCBlength = sizeof(DCB);
	dcb.BaudRate = 2400;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	SetCommState(hCom2, &dcb);	// Apply the new comm port settings


	timeouts.ReadIntervalTimeout = MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier = 0;
	timeouts.ReadTotalTimeoutConstant = 0;
	timeouts.WriteTotalTimeoutMultiplier = 0;
	timeouts.WriteTotalTimeoutConstant = 0;
	SetCommTimeouts( hCom2, &timeouts );

	EscapeCommFunction(hCom2, SETDTR);

	strcpy(strOutput, "Hello, World!\r");
	WriteFile(hCom2, strOutput, strlen(strOutput), &bytesWritten, NULL);	

	EscapeCommFunction(hCom2, CLRDTR);
	CloseHandle(hCom2);

}
  
Any thoughts? -Mike

Share this post


Link to post
Share on other sites
Stick some error checks in there, especially on the CreateFile call; otherwise, debugging will be almost impossible. Also, I could be wrong, but shouldn''t it be "COM2:"?



Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Or maybe not... looking at the code again. I didn''t see you were trying to write to the port before closing it.
What does the variable bytesWritten contain after the call? It should tell you how many bytes were actually sent to the device.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
... do listen to sneftel, despite the coffee. I think he hit the nail on the head there, "COM2:". You may need a \\.\ at the front as well, depending on versions of windows.

Share this post


Link to post
Share on other sites
I am using GetLastError() and FormatMessage() to see the error codes returned by CreateFile().

Using the following code, the error message reads "The parameter is incorrect." I am assuming the message is referring to the first parameter, but I cannot be sure. When I attempt a write after running CreateFile(), 'bytesWritten' is set to 14 bytes ("Hello, World\r\0").

///////////////
hCom2 = CreateFile( "COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
///////////////

I have tried each of the following strings as replacements for "COM2":

"COM2:"
"\\.\\COM2:"
"\\.\\COM2"

They all return the same message "The parameter is incorrect.". But when I write, I always get 14 bytes of data written.

Just to clarify, I'm using Visual C++ 6.0 on a Win98 system (although I want the code to be fully compatible with NT-based systems, as well).

Thanks for all the replies, so far.

- Mike

[edited by - doctorsixstring on July 15, 2002 1:35:53 PM]

[edited by - doctorsixstring on July 15, 2002 1:39:15 PM]

Share this post


Link to post
Share on other sites
I have a serial-port app I''ll look at when I get home; I''m confident I''ll be able to diff the problem.

I doubt it''s the first argument that''s causing the problem; Windows would either recognize the thing as a com port (and open it) or not (and create a file somewhere). My money''s on the flags.

Share this post


Link to post
Share on other sites
Here''s our call for our serial port routines:

  
m_handle = CreateFile (str,
GENERIC_READ | GENERIC_WRITE,
0, // comm devices must be opened w/exclusive-access

NULL, // no security attrs

OPEN_EXISTING, // comm devices must use OPEN_EXISTING

FILE_FLAG_OVERLAPPED, // overlapped I/O

NULL // hTemplate must be NULL for comm devices

);

str is of the form "COM%d", no colon. Only difference here is we''re using overlapped I/O.

Share this post


Link to post
Share on other sites
Thanks for all the replies, guys. I''ve built a small class that handles opening and closing the com ports and writing to it. Part of my problem was that I was attempting to open Com2 while simutaneously viewing Com2 using HyperTerminal. Obviously, I can''t have two connections open to one com port at the same time. To get around this, I soldered a short serial cable together, with each end able to plug into a serial port. Thus, I can send data out of Com2 and view the results in HyperTerminal (which is connected to Com1).

One last question: What exactly does it mean to use Ovelapped I/O?

Share this post


Link to post
Share on other sites
Should that return an error different than ''invalid parameter''? Maybe it''s fubar on 9x - well actually we all know the comm API is fubar on 9x, but maybe the error codes don''t work either.

Overlapped IO was one of the first forms of event driven asycronous IO for Windows. It''s supported on 9x & NT kernels. On NT you have other asyncronous options that have less overhead. RS-232 is a good place to use overlapped IO. It minimizes your latency from the time data is received to the time your applications knows about it. In high-bandwidth applications overlapped IO can actually degrade performance over polling (because overlapped IO can trigger thousands of times per second, whereas you would poll upto hundreds of times per second)

I also use

m_hComFile = CreateFile(m_strComPort, GENERIC_READ|GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

Share this post


Link to post
Share on other sites
A way to check whether the CreateFile was successful: If it failed, the output (the handle to the port) returns INVALID_HANDLE_VALUE. Just check for this to see if CreateFile was successful.
BTW, "COM2" is correct.

blw

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Isn''t there a way to use the socket API interface over a COM layer? Writing COM apps with the serial API is going to introduce a lot of headaches if you want reliable transmissions. Sockets are good because it handles all the retransmissions for you.

Share this post


Link to post
Share on other sites