Question

I'm very new to sending data over a serial port through .net and I've noticed after implementing a TCP counterpart that I wouldn't get it that easy with serial!

So to start at the top, I am nearly there with my serial bi-directional communication implementation I am just getting stuck on a few things: -

  1. My reads are being split across multiple messages or received as a fragmented response over the COM port and I don't know what settings I might need, or how I should write the code differently to fix this. What could cause this? I am inspecting the message at a breakpoint on SerialPort_DataReceived.

Basically the data should be sent as:

01: LS|DA090521|TI111043|q
02: PS|RN102|PTC|TA1040000|P#0|DA090521|TI111429|j

but it is being split (at random positions on each requested read)

01: LS|DA090521|TI111
02: 043|q
03: PS|RN102|PTC|TA1
04: 0000|P#0|DA090521|TI111429|j

- Question 1 has been answered, thanks Chris W. and others! I now have the message I expect being built from fragments progressively (looking out for STX, {msg body}, ETX) and then an action performed when message has been completely built, and got it going with a thread-safe Queue, very happy.

. 2. I am receiving a "|" symbol through my read nearly every cycle, is this due to a command I have set wrongly somehow, an artifact of Serial communication, or something the device is sending me? (I don't think so though, as Hyperterminal connectivity reveals this character is not being sent continuously.)

. 3. Can you confirm I am reading and writing data correctly in the respective methods.

Thanks guys for looking at my other two questions too.

Relevant code as follows:

...
    //                          COM3,    9600,     None,   8,        One
    SerialPort = new SerialPort(comPort, baudRate, parity, dataBits, stopBits);
    if (SerialPort.IsOpen) SerialPort.Close();
    // SerialPort.RtsEnable = true; // Request-to-send
    // SerialPort.DtrEnable = true; // Data-terminal-ready
    SerialPort.ReadTimeout = 150; // tried this, but didn't help
    SerialPort.WriteTimeout = 150; // tried this, but didn't help
    SerialPort.Open();

    SerialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
}

void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    // Process received data
    SerialPort sp = (SerialPort)sender;
    byte[] buffer = new byte[sp.BytesToRead];
    int bytesRead = sp.Read(buffer, 0, buffer.Length);

    // message has successfully been received
    message = Encoding.ASCII.GetString(buffer, 0, bytesRead);
}

public bool SendMessage(string text)
{
    // Only send message if a client is connected
    if (SerialPort != null && SerialPort.IsOpen)
    {
        byte[] buffer = Encoding.ASCII.GetBytes(text);
        SerialPort.Write(buffer, 0, buffer.Length);
    }
}
Was it helpful?

Solution

My reads are being split across multiple messages

This is normal, expected, inevitable behaviour. It can happen with data-over-TCP as well. To the serial interface it's just an endless stream of bytes. It's your application's responsibility to repackage those bytes into packets.

If the location of packet boundaries is important, and if you can't tell where the packet boundaries are supposed to be from looking at the received data, then you may need to rethink the format of the data so that you can tell where the packet boundaries are.

I am receiving a "|" symbol through my read nearly every cycle

What's the hex value of that character? See whether setting the Handshake property to XOnXOff or RequestToSendXOnXOff improves the situation.

OTHER TIPS

At the lower level the serial port can decide when to trigger the data received event. It might decide to do that before the "full" packet has arrived. But, it looks like you have a terminator character in your expected data set. If so you can do the following (note I have changed your SerialPort assignment to avoid syntax confusion:

        p = new SerialPort(PortName, BaudRate, Prty, DataBits, SBits);
        p.NewLine = Terminator;

where Terminator is a string containing your termination character(s). Then you can use SerialPort.ReadLine() (and SerialPort.WriteLine() if that applies). This might at least help with your first issue.

I have done a lot of Win32 serial port programming, but just a little with .NET, so take my advice with a grain of salt.

My reads are being split across multiple messages or received as a fragmented response over the COM port and I don't know what settings I might need, or how I should write the code differently to fix this.

As others have said, this is perfectly normal. Depending on what type of equipment is on the DCE side, you may have to do repacking yourself. I'm not sure what type of equipment you're hooked up to so I cannot really say much more.

If you want to get more data, you can try the following:

  • adjusting the System.Int32 ReceivedBytesThreshold property
  • using synchronous I/O and specifying a fixed number of bytes to read rather than event-based reception

I am receiving a "|" symbol through my read nearly every cycle, is this due to a command I have set wrongly somehow, an artifact of Serial communication, or something the device is sending me? (I don't think so though, as Hyperterminal connectivity reveals this character is not being sent continuously.)

If you're curious about what is going over the line, check out PortMon from SysInternals, a free app that will snoop your com port while you're transferring data over the line. It seems technical, but really you just have to look at the IRP_MJ_WRITE and IRP_MJ_READ commands, and on the line you'll see the length in bytes and the data sent over the wire. With this you should be able to tell if the problem is the .NET SerialPort object or if the device is actually sending "|" over the line.

Can you confirm I am reading and writing data correctly in the respective methods.

It looks proper for the event-based method of receiving data.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top