views:

692

answers:

3

I have a WPF test app for evaluating event-based serial port communication (vs. polling the serial port). The problem is that the DataReceived event doesn't seem to be firing at all.

I have a very basic WPF form with a TextBox for user input, a TextBlock for output, and a button to write the input to the serial port.

Here's the code:

public partial class Window1 : Window
{
    SerialPort port;

    public Window1()
    {
        InitializeComponent();

        port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
        port.DataReceived +=
            new SerialDataReceivedEventHandler(port_DataReceived);  
        port.Open();
    }

    void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        Debug.Print("receiving!");
        string data = port.ReadExisting();
        Debug.Print(data);
        outputText.Text = data;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Debug.Print("sending: " + inputText.Text);
        port.WriteLine(inputText.Text);
    }
}

Now, here are the complicating factors:

  1. The laptop I'm working on has no serial ports, so I'm using a piece of software called Virtual Serial Port Emulator to setup a COM2. VSPE has worked admirably in the past, and it's not clear why it would only malfunction with .NET's SerialPort class, but I mention it just in case.

  2. When I hit the button on my form to send the data, my Hyperterminal window (connected on COM2) shows that the data is getting through. Yes, I disconnect Hyperterminal when I want to test my form's ability to read the port.

  3. I've tried opening the port before wiring up the event. No change.

I've read through another post here where someone else is having a similar problem. None of that info has helped me in this case.

EDIT:

Here's the console version (modified from http://mark.michaelis.net/Blog/TheBasicsOfSystemIOPortsSerialPort.aspx):

class Program
{
    static SerialPort port;

    static void Main(string[] args)
    {
        port = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
        port.DataReceived +=
            new SerialDataReceivedEventHandler(port_DataReceived);
        port.Open();

        string text;
        do
        {
            text = Console.ReadLine();
            port.Write(text + "\r\n");
        }
        while (text.ToLower() != "q");
    }

    public static void port_DataReceived(object sender,
        SerialDataReceivedEventArgs args)
    {
        string text = port.ReadExisting();
        Console.WriteLine("received: " + text);
    }
}

This should eliminate any concern that it's a Threading issue (I think). This doesn't work either. Again, Hyperterminal reports the data sent through the port, but the console app doesn't seem to fire the DataReceived event.

EDIT #2:

I realized that I had two separate apps that should both send and receive from the serial port, so I decided to try running them simultaneously...

If I type into the console app, the WPF app DataReceived event fires, with the expected threading error (which I know how to deal with).

If I type into the WPF app, the console app DataReceived event fires, and it echoes the data.

I'm guessing the issue is somewhere in my use of the VSPE software, which is set up to treat one serial port as both input and output. And through some weirdness of the SerialPort class, one instance of a serial port can't be both the sender and receiver. Anyway, I think it's solved.

+1  A: 

I can't say for sure, but there could be a threading issue. WPF handles threading differently, and the polling of the virtual port is asynchronous, I believe. Have you tried this with a Windows Forms or console application to prove that it can work at all?

Dave Swersky
See the console version above. No luck.
Klay
+2  A: 

I use the exact same setup, it works perfectly now but had to solve many many problems to get there.

Here is why my initial declaration looks like:

comControl = new SerialPort();

//This is important - determine your min nb of bytes at which you will fire your event, mine is 9
comControl.ReceivedBytesThreshold = 9; 

//register the event handlers
comControl.DataReceived += new SerialDataReceivedEventHandler(OnReceive);
comControl.PinChanged += new SerialPinChangedEventHandler(OnPinChanged);

I seperated the open port and close port methods since i often check if the com port has been closed.

public bool OpenPort()
{
    try
    {
        //must keep it open to maintain connection (CTS)
        if (!comControl.IsOpen)
        {
             comControl.Open();
             comControl.RtsEnable = true;
        }
    }
    catch (Exception e)
    {
        //error handling here
    }
}

Lastly, verify that your Virtual Com Port driver is installed properly and that you are using the right port, a plug and play for my adapter was not enough. If you want to create a sort of control that will allow you to pick the ports available at runtime, the following command will give you the available ports:

System.IO.Ports.SerialPort.GetPortNames()
Lily
After your edit, i see that you have worked out some kinks, but you mentioned that "And through some weirdness of the SerialPort class, one instance of a serial port can't be both the sender and receiver" This is not true. The SerialPort class can be both the sender and the receiver. Since you state that things seem to workout somehow, i wont elaborate :)
Lily
Well then it definitely sounds like the weirdness is not in the SerialPort class, but in coupling it with the virtual serial port software.
Klay
+1 - Setting the RTS pin to Enabled was something I forgot. I forgot about hardware flow control.
sheepsimulator
A: 

I can only surmise that the problem was indeed with the Virtual Serial Port Emulator program. this is NOT to say there is a problem with that software: VSPE has worked very well for me so far. But there was some conflict between my code and how I had set up the VSPE connector.

Klay