Tech Off Thread

23 posts

Issues with .NET CF Serial Communication

Back to Forum: Tech Off
  • User profile image
    NotSoTragic​Hero

    We've had more trouble than it's worth with serial communication in the compact framework for CE.  We've tried the base SerialPort class provided, the OpenNETCF classes, and we've even tried creating our own wrapper class using the native dlls.

     

    The code is being deployed to a mobile data terminal running Windows CE, which is connected, via RS232, to a GPS/GSM unit.  When I connect this GSM unit directly to my PC, I can connect and make successful calls to it using HyperTerminal as well as with our wrapper class.  But when I convert the Kernel32 calls to CoreDLL calls, the wrapper class fails, as does the CF SerialPort and OpenNETCF classes.

     

    I've decided to start from scratch as I've been racking my brain too much and hacking away at too many things for too long now.  Below is a quick example class I've written to communicate with the device.

     

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    namespace SerialComTest
    {
        public partial class form_SerialCom : Form
        {
            private SerialPort port;
            private String displayString;
            public form_SerialCom()
            {
                InitializeComponent();
                button_Send.Click += new EventHandler(button_Send_Click);
                port = new SerialPort("COM2", 115200, Parity.None, 8, StopBits.One);
                port.NewLine = "\r\n";
                port.RtsEnable = true;
                port.DtrEnable = true;
                port.ReceivedBytesThreshold = 1;
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
                port.Open();
                if (port.IsOpen)
                {
                    textBox_Rec.Text += "Connected to " + port.PortName + Environment.NewLine;
                }
            }
            void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
            {
                throw new NotImplementedException();
            }
            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                displayString = port.ReadLine();
                try
                {
                    this.Invoke(new EventHandler(SetText));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            private void SetText(object o, EventArgs e)
            {
                textBox_Rec.Text += displayString + Environment.NewLine;
                displayString = string.Empty;
            }
            void button_Send_Click(object sender, EventArgs e)
            {
                port.Write(textBox_Send.Text + port.NewLine);
                textBox_Send.Text = "";
            }
        }
    }

     

    When I send an AT command to the device, the DataReceived event never fires.  I've also tried setting up a tick to try and capture some return data, yet I still get nothing.  I can rule out the data sending as the problem, as I can send a message, via SMS, that will cause the device to return data, yet still, nothing happens.

     

    Any help would be appreciated.  Thanks!

    -Brandon

  • User profile image
    ManipUni
  • User profile image
    NotSoTragic​Hero

    ManipUni said:

    Ploe is my co-worker.  His class works great using Kernel32, as I stated.  Fails with the CoreDLL implementation. Sad

     

    Returns a Win32Error:

    ErrorCode: -2147467259

    NativeErrorCode: 12

  • User profile image
    NotSoTragic​Hero

    Our main issue, with the class in the thread that was linked, is that it fails on GetCommState().  We suspect that this is a problem with our DCB, in that the CoreDLL DCB is a stripped down version of the Kernel32 DCB.  However, we've tried a ton of combinations, and nothing seems to work...  Embarassed

     

    On the other hand, we can't even get the standard SerialPort, as listed in the first post, to get any data either.  We seem to be failing with any implementation of serial communication.

  • User profile image
    davewill

    NotSoTragicHero said:

    Our main issue, with the class in the thread that was linked, is that it fails on GetCommState().  We suspect that this is a problem with our DCB, in that the CoreDLL DCB is a stripped down version of the Kernel32 DCB.  However, we've tried a ton of combinations, and nothing seems to work...  Embarassed

     

    On the other hand, we can't even get the standard SerialPort, as listed in the first post, to get any data either.  We seem to be failing with any implementation of serial communication.

    Do "port.open()" right after setting port=new rather than after setting the other port properties before the open.

     

    rule out handshaking by setting port.handshake

     

    rule out garbage by calling port.DiscardInBuffer and port.DiscardOutBuffer after setting the other port properties but before wiring up the port events.

  • User profile image
    NotSoTragic​Hero

    davewill said:
    NotSoTragicHero said:
    *snip*

    Do "port.open()" right after setting port=new rather than after setting the other port properties before the open.

     

    rule out handshaking by setting port.handshake

     

    rule out garbage by calling port.DiscardInBuffer and port.DiscardOutBuffer after setting the other port properties but before wiring up the port events.

    Thanks!  Big Smile

     

    This definitely did something, however, I am now getting a TimeOutException (I set the read/write timeout to 500 ms after the system kept hanging) whenever I try to write anything.  I can't seem to find anything wrong with the port properties...

     

    I feel like this is definitely a step forward, but I still have to be leaving something out somewhere...

     

    Current Code:

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Collections;
    namespace SerialComTest
    {
        public partial class form_SerialCom : Form
        {
            private SerialPort port;
            private String displayString;
            public form_SerialCom()
            {
                InitializeComponent();
                button_Send.Click += new EventHandler(button_Send_Click);
                port = new SerialPort("COM2", 115200, Parity.None, 8, StopBits.One);
                port.Open();
                port.NewLine = "\r\n";
                port.RtsEnable = true;
                port.DtrEnable = true;
                port.Handshake = Handshake.RequestToSend;
                port.ReceivedBytesThreshold = 1;
                port.WriteTimeout = 500;
                port.ReadTimeout = 500;
                port.DiscardInBuffer();
                port.DiscardOutBuffer();
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
                if (port.IsOpen)
                {
                    textBox_Rec.Text += "Connected to " + port.PortName + Environment.NewLine;
                }
            }
            void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
            {
                throw new NotImplementedException();
            }
            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                displayString = port.ReadLine();
                try
                {
                    this.Invoke(new EventHandler(SetText));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            private void SetText(object o, EventArgs e)
            {
                textBox_Rec.Text += displayString + Environment.NewLine;
                displayString = string.Empty;
            }
            void button_Send_Click(object sender, EventArgs e)
            {
                try
                {
                    port.WriteLine(textBox_Send.Text);
                }
                catch (TimeoutException) { }
                textBox_Send.Text = "";
            }
        }
    }

  • User profile image
    figuerres

    davewill said:
    NotSoTragicHero said:
    *snip*

    Do "port.open()" right after setting port=new rather than after setting the other port properties before the open.

     

    rule out handshaking by setting port.handshake

     

    rule out garbage by calling port.DiscardInBuffer and port.DiscardOutBuffer after setting the other port properties but before wiring up the port events.

    hey off topic but in the picture is that a racer ? looks like a southern black racer - i see lots of them around tampa where i live.

  • User profile image
    davewill

    NotSoTragicHero said:
    davewill said:
    *snip*

    Thanks!  Big Smile

     

    This definitely did something, however, I am now getting a TimeOutException (I set the read/write timeout to 500 ms after the system kept hanging) whenever I try to write anything.  I can't seem to find anything wrong with the port properties...

     

    I feel like this is definitely a step forward, but I still have to be leaving something out somewhere...

     

    Current Code:

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Collections;
    namespace SerialComTest
    {
        public partial class form_SerialCom : Form
        {
            private SerialPort port;
            private String displayString;
            public form_SerialCom()
            {
                InitializeComponent();
                button_Send.Click += new EventHandler(button_Send_Click);
                port = new SerialPort("COM2", 115200, Parity.None, 8, StopBits.One);
                port.Open();
                port.NewLine = "\r\n";
                port.RtsEnable = true;
                port.DtrEnable = true;
                port.Handshake = Handshake.RequestToSend;
                port.ReceivedBytesThreshold = 1;
                port.WriteTimeout = 500;
                port.ReadTimeout = 500;
                port.DiscardInBuffer();
                port.DiscardOutBuffer();
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
                if (port.IsOpen)
                {
                    textBox_Rec.Text += "Connected to " + port.PortName + Environment.NewLine;
                }
            }
            void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
            {
                throw new NotImplementedException();
            }
            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                displayString = port.ReadLine();
                try
                {
                    this.Invoke(new EventHandler(SetText));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            private void SetText(object o, EventArgs e)
            {
                textBox_Rec.Text += displayString + Environment.NewLine;
                displayString = string.Empty;
            }
            void button_Send_Click(object sender, EventArgs e)
            {
                try
                {
                    port.WriteLine(textBox_Send.Text);
                }
                catch (TimeoutException) { }
                textBox_Send.Text = "";
            }
        }
    }

    comment out

     

    port.RtsEnable = true;
    port.DtrEnable = true;

    and see if that matters.

     

    timeout on write almost sounds like a hardware handshake problem (like a pin isn't going low).

  • User profile image
    NotSoTragic​Hero

    davewill said:
    NotSoTragicHero said:
    *snip*

    comment out

     

    port.RtsEnable = true;
    port.DtrEnable = true;

    and see if that matters.

     

    timeout on write almost sounds like a hardware handshake problem (like a pin isn't going low).

    Didn't change anything... 

     

    I got past the WriteLine timeout by switching ports from COM2 to COM1.  Maybe something with the port?  However, now I get a timeout during the ReadLine call, and ReadExisting returns nothing.  DataReceived still doesn't fire.

  • User profile image
    davewill

    NotSoTragicHero said:
    davewill said:
    *snip*

    Didn't change anything... 

     

    I got past the WriteLine timeout by switching ports from COM2 to COM1.  Maybe something with the port?  However, now I get a timeout during the ReadLine call, and ReadExisting returns nothing.  DataReceived still doesn't fire.

    Whoa.  Hold on.  It sounds like your not sure which COM you need to use.  Usually COM1 is the port that is the physical port on the windows device.  If you are attaching the GSM unit to this physical port on the windows device then COM1 sounds more correct but you need to find out what that windows device normally has for COM.

     

    The cable between the windows unit and the GSM unit ... is it a hardware handshaking cable or a software handshaking cable?

  • User profile image
    NotSoTragic​Hero

    davewill said:
    NotSoTragicHero said:
    *snip*

    Whoa.  Hold on.  It sounds like your not sure which COM you need to use.  Usually COM1 is the port that is the physical port on the windows device.  If you are attaching the GSM unit to this physical port on the windows device then COM1 sounds more correct but you need to find out what that windows device normally has for COM.

     

    The cable between the windows unit and the GSM unit ... is it a hardware handshaking cable or a software handshaking cable?

    The Windows CE device actually has two physical ports.  One is labeled COM1, and the other is labeled COM2.  I physically changed the cable to COM1, and changed the port name to COM1.  The device between the two units requires hardware handshaking.

  • User profile image
    davewill

    NotSoTragicHero said:
    davewill said:
    *snip*

    The Windows CE device actually has two physical ports.  One is labeled COM1, and the other is labeled COM2.  I physically changed the cable to COM1, and changed the port name to COM1.  The device between the two units requires hardware handshaking.

    Make sure the port on the GSM side is using hardware handshaking.

     

    If you are getting a timeout on the Write then it sure sounds like it is waiting on the GSM side to give the goahead.

     

    How about the send and recv buffer sizes on both sides of the cable?  are they sufficient.

     

     

    set port.rts = true and port.dtr = false since using hardware handshaking.

  • User profile image
    NotSoTragic​Hero

    davewill said:
    NotSoTragicHero said:
    *snip*

    Make sure the port on the GSM side is using hardware handshaking.

     

    If you are getting a timeout on the Write then it sure sounds like it is waiting on the GSM side to give the goahead.

     

    How about the send and recv buffer sizes on both sides of the cable?  are they sufficient.

     

     

    set port.rts = true and port.dtr = false since using hardware handshaking.

    The read and write buffer sizes are 4096 and 2048 respectively, so I don't think it is that.

     

    I don't believe there is any way to check the other side of the cable.    Sad

     

    The device's manual states that hardware handshaking is in fact enabled, however.

     

    Currently, I am only getting the ReadLine time out exception.

     

    Current Code:

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Collections;
    using System.Threading;
    namespace SerialComTest
    {
        public partial class form_SerialCom : Form
        {
            private SerialPort port;
            private String displayString;
            public form_SerialCom()
            {
                InitializeComponent();
                button_Send.Click += new EventHandler(button_Send_Click);
                port = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
                port.Open();
                port.NewLine = Environment.NewLine;
                port.RtsEnable = true;
                port.DtrEnable = false;
                port.Handshake = Handshake.RequestToSend;
                port.ReceivedBytesThreshold = 1;
                port.WriteTimeout = 500;
                port.ReadTimeout = 500;
                port.DiscardInBuffer();
                port.DiscardOutBuffer();
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
                if (port.IsOpen)
                {
                    textBox_Rec.Text += "Connected to " + port.PortName + Environment.NewLine;
                }
                Thread thread = new Thread(delegate()
                {
                    while (true)
                    {
                        try
                        {
                            String test = port.ReadLine();
                            textBox_Rec.Text += test + Environment.NewLine;
                        }
                        catch (TimeoutException) { }
                    }
                });
                thread.Start();
            }
            void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
            {
                throw new NotImplementedException();
            }
            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                displayString = port.ReadLine();
                try
                {
                    this.Invoke(new EventHandler(SetText));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            private void SetText(object o, EventArgs e)
            {
                textBox_Rec.Text += displayString + Environment.NewLine;
                displayString = string.Empty;
            }
            void button_Send_Click(object sender, EventArgs e)
            {
                try
                {
                    port.WriteLine(textBox_Send.Text);
                }
                catch (TimeoutException)
                {
                    textBox_Rec.Text += ("The write operation timed out." + Environment.NewLine);
                }
                textBox_Send.Text = "";
            }
        }
    }

  • User profile image
    davewill

    NotSoTragicHero said:
    davewill said:
    *snip*

    The read and write buffer sizes are 4096 and 2048 respectively, so I don't think it is that.

     

    I don't believe there is any way to check the other side of the cable.    Sad

     

    The device's manual states that hardware handshaking is in fact enabled, however.

     

    Currently, I am only getting the ReadLine time out exception.

     

    Current Code:

    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO.Ports;
    using System.Collections;
    using System.Threading;
    namespace SerialComTest
    {
        public partial class form_SerialCom : Form
        {
            private SerialPort port;
            private String displayString;
            public form_SerialCom()
            {
                InitializeComponent();
                button_Send.Click += new EventHandler(button_Send_Click);
                port = new SerialPort("COM1", 115200, Parity.None, 8, StopBits.One);
                port.Open();
                port.NewLine = Environment.NewLine;
                port.RtsEnable = true;
                port.DtrEnable = false;
                port.Handshake = Handshake.RequestToSend;
                port.ReceivedBytesThreshold = 1;
                port.WriteTimeout = 500;
                port.ReadTimeout = 500;
                port.DiscardInBuffer();
                port.DiscardOutBuffer();
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                port.ErrorReceived += new SerialErrorReceivedEventHandler(port_ErrorReceived);
                if (port.IsOpen)
                {
                    textBox_Rec.Text += "Connected to " + port.PortName + Environment.NewLine;
                }
                Thread thread = new Thread(delegate()
                {
                    while (true)
                    {
                        try
                        {
                            String test = port.ReadLine();
                            textBox_Rec.Text += test + Environment.NewLine;
                        }
                        catch (TimeoutException) { }
                    }
                });
                thread.Start();
            }
            void port_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
            {
                throw new NotImplementedException();
            }
            void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                displayString = port.ReadLine();
                try
                {
                    this.Invoke(new EventHandler(SetText));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            private void SetText(object o, EventArgs e)
            {
                textBox_Rec.Text += displayString + Environment.NewLine;
                displayString = string.Empty;
            }
            void button_Send_Click(object sender, EventArgs e)
            {
                try
                {
                    port.WriteLine(textBox_Send.Text);
                }
                catch (TimeoutException)
                {
                    textBox_Rec.Text += ("The write operation timed out." + Environment.NewLine);
                }
                textBox_Send.Text = "";
            }
        }
    }

    ok.  so your getting problems on the ReadLine.  That means the event is firing.  The code needs a little work on the actual using of the received data.  The port is setup to trigger the event when each byte enters the receive buffer (ReceivedBytesThreshold=1) ... yet your DataReceived event is trying to read a line at a time rather than doing something like 

     

                displayString &= port.ReadByte();

  • User profile image
    NotSoTragic​Hero

    davewill said:
    NotSoTragicHero said:
    *snip*

    ok.  so your getting problems on the ReadLine.  That means the event is firing.  The code needs a little work on the actual using of the received data.  The port is setup to trigger the event when each byte enters the receive buffer (ReceivedBytesThreshold=1) ... yet your DataReceived event is trying to read a line at a time rather than doing something like 

     

                displayString &= port.ReadByte();

    Actually, the event isn't being fired still.  Since it isn't fired, I'm trying to catch the data in the anonymous thread declared in the constructor for now, which is why I know the exception fires on the ReadLine.  Trying ReadByte and ReadLine both cause a TimeoutException.

  • User profile image
    davewill

    NotSoTragicHero said:
    davewill said:
    *snip*

    Actually, the event isn't being fired still.  Since it isn't fired, I'm trying to catch the data in the anonymous thread declared in the constructor for now, which is why I know the exception fires on the ReadLine.  Trying ReadByte and ReadLine both cause a TimeoutException.

    Ok.  How about old school polling with a timer just to see if anything shows up.  Does that work?

     

      Private Sub ReadFromPort()
          If port.BytesToRead = 0 Then Exit Sub
          Do While port.BytesToRead > 0
            ' Read in data...
              Dim b As System.Byte = CType(port.ReadByte, System.Byte)

             

              'TODO: put this b somewhere so we know it came in

     

          Loop
      End Sub

     

    sorry ... vb syntax is the way my brain works.

  • User profile image
    NotSoTragic​Hero

    davewill said:
    NotSoTragicHero said:
    *snip*

    Ok.  How about old school polling with a timer just to see if anything shows up.  Does that work?

     

      Private Sub ReadFromPort()
          If port.BytesToRead = 0 Then Exit Sub
          Do While port.BytesToRead > 0
            ' Read in data...
              Dim b As System.Byte = CType(port.ReadByte, System.Byte)

             

              'TODO: put this b somewhere so we know it came in

     

          Loop
      End Sub

     

    sorry ... vb syntax is the way my brain works.

    Nothing.  Sad

     

    It seems that no matter what, I can't get anything to return from this thing.  I know the device works, as I can poll it using PuTTY just fine.   Mad

  • User profile image
    davewill

    NotSoTragicHero said:
    davewill said:
    *snip*

    Nothing.  Sad

     

    It seems that no matter what, I can't get anything to return from this thing.  I know the device works, as I can poll it using PuTTY just fine.   Mad

    Bummer.  I don't know what else to suggest.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.