Аватар для chjzjk
3 / 3 / 2
Регистрация: 31.10.2013
Сообщений: 22

SerialPort(COM) Разрыв пакета при приеме

10.11.2015, 13:57. Показов 2996. Ответов 3
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вся соль в приеме данных... Настроил виртуальный порты - гоняю данные все работает идеально, пробую связать 2 машины - приходит не всЕ сообщение, а скачала кусок, потом второй кусок(пакет 15 байт). В принципе не проблема склеить пакет, но как-то не комильфо. Или так и должно быть?
Могу приклеить код если нужно.

Добавлено через 19 минут
Вообщем решил вроде проблему. Оказалось что нужно просто поставить задержку. Ну и конечно обнулять буфер после приема.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//где-то в конструкторе 
 _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;
        }
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
10.11.2015, 13:57
Ответы с готовыми решениями:

Возможно ли при импорте в модуль пакета подняться выше пакета?
Есть скрипты .py, лежащие на одном уровне(в одном каталоге) и есть пакет модулей, лежащий на том же самом уровне. Возможно ли...

Виснет USART при приеме
Добрый вечер всем. Подскажите как решить проблему с USORT. Проверяю через proteus и его терминал следующий код: Вот это подключаемый...

Задание при приеме на работу
Здравствуйте, уважаемые форумчане! При устройстве на работу получила перечень заданий, с большинством из которых уже справилась. Осталось...

3
 Аватар для Sanya_sa
913 / 817 / 333
Регистрация: 03.02.2015
Сообщений: 5,276
Записей в блоге: 9
10.11.2015, 14:22
Цитата Сообщение от chjzjk Посмотреть сообщение
приходит не всЕ сообщение
это нормально что не все приходят, я сам их клею. Ща посмотрю гдето проект был давнишний.

Добавлено через 12 минут
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
       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;
        }

Давно писал только начинал программировать. так что не очень всё красиво, но зато по сей день работает отлично.
Это часть кода так что если не обьявленные методы встретети не удивляйтесь. Вам Read_data_com() и AddCommand будет интересен. В ParseData просто через case выбираем нужные пакеты.
0
 Аватар для chjzjk
3 / 3 / 2
Регистрация: 31.10.2013
Сообщений: 22
11.11.2015, 10:48  [ТС]
Хз, вроде не очень правильно ожидать 4096 байт. Тем более, что вы их никогда не получите целиком и массив будет забиваться до конца нулями, от сюда и клейка пакета. Я организовывал передачу на 2 устройствах сразу, то есть под конкретную задачу(пакет 15 байт) и их реально можно получать применив задержку. Думал что достаточно будет установить параметр serialPort.ReadTimeout, но у меня почему-то он, ни на что не влиял. Обычно при большом ожидании данных используют побайтовое чтение (зная за ранее размер данных, или управляющий конечный символ)
0
-31 / 2 / 2
Регистрация: 05.09.2018
Сообщений: 184
13.08.2021, 10:52
Цитата Сообщение от chjzjk Посмотреть сообщение
Вообщем решил вроде проблему. Оказалось что нужно просто поставить задержку. Ну и конечно обнулять буфер после приема.
А куда вы добавили задержку?
Я пользуюсь свойством read timeout, но оно ни на что не влияет, и пакет всё равно разрывается
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.08.2021, 10:52
Помогаю со студенческими работами здесь

Задача при приеме на работу
Офигенская задача, я ее давно услышал. Сейчас Вам повествую о ней Пришел один человек для приема на работу. Ему задают 4...

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

Траблы с MSCOMM при приеме SMS
Приветствую форумчан. Кто нибудь занимался приемом SMS с трубы подключенной через DATA-кабель к компу? Пробовал использовать...

Тестовое задание при приеме на работу
Друг искал работу. В одной из контор предложили тестовое задание: ----- Разработать на VC векторный графический редактор, с...

Типовые задачи при приеме на работу программистом
Добрый вечер! Подскажите какие задачи задают при приеме на работу стажере! На собеседование был один раз задали инвертировать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

Новые блоги и статьи
Отчёт о спецтехнике находящейся в ремонте
Maks 20.04.2026
Отчёт из решения ниже размещен в конфигурации КА2. Задача: отобразить спецтехнику, которая на данный момент находится в ремонте. Есть нетиповой документ "Заявка на ремонт спецтехники" который. . .
Памятка для бота и "визитка" для читателей "Semantic Universe Layer (Слой семантической вселенной)"
Hrethgir 19.04.2026
Сгенерировано для краткого описания по случаю сборки и компиляции скелета серверного приложения. И пусть после этого скажут, что статьи сгенерированные AI - туфта и не интересно. И это не реклама -. . .
Запрет удаления строк ТЧ документа при определенном условии
Maks 19.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "Аккумуляторы", разработанного в конфигурации КА2. У данного документа есть ТЧ, в которой в зависимости от прав доступа. . .
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru