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;
}