简体   繁体   中英

C# Reading Serial data from sensor

I want to make a GUI for my device to show the value of each sensor. My device send data with this format

:1*895*123; :1*987*145;

* is use to separate data from sensors

; is for the end of data

: is for start of data in next loop

I have variables dot, Rx1 and Ry2 to storing the data and show it on label, but looks like my program didn't works.. here's my code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        string TestText, Rx1, Ry1, dot;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }



    private void button1_Click(object sender, EventArgs e)
    {
        serialPort1.PortName = "COM7";
        serialPort1.BaudRate = 2400;

        serialPort1.Open();
        if (serialPort1.IsOpen)
        {
            button1.Enabled = false;
            button2.Enabled = true;
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)
        {
            serialPort1.Close();
            button1.Enabled = true;
            button2.Enabled = false;
        }

    }

    private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        TestText = serialPort1.ReadExisting();
        string[] nameArray = TestText.Split ('*');
        foreach (string name in nameArray)
        {
            dot = nameArray[0];
            Rx1 = nameArray[1];
            Ry1 = nameArray[2];
        }
    }

    private void label3_Click(object sender, EventArgs e)
    {

    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        label3.Text = dot;
        posY.Text = Ry1;
        posX.Text = Rx1;
    }
        //this.Invoke(new EventHandler(DisplayText));
    }


}

I'm still new in c# and not so good with it.. so i need help. thanks before.

Are you sure that you're getting complete packets in the data received method? if not you'll need to buffer them up to be sure it's working properly.

You could try something like this.

// A buffer for the incoming data strings.
string buffer = string.Empty;

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
  // buffer up the latest data.
  buffer += serialPort1.ReadExisting();;

  // there could be more than one packet in the data so we have to keep looping.
  bool done = false;
  while (!done)
    {
       // check for a complete message.
       int start = buffer.IndexOf(":");
       int end = buffer.IndexOf(";");
       if (start > -1 && end > -1 && start < end)
       {
          // A complete packet is in the buffer.
          string packet = buffer.Substring(start + 1, (end - start) - 1);

          // remove the packet from the buffer.
          buffer = buffer.Remove(start, (end - start) + 1);

          // split the packet up in to it's parameters.
          string[] parameters = packet.Split('*');
          rx1 = parameters[0];
          ry1 = parameters[1];
          dot = parameters[2];

       }
    else
       done = true;
}

If you getting just one chunk of data after reading. For example :1*895*123;

TestText = serialPort1.ReadExisting();//:1*895*123;
string[] nameArray = TestText.Split(new []{":", "*", ";"}, StringSplitOptions.RemoveEmptyEntries);
label3.Text = nameArray[0];//1
posY.Text = nameArray[1];  //895
posX.Text = nameArray[2];  //123

and if you receive :1*895*123; :1*987*145; :1*895*123; :1*987*145;

var chunks = s.Split(new [] { ":", ";", " "}, StringSplitOptions.RemoveEmptyEntries);
foreach (var chunk in chunks)
{
   string[] data = chunk.Split(new [] { "*" }, StringSplitOptions.RemoveEmptyEntries);
   label3.Text = data[0];
   posY.Text = data[1];  
   posX.Text = data[2];  
}

But then in labels you just see latest chunk data, so you need store a list of your data. For example you can create class:

class chunkData
{
    public string dot;
    public string posX;
    public string posY;
}

and use it like this:

private List<chunkData> dataList = new List<chunkData>();
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   TestText = serialPort1.ReadExisting();
   var chunks = TestText.Split(new [] { ":", ";", " "}, StringSplitOptions.RemoveEmptyEntries);
   foreach (var chunk in chunks)
   {
      string[] data = chunk.Split(new [] { "*" }, StringSplitOptions.RemoveEmptyEntries);
      dataList.Add(new chunkData(){dot=data[0], posX=data[1], posY=data[2]})
   }
   //display dataList to DataGridView or other control
}

EDIT : here is what you can do if you receiving data symbol by symbol:

private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
   string temp = serialPort1.ReadExisting();
   if(temp == ";") //OK we have end of data lets process it
      splitAndDisplay();
   else
      TestText += temp; 
}

private void splitAndDisplay()
{
   string[] nameArray = TestText.Split(new []{":", "*"}, StringSplitOptions.RemoveEmptyEntries);
   this.Invoke(new Action(() =>
     {
       label3.Text = nameArray[0];
       posY.Text = nameArray[1];  
       posX.Text = nameArray[2];
      }));
   TestText = "";
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM