C# - изменить формат данных, полученных от последовательного порта - PullRequest
0 голосов
/ 20 апреля 2020

Я создаю приложение формы C#, которое получает данные от прибора, обменивающегося данными со скоростью 2400 бод, четность отсутствует, 8-битные данные, 1 стоповый бит. Данные поступают в виде непрерывной строки в виде [000000] [000000] [000000]. Например, если во время процедуры показания прибора изменяются, например, 0,50,0,49,0,72,0,61,0,48, то строка полученных данных будет иметь значение [000050] [000049] [000072] [000061] [000048], то есть как в настоящее время оно отображается в текстовом поле.

Мне нужно отобразить максимальное значение, достигнутое во время процедуры, в текстовое поле и в правильном формате, как в этом случае должно быть 0,72. Я в недоумении о том, что будет код для этого.

Ниже мой текущий код для связи через последовательный порт.

    public Form2()
    {
        InitializeComponent();
    }

    private void Form2_Load(object sender, EventArgs e)
    {

    }

    private void Main_Load(object sender, EventArgs e)
    {
    }

   //this is the button to open port.
    private void button1_Click(object sender, EventArgs e)
    {
        button1.Enabled = false;
        button2.Enabled = true;
        try
        {
            serialPort1.PortName = comboBox1.Text;
            serialPort1.Open();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }


    //Event handler for data received.
    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        string indata = sp.ReadExisting();
        Regex rx = new Regex(@"\[(\d+)\]");
        double.TryParse(richTextBox2.Text, out double max);
        foreach (Match match in rx.Matches(indata))
        {
            double val = int.Parse(match.Groups[1].Value) / 100.0;
            if (val > max)
                max = val;
        }
        richTextBox2.Text = max.ToString();
    }



    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {


    }

    //this is the button to close port
    private void button2_Click(object sender, EventArgs e)
    {
        button1.Enabled = true;
        button2.Enabled = false;
        try
        {
            serialPort1.Close();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    private void button3_Click(object sender, EventArgs e)
    {
        if (serialPort1.IsOpen)
        {
            serialPort1.DataReceived += DataReceivedHandler;
        }
        else
        {
            MessageBox.Show("Error : Port needs to be open or wrong port selected!");
        }

    }   


    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (serialPort1.IsOpen)
            serialPort1.Close();
    }


    private void button4_Click(object sender, EventArgs e)
    {
        string[] ports = SerialPort.GetPortNames();
        comboBox1.Items.AddRange(ports);
        comboBox1.SelectedIndex = 0;
        button2.Enabled = false;

    }

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

То есть вы хотите обрабатывать данные каждый раз, когда есть данные для обработки, верно?

Если вы используете «System.IO.Ports», а ваш serialPort1 имеет тип SerialPort, у вас есть « DataReceived "событие доступно. Поэтому после создания экземпляра serialPort1 вы можете:

private void button1_Click(object sender, EventArgs e)
{
    button1.Enabled = false;
    button2.Enabled = true;
    try
    {
        //check and set the settings of your device
        serialPort1 = new SerialPort
        {
            PortName = comboBox1.Text,
            BaudRate = 2400,
            Parity = Parity.None,
            StopBits = StopBits.Odd,
            DataBits = 8,
            Handshake = Handshake.None,
            RtsEnable = true
        };

        serialPort1.DataReceived += DataReceivedHandler;
        serialPort1.Open();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Затем вам просто нужно объявить обработчик событий, что-то вроде этого:

private void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    string indata = sp.ReadExisting();
    Regex rx = new Regex(@"\[(\d+)\]");
    double.TryParse(textBox13.Text, out double max);
    foreach (Match match in rx.Matches(indata))
    {
        double val = int.Parse(match.Groups[1].Value) / 100.0;
        if (val > max)
            max = val;
    }
    textBox13.Text = max .ToString();
}

При этом будут сравниваться полученные значения и текущий значение в текстовом поле.

0 голосов
/ 20 апреля 2020

Если я понимаю, что вы правильно форматируете требование, вы в основном хотите удалить нули в начале каждого из чисел, а затем сравнить их, чтобы найти максимальное значение и отобразить их в формате x.xx Если это так, создайте отдельный метод для обработки этого так:

    private decimal GetMaxReading(string rawReadingData)
    {
        decimal maxReading = 0;
        var readings = rawReadingData.Split('[',).ToList();

        foreach (var reading in readings)
        {
            var readingString = reading.TrimStart('0')
                                       .TrimEnd(']');

            var isInt = int.TryParse(readingString, out int readingValue);
            var value = isInt ? (decimal)readingValue / 100 : 0;
            maxReading = value > maxReading ? value : maxReading;
        }

        return maxReading;
    }
...