Transferring data: Issue with SerialPort or device?
-
Friday, August 03, 2012 10:15 PM
I have tried this using both VS 2010 and VS 2008 to see if it made any difference but it doesn't.
My app sends data to a device sitting off my com port. Settings are default except for the main ones: 9600, N, 8, 1. Data contents are in ASCII and are packaged within an STX, ETX and LRC. The device sitting on the com port replies with an ACK when it receives data that has a correct LRC and an NAK if the LRC is incorrect. Whenever I send data, I always receive and ACK back so that implies with me the data is accurate. The problem lies in the fact that the deive does not process the data that is being sent.
As a control, I have used the same two projects (VS 2008/2010) to communicate with a different model device but has a similar message breakdown and it responds in the expected manner. As a second control, I have a VB6 app that uses the PDQComm control to send identical messages and it works with both devices.
I am logging a hex breakdown of the data and it matches the data breakdown of a port sniffer I used, just in case the .Net framework was adding extra bits. I have compared the hex breakdown of the VB6 apps and again, they are identical.
My question: is it possible that the .Net framework is parceling the data in such a way that it will make the older device accept the LRC is correct but make the data contents undecipherable? Just remember, the newer device processes the same data without issue.
The code being used:
private SerialPort port; port.PortName = string.Format("COM{0}", config.ComPort); port.BaudRate = 9600; port.Parity = Parity.None; port.DataBits = 8; port.StopBits = StopBits.One; port.ReadBufferSize = 4096; port.WriteBufferSize = 4096; port.ReadTimeout = 2000; port.WriteTimeout = 500; port.Handshake = Handshake.None; port.Open(); if (port.IsOpen) { DateTime timeout = DateTime.Now.AddSeconds(2); port.Write(data); result==DeviceResult.unset; while (result==DeviceResult.unset) { if (timeout > DateTime.Now) { try { int bytesToRead = port.BytesToRead; if (bytesToRead > 0) { byte[] buffer = new byte[bytesToRead]; port.Read(buffer, 0, bytesToRead); string temp=System.Text.Encoding.ASCII.GetString(buffer); if (temp.Length == 1 && temp == ((char)6).ToString()) { // log ACK received } else { readMessage += temp; } if (readMessage.Length > 1) { if (readMessage.Contains((char)3)) { int lastEtxPos = readMessage.LastIndexOf((char)3); if(readMessage.Length==lastEtxPos+2) { result = DeviceResult.success; } } } } } catch (Exception) { result = DeviceResult.error; } } else { result = DeviceResult.timeout; } } }
Any suggestions greatly appreciated.
All Replies
-
Saturday, August 04, 2012 2:46 PM
I have two suggestions
1) I don't think you are sending any data. I don't see any data being sent.
2) You code is very complicated. Start with something much simplier. Step through the code below slowly waiting a couple of seconds between each line of code and see if you get results.
private SerialPort port;
port.PortName = string.Format("COM{0}", config.ComPort);
port.BaudRate = 9600;
port.Parity = Parity.None;
port.DataBits = 8;
port.StopBits = StopBits.One;
port.ReadBufferSize = 4096;
port.WriteBufferSize = 4096;
port.ReadTimeout = 2000;
port.WriteTimeout = 500;
port.Handshake = Handshake.None;port.Open();
if (port.IsOpen)
{
port.Write(data);
int bytesToRead = port.BytesToRead;
byte[] buffer = new byte[bytesToRead];}
jdweng
-
Monday, August 06, 2012 12:29 PMYes, data is being sent, I didn't show the routine that populates the data. Because this is working with one device but not another, I know the contents of the data is fine. To me, it doesn't make sense why it would not work unless the SerialPort object is manipulating the data in some I don't know of.
-
Monday, August 06, 2012 12:59 PMNever jump to any conclusion until you verify that you are correct. Try the very simple code that I posted to make sure it is really the NET library. It will take only a couple of minutes to tgry the simple code I posted and will be well worth the time. I've seen too many cases like this over the years when there was a software error that caused the problem.
jdweng
-
Monday, August 06, 2012 4:02 PM
I personally stay away from BytesToRead. I would use the readBuffer size. Since you have a terminator you always know where the end is. Try the example below and see if it helps.
-
Monday, August 06, 2012 6:21 PMI added your code as a separate test method and stepped through it in debug mode. I can confirm that only one character is being returned, the ACK. No matter how long I wait before analysing the BytesToRead value, it only reports 1 character.
-
Monday, August 06, 2012 6:25 PMI modified that too, changing the terminator to 0x3 instead of 0x4. Like the above, only one character was received. I tried setting the
ReceivedBytesThreshold value to 2 and the _serialPort_DataReceived method never got invoked which makes sense if the device is only returning one character.
-
Monday, August 06, 2012 6:32 PM
An update:
I used a port sniffer and can confirm that the device is only sending back the ACK character and no other. I repeated the exercise with HyperTerminal , sending the exact same data, and it received the full response. Using the exact same data and sending to the other device, the application receives the full response. My thinking is that somehow SerialPort is restricting the older device to a one character return.
-
Monday, August 06, 2012 7:19 PM
If you have a port sniffer make sure you view the control lines and look at the data in hex mode to check if the data is being send as 8 bit no parity or 7 bit with parity. Compare the control lines settings between the working software and the non working software. Also make sure you use the same cables in both experiments. Usually in these situations settings the control line properly will solve the problem.
Occasionally you have to add more stop bits when you are running on a faster processor. I always use two stop bits to make sure I don't have any issues.
ETX (end of text = 0x03) and EOT (end of transmission = 0x04) are kind of old fashion. Make sure you follow the device specifications. Sometimes the COM drivers on the PC will filter these characters. More common these days is to end each transmission with a CR (or CRLF). Using strings with binary characters may cause problems. ASCII encoding may be changing your data to 7 bit ASCII with parity instead of 8 bit ASCII with no parity.
jdweng
-
Wednesday, August 08, 2012 4:49 PM
Ok, through trial and error, plus analysing all the properties of the port when open, I finally stumbled upon a winning combination.
Handshake=XonXoff, DtrEnable=true, RtsEnable=true.
This works for both devices. Thanks for everyone's help.
This issue is closed.
- Edited by pauldev263 Wednesday, August 08, 2012 4:50 PM
- Marked As Answer by pauldev263 Wednesday, August 08, 2012 4:51 PM

