C # - получение всех данных с устройства через последовательный порт и определение управляющего символа (ACK, SOH, ...) - PullRequest
2 голосов
/ 26 апреля 2019

Я могу легко получить ответ от устройства и показать его в текстовом поле с помощью Serial.ReadExisting ().При отображении данных проблема заключается в том, что некоторые управляющие символы (ACK, SOH, ETX, ...) недоступны для печати. ​​

Я пытаюсь определить управляющий символ по последовательному ответу с помощью приведенного ниже кода, но что-то не так всравнение.

Код:

public bool read_port(ref string rs232data, int timeout)
    {
        try
        {
            int index_read = 0;
            int total_read = 0;
            int i = 0;
            int delay_ms = 1;
            byte[] buffer = new byte[serialPort1.ReadBufferSize];
            rs232data = "";
            string buffer_str = "";

            if ((serialPort1.IsOpen == false))
            {
                #if DEBUG
                MessageBox.Show("COM port is not opening");
                #endif
                return false;
            }
            do
            {
                Application.DoEvents();
                PauseForMilliSeconds(delay_ms); //System.Threading.Thread.Sleep(delay_ms);
                i++;

                //serial port receive data
                if (serialPort1.BytesToRead <= 0) continue;
                if (i > 1) i--;
                index_read = serialPort1.Read(buffer, total_read, serialPort1.BytesToRead);
                total_read += index_read;
                buffer_str = ToStringLsb(buffer);

                //// Find a Start byte
                int ack_index = buffer_str.LastIndexOf(ToStringLsb(ACK));
                int nak_index = buffer_str.LastIndexOf(ToStringLsb(NAK));

                //Find a Stop byte
                int stop_index_etx = buffer_str.LastIndexOf(ToStringLsb(ETX));
                int stop_index_lf = buffer_str.LastIndexOf(ToStringLsb(LF));

                if ((stop_index_etx < 0) && (stop_index_lf < 0) && (ack_index < 0)) continue; // Can't find a byte Stop


                if (stop_index_etx > 0)
                {
                    if ((stop_index_etx + 1) < total_read)
                    {
                        stop_index_etx++;
                    }
                    else
                    {
                        if (buffer[total_read - 2] == ETX)
                        {
                            stop_index_etx--;
                        }
                        else continue;
                    }
                }

                rs232data = buffer_str.Substring(0, total_read);
                return true;
            }
            while (i < timeout);
            return false;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
            return false;
        }
    }

    public static string ToStringLsb(byte bytevalue)
    {
        try
        {
            byte[] bytearray = { bytevalue };
            return System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytearray);
        }
        catch (System.Exception ex)
        {
            MessageBox.Show(ex.Message);
            return "";
        }
    }

    public static string ToStringLsb(byte[] bytearray)
    {
        return System.Text.Encoding.GetEncoding("iso-8859-1").GetString(bytearray);
    }

1 Ответ

0 голосов
/ 26 апреля 2019

Вам нужно взглянуть на карту ASCII и определить, какие значения являются контрольными значениями, которые вы ищете.

ASCII Map

Так, например, я быопределите следующие управляющие символы в моем коде, затем в вашем событии DataReceived вы можете искать эти символы.

char ACK = (char)6;
char NAK = (char)21;
char SOH = (char)1;
char LF = (char)10;
StringBuilder sb = new StringBuilder();

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string Data = serialPort1.ReadExisting();

    foreach (char c in Data)
    {
        if (c == LF)
        {
            sb.Append(c);

            CurrentLine = sb.ToString();
            sb.Clear();

            //parse CurrentLine here or print it to textbox
        }
        if (c == ACK)
        {
            sb.Append("<ACK>"); //or whatever you want to print
        }
        else
        {
            sb.Append(c);
        }
    }
}

edit: Чтобы ответить на некоторые ваши вопросы в комментариях ниже.Событие DataReceived срабатывает, когда в буфер попадают символы, но оно может срабатывать, получая только половину вашего сообщения.Таким образом, при использовании этого события вы должны создавать строку, пока не узнаете, что у вас есть все сообщение.В моем примере выше я предполагаю, что LF (перевод строки) указывает, что у меня есть все сообщение.Для вас вы должны использовать любой символ, который вы ищете, который отмечает конец вашего сообщения (может быть, ACK в вашем случае?).Вы можете добавить этот символ к вашей строке или нет, это зависит от ваших требований.В моем примере вы можете видеть, что я добавляю LF, но вы можете легко убрать эту строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...