2 / 2 / 0
Регистрация: 29.09.2015
Сообщений: 29

COM-порт принимает не все пакеты

21.10.2015, 10:19. Показов 1886. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
И так, у меня есть программа которая работает с com-портом. Но проблема в том, что не всегда он получает все пакеты(где-то что-то теряет). Видимо нужно добавить Timer(). Но честно с ним не работал. Может подскажете как его реализовывать. Точнее где он нужен в чтении пакета.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 COM Com = new COM("COM7", 9600, Parity.None, 8, StopBits.One);
                Com.Open("COM7", 9600, Parity.None, 8, StopBits.One);
                int i = 1;
                While(i<5)
               {
                     DataToByte.Clear();
                     DataToByte.AddRange(AddrBig); // сначала старшие
                     DataToByte.AddRange(ModRTU_CRC16(DataToByte, DataToByte.Count)); 
                     Com.Write(DataToByte);//отправляю запрос
                     Thread.Sleep(1);// не помогает
                     Conn(Com.Read()); //читаю ответ
                     i++;
               }
                Com.Close();//закрываю порт
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.10.2015, 10:19
Ответы с готовыми решениями:

Сервер принимает пакеты если клиент указывает неверный порт получателя UDP.
Вот возникла проблема не могу понять почему сервер принимает пакеты если клиент указывает неверный порт получателя UDP. Кто то может...

Как посылать пакеты из программки на все машины сети в определенный порт?
Как посылать пакеты из программки на все машины сети в определленый порт? Просто надо сделать небольшой чат под ЛВС, но хотелось бы без...

Не принимает пакеты
Доброго времени суток Уважаемые форумчане. Нуждаюсь в вашей помощи. Опищу что есть и какая проблема. Интернет клуб. 6 компов...

12
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.10.2015, 10:30
Цитата Сообщение от inavalny Посмотреть сообщение
проблема в том, что не всегда он получает все пакеты(где-то что-то теряет).
Протокол обмена с устройством известен?
Если да, то просто в цикле крутить проверку на количество байт в буфере порта, как накопилось сколько должно, согласно протоколу обмена, то запускать чтение данных.
0
2 / 2 / 0
Регистрация: 29.09.2015
Сообщений: 29
21.10.2015, 10:35  [ТС]
insite2012, это я внутри Com.Read() делаю
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
 public byte[] Read()
            {
                int readedBytesCount = 0;               // счётчик считанных байтов
                byte len = 0;                           // длина поля DATA
                byte[] result = { 0x00 };
                int cap = 0x00;
                byte[] crc = new byte[2];
                int chance = 0;
                while (true)
                {
                    try
                    {
                        if (!port.IsOpen)
                        {
                            break;
                        }
                        lock (portLocker)
                        {
 
                            if (port.BytesToRead < 1)
                            {
                                if (chance > 100)
                                {
                                    cap = 0x08;
                                    break;
                                }
                                continue;
                            }
                            byte[] receiveBuffer = new byte[port.BytesToRead];    // приёмный буфер
                            //address
                            readedBytesCount += port.Read(receiveBuffer, readedBytesCount, 4);
                            readedBytesCount += port.Read(receiveBuffer, readedBytesCount, 1);
                            //len
                            readedBytesCount += port.Read(receiveBuffer, readedBytesCount, 1);
                            len = receiveBuffer[readedBytesCount - 1];
                            result = new byte[len];
                            //data
                            readedBytesCount += port.Read(result, 0, len);
                            result.CopyTo(receiveBuffer, readedBytesCount - len);
                            //crc16
                            readedBytesCount += port.Read(crc, 0, 2);
                            byte[] crc16 = ModRTU_CRC16(receiveBuffer, receiveBuffer.Length - 2);
                            if (crc16.SequenceEqual(crc))
                            {
                            cap = 0x00;
                            port.ReadExisting();
                            return result;
                            }
                        }
                    }
                    catch (Exception) { }
                    Thread.Sleep(1);
                    return null;
                }
                return null;
            }
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.10.2015, 10:43
Цитата Сообщение от inavalny Посмотреть сообщение
это я внутри Com.Read() делаю
1. Мне ваш код ни о чем не говорит, поскольку я не знаю логики работы.
2. Слишком у вас как-то сложно, думаю можно было проще.
3. Я спрашивал, известен ли протокол. Так какой ответ?
0
2 / 2 / 0
Регистрация: 29.09.2015
Сообщений: 29
21.10.2015, 10:47  [ТС]
insite2012, ну конечно известен, я же Вам в куске кода показал, что читаю побайтово -сначала 4 байта адрес устройства, потом длину данных, потом сами данные и контрольную сумму. если что-то не так, попадает в эксепшн.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.10.2015, 10:53
Цитата Сообщение от inavalny Посмотреть сообщение
читаю побайтово -сначала 4 байта адрес устройства, потом длину данных, потом сами данные и контрольную сумму.
А зачем так сложно? Если протокол известен, то как правило и полный размер пакета для приема тоже известен. Тогда зачем читать кусками? Заполнился полностью буфер, считали из него все, а потом разбивайте на куски, проверяйте и так далее, в общем обрабатывайте данные.
0
2 / 2 / 0
Регистрация: 29.09.2015
Сообщений: 29
21.10.2015, 10:53  [ТС]
insite2012, я наверно неправильно сформировал вопрос. Дело в том что мне кажется ответ с компорта приходит позже чем я его начинаю читать и поэтому я данные не получаю. Скорее всего надо чтоб программа немного подождала после отправки запроса. Вот я и думаю как это сделать
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.10.2015, 11:04
Цитата Сообщение от inavalny Посмотреть сообщение
Вот я и думаю как это сделать
Сейчас покажу примерный вариант.

