views:

1055

answers:

5

I am working on a Windows utility program which communicates with some custom hardware using a standard COM port. The communication protocol (which is out of my control) requires me to transmit and receive raw 8-bit data bytes.

I am currently using the following Windows API function to send data to the COM port:

WriteFile(hFile, lpBuffer, numberOfBytesToWrite, ...)

where hFile is a reference to the properly opened COM port, and lpBuffer is an array of bytes that I have stored in memory. The code works perfectly until a null character (ASCII zero) needs to be sent to the device. WriteFile stops sending as soon as it detects the null character because it assumes that it has reached the end of the string. This happens even though I set numberOfBytesToWrite properly.

How can I send raw data to the COM port using the Windows API? I would prefer to use a standard API call similar to WriteFile, but I am open to suggestions.

I am currently using RapidQ to build the utility, but all it does is call the Windows API function directly.

Edit: My setup consists of a Windows PC connected via serial port to the custom hardware module. The module has a small screen on which I am able to view the transmitted characters. I have tested this setup with another third-party utility program. I am able to communicate with the module using this third party program, and null characters show up properly. In my own program, when I use WriteFile, a null character anywhere in the transmit stream stops the rests of the stream from being sent.

+1  A: 

Serial Communications in Win32

Ed Guiness
+3  A: 

I've done Windows serial port programming before, and am sure that I have been able to send null characters through the serial ports (various file transfer protocols wouldn't have worked otherwise). I can think of two possible explanations:

  1. The receiving device is printing the data it received using a method that stops at the first null character. How are you determining that the transmitting device is terminating at the first null? Could the problem be somewhere further down the line?
  2. The serial driver is broken. This is rather unlikely, but is a possible explanation. If you are using some dodgy proprietary third party serial port and its drivers, then they might be suspect. If you are using a standard built-in serial port with the normal Windows drivers, then this is probably not a problem.

I just had a quick look at RapidQ and there's a third possible explanation:

  1. The marshaling that RapidQ may do in the process of calling Win32 API functions may have trouble with embedded null characters in the data to send. I don't know anything about RapidQ, but this is yet another link in the chain that must be considered.
Greg Hewgill
Good point. I should have made that clear in my question, but I have the receiving device display the characters on a small screen. I have tested this setup with a similar utility on the same sending computer and I was able to receive and display null characters properly.
e.James
That is why I am looking at WriteFile as the culprit. Is there a better function call to use for raw data?
e.James
WriteFile is the correct function to call, there is no lower level function.
Greg Hewgill
WriteFile is just a wrapper around the Kernel call NtWriteFile... Make sure your buffer is sending unsigned chars, if you have to send all 8 bits, or, maybe the opsite. Maybe the device is broke and you hae to send signed chars...
LarryF
Thanks, guys. I'll look deeper into the way I'm using WriteFile.
e.James
@Greg Hewgill: Your third point was correct. I changed the code to send single NULL characters individually, and everything worked. Thank you for the help!
e.James
+1  A: 

Greg is probably correct, but I would also check on your com port settings. Make sure your DCB settings are set properly. Look up SetCommState, and GetCommState for information.

Normally, Serial is 8N1, but your device might be using some other parity, or stop bit configuration, etc.

Like Greg, I've done a lot of work over serial myself, and this can often be the source of problems... Try talking with RS485 and an incorrect DCB structure... heh..

Larry

PS: If you don't already have one, I'd recommend getting yourself a good serial break-out box. I have one somewhere around the house, and it will show you what all the signals are, on all the lines during all of your communications, and is a very powerful debugging tool.

LarryF
+1  A: 

I have used WriteFile in the past and it worked fine with null bytes. I would dig into RapidQ, it could be the problem.

Rob Prouse
+1  A: 

If none of this helps, you can always do what I do. Use Greg's COMM code to test the device with. Remember Qmodem? :) Very nice tool for testing/debugging serial routines. You ccould even use Qmodem and a simple Qmodem script to read the COM port on another box (or another port in the same box), and print out the hex value of every char sent. Oh wait. Qmodem has that built in. :) Use the Debug ASCII emulation and it will show the hex values of every char that comes across the serial port. Then, you could at least verify if your code is working correctly or not.

Now, Question. Does WriteFile return when it hits the NULL, or does it just sit and wait, and never return?

If it never returns, then it may not be your code. WriteFile only returns when it has sent all dwBytesToWrite, or if there is an error. Anything else, and it's TRYING to write, but there is a failure on the other end.

LarryF