С# Отправка данных через последовательный порт, данные в байтовом массиве получены неполными

Я разрабатываю графический интерфейс, который получает информацию от ATmega8A. Приведенный ниже код из графического интерфейса должен делать следующее:

  • Проверить заголовок: здесь я читаю данные в массив байтов (byte[] test), который проверяется на соответствие OxFF
  • Если header == 0xFF, прочитать второй массив байтов (byte[] data)

Пожалуйста, смотрите код ниже.

Теперь у меня есть следующая проблема. Если я отправляю просто число, например 1, то это число без проблем отображается в textBox1. Однако, если я пытаюсь отправить число, например 433, я всегда получаю 4, 33 теряется. Я предполагаю, что это связано с моим включенным оператором if, но я не могу объяснить, почему эти данные теряются.

namespace RS232
{
   public partial class fclsRS232Tester : Form
   {
    string InputData = String.Empty;
    string initText = "waiting...";

    delegate void SetTextCallback(string text);

    public fclsRS232Tester()
    {
        InitializeComponent();

        // Nice methods to browse all available ports:
        string[] ports = SerialPort.GetPortNames();

        // Add all port names to the combo box:
        foreach (string port in ports)
        {
            cmbComSelect.Items.Add(port);
        }

        cmbBaud.Items.Add(2400);
        cmbBaud.Items.Add(9600);

        cmbComSelect.SelectedIndex = 0;
        cmbBaud.SelectedIndex = 1;

        button4.Enabled = false;
        textBox1.Text = initText;
        textBox2.Text = initText;

    }

    private void cmbComSelect_SelectionChangeCommitted(object sender, EventArgs e)
    {
        if (port.IsOpen) port.Close();
        port.PortName = cmbComSelect.SelectedItem.ToString();
        stsStatus.Text = port.PortName + ": 9600,8N1";

        // try to open the selected port:
        try
        {
            port.Open();
            button4.Enabled = true;
            textBox1.Clear();
            textBox2.Clear();
        }
        // give a message, if the port is not available:
        catch
        {
            MessageBox.Show("Serial port " + port.PortName + " cannot be opened!", "RS232      tester", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            cmbComSelect.SelectedText = "";
            stsStatus.Text = "Select serial port!";
        }
    }

    private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
    {
        int bytenumber;
        int bufferSize = port.BytesToRead;
        byte[] test = new byte[1];
        byte[] data = new byte[bufferSize];
        byte[] data2 = new byte[bufferSize];

        port.Read(test, 0, 1);

        if (test[0] == 0xFF)  //Receive X-andY- coordinates from MCU and plot the coordinates 
        {
            bytenumber = port.Read(data, 0, bufferSize);
            string info = System.Text.Encoding.ASCII.GetString(data);

            this.Invoke((MethodInvoker)delegate
            {
                this.txtIn.Text += info;                      
            }
        }
    }
}

person AKAP    schedule 07.09.2014    source источник
comment
Какой объект содержит port?   -  person Guffa    schedule 07.09.2014
comment
Я определил порт следующим образом:   -  person AKAP    schedule 07.09.2014
comment
ИнициализироватьКомпонент(); // Хорошие методы для просмотра всех доступных портов: string[] ports = SerialPort.GetPortNames(); // Добавляем все имена портов в поле со списком: foreach (string port in ports) { cmbComSelect.Items.Add(port); }   -  person AKAP    schedule 07.09.2014
comment
Это не может быть port, который используется в методе. Эта переменная существует только в области действия foreach, а строка не имеет свойства BytesToRead или метода Read.   -  person Guffa    schedule 07.09.2014
comment
Я также включил следующий код: private void cmbComSelect_SelectionChangeCommitted(object sender, EventArgs e) { if (port.IsOpen) port.Close(); port.PortName = cmbComSelect.SelectedItem.ToString(); stsStatus.Text = порт.ИмяПорта + : 9600,8N1; // пытаемся открыть выбранный порт: try { port.Open(); button4.Enabled = истина; текстовое поле1.Очистить(); текстовое поле2.Очистить(); }   -  person AKAP    schedule 07.09.2014
comment
Это еще один код, который просто использует port. Где заявлено?   -  person Guffa    schedule 07.09.2014
comment
Кажется, у меня нет объявления рядом с приведенным выше кодом. Может ли это быть правдой?   -  person AKAP    schedule 07.09.2014
comment
Его нужно где-то объявить, но его может не быть в коде, на который вы смотрите. У вас есть элемент управления на странице с таким именем?   -  person Guffa    schedule 07.09.2014
comment
Я только что включил свой полный код выше. Я новичок в С#, поэтому я все еще много читаю.   -  person AKAP    schedule 07.09.2014
comment
измените свое первое чтение на var firstRead = port.Read(data, 0, buffersize); и после этого добавьте Debug.WriteLine(firstRead); и Debug.WriteLine(BitConverter.ToString(data)); проверку в окне вывода отладки Visual Studio, если вы получаете ожидаемые данные.   -  person rene    schedule 07.09.2014
comment
Это полностью задумано, вы получаете столько байтов, сколько доступно в буфере приема. Обычно не больше одного-двух. Вы должны изменить свой код, чтобы не начинать обработку данных, пока вы не получите все их.   -  person Hans Passant    schedule 07.09.2014


Ответы (2)


Обработчик DataReceived вызывается всякий раз, когда данные доступны в полученном буфере. Поэтому прочитайте все данные в буфере, а затем обработайте заголовок и т. д., прежде чем будет получен следующий пакет данных. После получения новых данных старые данные перезаписываются, что приводит к потере данных. В вашем случае вы читаете только 1 байт при вызове port.Read(). Я бы изменил это на port.Read(test, 0, bufferSize);

Кроме того, я бы просто сохранил данные в буфере, а обработка данных выполнялась в отдельном потоке. Чем больше времени вы проводите в обработчике, тем выше вероятность потери данных.

person DroidSK    schedule 07.09.2014

проблема была решена путем сохранения всех данных в буфере:

private void port_DataReceived_1 (отправитель объекта, SerialDataReceivedEventArgs e) { int bytenumber; байт[] данные = новый байт[10];

        bytenumber = port.Read(data, 0, 10);

        if (data[0] == 0xFF)
        {
        }
    }

и т.п.

person AKAP    schedule 14.09.2014