允许触发的Datareceivedhandler事件方法运行一次还是一段时间?

时间:2016-02-11 10:26:30

标签: c# events serial-port

我有一个程序,用于从串口读取数据,将其显示在图表上并允许保存。这些数据只是逐个发送的uint64号码。数据发送速度非常快(每秒多次)。

目前,数据被读入数据表,此功能在datareceivedhandler事件方法中完成,该方法在接收数据时自动触发。

我希望得到以下内容:

  • “runonce”按钮,允许单次捕获数据
  • 可选时间和'定时'按钮,只允许在一段时间内读取数据
  • 一个“连续”按钮,可以永久保存数据

任何不在所选时间/捕获范围内的数据都应该被丢弃(或者从不首先捕获)。应该有一个“停止捕获”按钮,可以停止连续或定时模式。

实施此方法的最佳方法是什么?我在下面附上了我的代码。

using System;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;
using System.Text.RegularExpressions;

namespace FieldProbe
{
    public partial class MainForm : Form
    {
        SerialPort _port = new SerialPort();    //set up port
        DataTable dt = new DataTable(); //set up datatable to hold output
        int numSamples = 0;

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            var ports = SerialPort.GetPortNames();  //get list of ports connected to PC
            cmbSerialPorts.DataSource = ports;      //use list of ports as combobox options
            _port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);  //create pointer to datareceived event handler

            dt.Clear(); //Clear datatable on start
            dt.Columns.Add("index", typeof(int));           //index
            dt.Columns.Add("dutyCycle", typeof(float));     //0.5 means equal on/off, 1.0 means permanently on
            dt.Columns.Add("frequency", typeof(float));     //probe can go from 40MHz to 10GHz
            dt.Columns.Add("distance", typeof(float));      //antenna to radiator distance in metres (usually 1m)
            dt.Columns.Add("pulseWidth", typeof(float));    //calculated from duty cycle and frequency
            dt.Columns.Add("level", typeof(int));           //output in V/m

            chChart.Series["series1"].YValueMembers = "level";
            chChart.Series["series1"].XValueMember = "index";
            chChart.DataSource = dt;
            chChart.DataBind();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (btnConnect.Text == "Connect")   //if user clicks connect button
            {

                if (cmbSerialPorts.SelectedIndex > -1)  //if port valid
                {
                    //MessageBox.Show(String.Format("You selected port '{0}'", cmbSerialPorts.SelectedItem));
                    Connect(cmbSerialPorts.SelectedItem.ToString());    //go to connect function
                }
                else
                {
                    MessageBox.Show("Please select a port first");
                }
            }
            else    //if user clicks disconnect button
            {
                btnConnect.Text = "Connect";
                btnContinuous.Enabled = false;
                btnSingle.Enabled = false;
                btnTimed.Enabled = false;
                nudTime.Enabled = false;
                try
                {
                    _port.Close();
                }
                catch
                {
                    MessageBox.Show("Connection close failed- device may already be unplugged. Program will exit.");
                    Application.Exit();
                }

            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
            saveFileDialog1.Filter = "csv files (*.csv)|*.csv*";
            saveFileDialog1.RestoreDirectory = true;
            saveFileDialog1.DefaultExt = "csv";
            saveFileDialog1.AddExtension = true;

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                File.WriteAllText(saveFileDialog1.FileName, dtToCSV());
            }
        }

        private void btnSingle_Click(object sender, EventArgs e)
        {

        }

        private void Connect(string portName)
        {
            if (!_port.IsOpen)
            {
                _port.BaudRate = 9600;  //CHANGE ME AFTER ARDUINO TESTING!!!!!!!!!!!!!!
                _port.DataBits = 8;
                _port.StopBits = StopBits.One;
                _port.Parity = Parity.None;
                _port.Handshake = Handshake.None;
                _port.RtsEnable = true; //CHANGE ME AFTER ARDUINO TESTING!!!!!!!!!!!!!!
                _port.DtrEnable = true; //CHANGE ME AFTER ARDUINO TESTING!!!!!!!!!!!!!!
                _port.PortName = portName;
                try
                {
                    _port.Open();   //connect to port
                    btnConnect.Text = "Disconnect";
                    btnContinuous.Enabled = true;
                    btnSingle.Enabled = true;
                    btnTimed.Enabled = true;
                    nudTime.Enabled = true;
                }
                catch
                {
                    MessageBox.Show("ERROR: Port invalid or in use!");
                    btnConnect.Text = "Connect";
                    btnContinuous.Enabled = false;
                    btnSingle.Enabled = false;
                    btnTimed.Enabled = false;
                    nudTime.Enabled = false;
                }
            }
        }

        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender; //set up serial port
            string indata = sp.ReadExisting();  //read data from port
            string indataString = Regex.Match(indata, @"\d+").Value;    //extract number (still a string)

            numSamples++;   //increment x axis

            try
            {
                int indataInt = Int32.Parse(indataString);  //convert string to int
                var pulseWidth = nudDutyCycle.Value / (nudFrequency.Value * 100);   //formula to find pulse width from duy cycle & frequency
                object[] o = { numSamples, nudDutyCycle.Value, nudFrequency.Value, nudDistance.Value, pulseWidth, indataInt };  //collect data
                dt.Rows.Add(o); //add data to datatable

                teIncomingData.invokeIfRequired(() =>   //add text to textbox (different thread)
                {
                    teIncomingData.AppendText(indataString + Environment.NewLine);
                });
            }
            catch { }

            chChart.invokeIfRequired(() =>  //update chart (different thread)
            {
                chChart.DataBind();
            });
        }

        private string dtToCSV()
        {
            string file = "";

            foreach (DataColumn col in dt.Columns)
                file = string.Concat(file, col.ColumnName, ",");

            file = file.Remove(file.LastIndexOf(','), 1);
            file = string.Concat(file, "\r\n");

            foreach (DataRow row in dt.Rows)
            {
                foreach (object item in row.ItemArray)
                    file = string.Concat(file, item.ToString(), ",");

                file = file.Remove(file.LastIndexOf(','), 1);
                file = string.Concat(file, "\r\n");
            }

            return file;
        }

        public void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {   //do not delete me, this needs to exist for some reason for saving to work
        }
    }

    public static class Invoker
    {
        public static void invokeIfRequired(this ISynchronizeInvoke obj, MethodInvoker action)
        {
            if(obj.InvokeRequired)
            {
                var args = new object[0];
                obj.Invoke(action, args);
            }
            else
            {
                action();
            }
        }
    }
}

0 个答案:

没有答案