views:

50

answers:

3

i am writing a method which sends a particular packet and gets an answer back from an electronic device. I am using system.io.ports with rtsEnabled = true.

The problem is that when entering the application the received packet is altered. I am monitoring what is being received using eltima and the packet received by eltima and that by the application have two bytes different.

The application is changing every byte which is double in hex (example FF or BB) to 3F. The following is what Eltima is giving:

5b 00 00 09 32 13 31 33 35 36 31 39 31 30 30 38 32 35 00 01 ff 64 01 00 bb 0f 5d --Eltima

5B 00 00 09 32 13 31 33 35 30 32 37 31 30 30 38 32 35 00 01 3F 64 01 00 3F 04 5D --MyApplication

The following is my code:

public string MakeSerialConnection(string COM, int baud, string dest)
    {
        SerialPort port = new SerialPort(COM, baud, Parity.None, 8, StopBits.One);
        try
        {
            if (!(port.IsOpen))
            {
                string destination = dest;
                //BUILD PACKET FOR SENDING
                byte[] fullPacket = BuildPacket(destination);
                port.Open();
                port.RtsEnable = false;

                port.Handshake = Handshake.None;

                //SEND PACKET TO DEVICE
                port.Write(fullPacket,0,9);

                #region RECEIVE DATA FROM SERIAL
                //MAKE PROCESS STOP FOR 5sec
                Thread.Sleep(240);

                port.RtsEnable = true;

                Thread.Sleep(1000);
                string reading = port.ReadExisting();
               // int readingint = port.ReadByte();

                    port.Close();
                    port.Dispose();
                    return reading;
                #endregion
            }
            else
            {
                return "";
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            if (port != null)
            {
                //port.Close();
                if (port.IsOpen)
                {
                    port.Close();
                }
                port.Dispose();
            }

        }

Please help me figure out why this is happening

A: 

What does the device spec say about the Handshaking? You might have to set the handshake to RequestToSend. Also, If possible, use the DataReceived to receive data rather than sleeping.

I would also check the Encoding of the serial port to make sure it matches what the device is using. The default is ASCIIEncoding, so if the device is using something else (ex: Unicode) you'll need to change it.

SwDevMan81
handshake is not the issue and i doubt that the problem with encoding since other packets are being received good.the data in this packet all matches up except where the values in hex are the same (eg bb or ff)
IanCian
@IanCian - Encoding will actually change the bytes if it doesn't recognize it. See this post as an example: http://stackoverflow.com/questions/2714533/how-to-apply-encoding-when-reading-from-a-serial-port
SwDevMan81
That encoding doesn't support bytes with the high bit set and translates them to '?' (3F in hex is the "?").
SwDevMan81
Try encoding 28591
dbasnett
+1  A: 

It you look in an ASCII code chart, you'll see the 0x3f is the character code for ?. That's the substitution character you'll get when Encoding.GetString() cannot convert a byte value to a character. Makes sense, the default SerialPort.Encoding is ASCII, 0xff is not a valid character code in that encoding.

The root problem is that you are reading strings. But the device is not sending strings, it is sending bytes. You must use SerialPort.Read() instead of ReadExisting().

Hans Passant
@Hans - Couldn't the OP just change the Encoding of the SerialPort and still use the ReadExisting() call?
SwDevMan81
@SwDev: bytes cannot be mapped 1-to-1 to a string, those days are over. Lots of byte values don't have a corresponding codepoint in Unicode.
Hans Passant
Agreed with Hans, that is my analysis as well.
Lily
If I am not mistaken encoding 28591 is a direct mapping of byte values received.
dbasnett
+1  A: 

Do not place your read bytes into a string. As stated by SwDevMan, you're not sending a string through the port but a byte array. As good practice, avoid casting your data into types that don't belong. Sometimes, the code behind the framework changes the data without your knowledge.

Use Read() or ReadByte() and place your bytes into an array or bytes or list that you will build. Read() is the logical way but ReadByte has it's uses. Using ReadByte() will read one byte at a time. If you are expecting the first byte to be a special flag, a start of command flag for instance, you can immediatly validate it and choose to either discard or continue reading.

        while (serialport.BytesToRead > 0)
        {
            startingByte= Convert.ToByte(serialport.ReadByte());
            CheckIfStartOfCommand(startingByte)
            ...
        }

Otherwise, use Read() to get a certain number of bytes into a preset array.

Lily