Добавлено через 8 минут
inavalny, в самом простом случае, без обработки ошибок и не используя потоки (хотя это все не сложно), метод чтения я бы организовал примерно так.
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.Threading;
using System.Threading.Tasks;
using System.IO.Ports;
 
namespace ConsoleApplication6 {
    class Program {
        static void Main(string[] args) {
        }
 
        static void ReadData(string portName, List<byte> outData, int readCount) {
            using (SerialPort port = new SerialPort(portName, 9600)) {
                port.Open();
                for (int i = 0; i < 10; i++) {
                    if (port.BytesToRead != readCount) {
                        Thread.Sleep(100);
                        continue;
                    }
                    byte[] temp = new byte[readCount];
                    port.Read(temp, 0, readCount);
                    outData.Clear();
                    outData.AddRange(temp);
                    return;
                }
                throw new TimeoutException("NO DATA!");
            }
        }
    }
}
0
2 / 2 / 0
Регистрация: 29.09.2015
Сообщений: 29
21.10.2015, 11:17  [ТС]
insite2012, То есть Вы предлагаете перед чтением с компорта проверить равен ли port.BytesToRead с количеством байтов для данного ответа на запрос..но запросы сами по себе разные и у каждого свой readCount. То есть предлагаете прописать для каждого вида запроса еще и его длину? Допустим вариантов запросов около сотни. Мне для каждого прописывать readCount??
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.10.2015, 11:23
Цитата Сообщение от inavalny Посмотреть сообщение
Допустим вариантов запросов около сотни.
Это много, на ваш взгляд?
Цитата Сообщение от inavalny Посмотреть сообщение
Мне для каждого прописывать readCount??
А почему нет? Работать желательно согласно протоколу, а не читать наобум, сколько придет.
Для упрощения могу предложить такую организацию: делаете словарь, в который и заносите все пары размер чтения - сам запрос (или еще как-то организовать, подобным образом).
Плюсы: вы будете читать именно столько, сколько следует при этом варианте запроса, а не неизвестное количество, ну и если понадобится добавить запрос (а он может использоваться не в одном метода, а в нескольких, так ведь?), то придется всего добавить одну запись в словарь.
0
2 / 2 / 0
Регистрация: 29.09.2015
Сообщений: 29
21.10.2015, 13:05  [ТС]
Проблема решена. Поставил просто побольше миллисекунд поспать и все заработало
C#
1
2
3
 Com.Write(bufForWrite);
                    Thread.Sleep(999);
                    byte[] buffreader = Com.Read();
Предложение insite2012, хорошее, но не забываем про человеческий фактор и не всегда протоколы прописаны правильно, а ждать определенное количество байтов и если их нет, то ничего не считывать, приводит к тому что никаких даже не по размеру данных не считывает. А лучше чтоб прога показывала, что она хоть что-то считала ИМХО.
0
Эксперт .NET
 Аватар для insite2012
5548 / 4311 / 1218
Регистрация: 12.10.2013
Сообщений: 12,371
Записей в блоге: 2
21.10.2015, 14:27
Цитата Сообщение от inavalny Посмотреть сообщение
лучше чтоб прога показывала, что она хоть что-то считала ИМХО.
Не знаю как у вас, но в моей специфике протокол - четко формализованный. И либо весь пакет пришел (тогда чтение удачно), либо нет - и тогда выбрасывается исключение об ошибке. А считывать "хоть что-то" у меня не вариант))))
0
484 / 397 / 68
Регистрация: 14.02.2014
Сообщений: 1,930
21.10.2015, 14:46
Цитата Сообщение от inavalny Посмотреть сообщение
Проблема решена. Поставил просто побольше миллисекунд поспать и все заработало
Костыль.

Протокол похож на ModBus RTU. Как правило при организации обмена с использованием этого протокола добавляется т.н. таймаут ответа. Запрос послали, начинаем принимать данные и запускаем таймер, всё, что получаем в порт - записываем в буфер пока не произойдёт одно из условий: длинна полученных данных не сравняется с ожидаемой, выйдёт время таймаута. Затем проверка контрольной суммы и обработка данных.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.10.2015, 14:46
Помогаю со студенческими работами здесь

Recvfrom() не принимает пакеты
Короче говоря в udp-клиенте , когда оставляю его принимать пакеты он просто игнорит всё и считает , что принял пакет. (короче recvfrom()...

Встроенная сеть не принимает пакеты
Всем привет. Ситуация такая: Есть мать MSI P35 Neo (MS-7360 ver 1.0) в ней встроенная сеть Realtek 8111F Втыкаю туда кабель -...

Сетевая принимает но не отправляет пакеты
Помогите плиз. Windows server 2003 просто перестал отправлять пакеты. Все было настроено и работало. В чем может быть проблема? Антивирус...

Подключение отправляет пакеты, но не принимает
Было всё нормально, проблем с подключением не было, и вдруг перестал работать интернет. Оказалось, что подключение отправляет пакеты, но не...

QUdpSocket не принимает пакеты на windows
groupAddress = QHostAddress(/*&quot;192.168.0.102&quot;*/&quot;239.255.43.21&quot;); statusLabel = new QLabel(tr(&quot;Listening for multicasted...


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

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

Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru