SerialPort(COM) Разрыв пакета при приеме - C#
Формулировка задачи:
Вся соль в приеме данных... Настроил виртуальный порты - гоняю данные все работает идеально, пробую связать 2 машины - приходит не всЕ сообщение, а скачала кусок, потом второй кусок(пакет 15 байт). В принципе не проблема склеить пакет, но как-то не комильфо. Или так и должно быть?
Могу приклеить код если нужно.
Вообщем решил вроде проблему. Оказалось что нужно просто поставить задержку. Ну и конечно обнулять буфер после приема.
//где-то в конструкторе _serialPort.DataReceived += _serialPort_DataReceived; void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e) { Thread.Sleep(15); ReadFromComPort(); _serialPort.DiscardInBuffer(); } public bool ReadFromComPort() { int CountReadBuf = _serialPort.BytesToRead; if (CountReadBuf != 0) { //MessageBox.Show("Count=" + CountReadBuf.ToString()); byte[] ReadBuffer = new byte[CountReadBuf]; try { _serialPort.Read(ReadBuffer,0,CountReadBuf); MessageIn.Add(new MessagePer("COM",ReadBuffer,"INPUT"));// моя обработка //MessageBox.Show(String.Join(" ",MessageIn[MessageIn.Count-1].Data)); return true; } catch (Exception ex) { MessageBox.Show("Error Read to serial port :: " + ex.Message, "Error!"); return false; } } return false; }
Решение задачи: «SerialPort(COM) Разрыв пакета при приеме»
textual
Листинг программы
public event EventHandler end_data; public event EventHandler get_ans_dl_point; // Для обработки данных и подключения к СОМ порту public void scan_ports() { while(true) { System.Threading.Thread.Sleep(65); if(!on) { on = Scan_com_ports(); all_reset(); } else { id_lave = true; // установим id_lave в true если Read_data_com не выставит в false //то читаем дальше если нет то пытаемся сново пронюхать порты Read_data_com(); if (!id_lave) { on = id_lave; main_serial.Close(); } } } } // Обнуляем все переменные public void all_reset() { real_cren = 0; real_tangaj = 0; axel_x = 0; axel_y = 0; axel_z = 0; giro_x = 0; giro_y = 0; giro_z = 0; real_curs = 0; real_vertical_speed = 0; real_h = 0; rssi = -1; latitude = -1; longitude = -1; curs_gps = 0; h_gps = 0; speed_gps = 0; satilite_gps = -1; I_last = 0; ; I = 0; ; U = -1; ; U_ant = -1; stat_system = false; stat_motors = false; stat_load = false; stat_around = false; stat_start = false; stat_end = false; stat_stop = false; stat_gps = false; stat_home = false; } // Читаем наиболее актуальные данные из буфера СОМ порта public void Read_data_com() { try { byte[] tmp_buffer = new byte[4096]; int size = main_serial.Read(tmp_buffer, 0, 4096); // Вначале оттделим команды и сохраним их в списке команд CommandList, // в данном списке команда с одним кодом будет в единственном экземляре // таким образом команда с конкретным кодом будет являться последней пришедшей с устройства, т.е. актуальной for (int i = 0; i < size; ++i) { // Пытаемся поймать ответы на наши действия if (i < tmp_buffer.Length - 16) { if (tmp_buffer[i] == 0xff && tmp_buffer[i + 1] == 0xff && tmp_buffer[i + 2] == 0x63 && tmp_buffer[i + 4] != 0) { back_mesage[0] = tmp_buffer[i + 4]; back_mesage[1] = tmp_buffer[i + 5]; back_mesage[2] = tmp_buffer[i + 6]; back_mesage[3] = tmp_buffer[i + 7]; back_mesage[4] = tmp_buffer[i + 8]; back_mesage[5] = tmp_buffer[i + 9]; back_mesage[6] = tmp_buffer[i + 10]; back_mesage[7] = tmp_buffer[i + 11]; back_mesage[8] = tmp_buffer[i + 12]; back_mesage[9] = tmp_buffer[i + 13]; } if (tmp_buffer[i] == 0xff && tmp_buffer[i + 1] == 0xff && tmp_buffer[i + 2] == 0x64 && tmp_buffer[i + 4] != 0) { back_mesage[10] = tmp_buffer[i + 4]; back_mesage[11] = tmp_buffer[i + 5]; back_mesage[12] = tmp_buffer[i + 6]; back_mesage[13] = tmp_buffer[i + 7]; back_mesage[14] = tmp_buffer[i + 8]; back_mesage[15] = tmp_buffer[i + 9]; // Событие отклик на наши действия if (get_ans_dl_point != null) get_ans_dl_point(this, EventArgs.Empty); } } // Получен маркер нового пакета данных в то время как предыдущий пакет не был дополучен // (обеспечивается условием DataBufferSize > 1) if (tmp_buffer[i] == 0xff && DataBufferSize > 1 && DataBuffer[DataBufferSize - 1] == 0xff) { // Обнулим буффер данных от устройства DataBuffer[0] = 0xff; DataBufferSize = 1; } DataBuffer[DataBufferSize] = tmp_buffer[i]; ++DataBufferSize; // Пакеты данных всегда по MAX_DATA_SIZE байт if (DataBufferSize >= MAX_DATA_SIZE) { AddCommand(DataBuffer, DataBufferSize); // После разбора данных обнулим буффер DataBufferSize = 0; } } // После получения всех команд обработаем все данные пришедшие в _актуальных_ командах System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<byte, byte[]>> enumerator = CommandList.GetEnumerator(); while (enumerator.MoveNext()) { System.Collections.Generic.KeyValuePair<byte, byte[]> item = enumerator.Current; ParseData(item.Value, item.Value.Length); } CommandList.Clear(); // Событие окончания if (end_data != null) end_data(this, EventArgs.Empty); } catch (System.InvalidOperationException) { id_lave = false; } catch (System.Exception) { } } // Поиск нужного порта public bool Scan_com_ports() { // Очищаем массив для хранаения имён СОМ портов и записываем в него имена имеющихся СОМ в системе, // необходимо если число ком портов измененилось Array.Clear(com_array, 0, com_array.Length); com_array = System.IO.Ports.SerialPort.GetPortNames(); if (com_array.Length <= 0) return false; for (int i = 0; i < com_array.Length; ++i) { try { main_serial.Close(); if (!main_serial.IsOpen) { main_serial.PortName = com_array[i]; main_serial.BaudRate = 57600; main_serial.ReadTimeout = 2000; main_serial.WriteBufferSize = 2048; main_serial.RtsEnable = true; main_serial.DataBits = 8; main_serial.Open(); System.Threading.Thread.Sleep(310); // время для заполнения буфера СОМ порта main_serial.Read(tmp_buffer, 0, 400); System.Threading.Thread.Sleep(310); // время для заполнения буфера СОМ порта // условие того что порт нужный for (int j = 0; j < size - 16; ++j) { if (tmp_buffer[j] == 0xff && tmp_buffer[j + 1] == 0xff && tmp_buffer[j + 2] == 0x75) return true; } } } catch (System.Exception ) { } } return false; } // Комнды обрабатываются private bool AddCommand(byte[] data_buffer, int data_size) { if (data_size < MAX_DATA_SIZE || data_buffer[0] != 0xFF || data_buffer[1] != 0xFF) return false; CommandList[data_buffer[2]] = new byte[data_size]; Array.Copy(data_buffer, CommandList[data_buffer[2]], data_size); return true; }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д