С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/21: Рейтинг темы: голосов - 21, средняя оценка - 4.86
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
.NET 4.x

Чтение COM - порта

20.01.2017, 13:28. Показов 4166. Ответов 24
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.
Опишу для начала свой проект.
У меня есть устройство АКИП. Я пишу программу для дистанционной работы с ним. Все хорошо, но есть одна проблема.
А проблема заключается в чтении данных с данного устройства.

У меня есть таймер, который читает параметры:
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
private void timer_update_current_Tick(object sender, EventArgs e)
        {
            try
            {
                if (index == dataGridView1.Rows.Count - 1)
                {
                    timer_update_current.Stop();
                }
                else if (index < dataGridView1.Rows.Count - 1)
                {
                    proc_work.SelectedIndex = proc_work.Items.Count - 1;
                    var value = current_vol.Text;
                    value = value.Replace(".", ",");
                    min_string = Convert.ToDecimal(value);
 
                    if (target_port.IsOpen)
                    {
                        if (min_string > min_user)
                        {
                            String current_volt = "MEAS:Volt?;";
                            byte[] outByte = Encoding.UTF8.GetBytes(current_volt);
                            target_port.Write(outByte, 0, outByte.Length);
 
                            Thread.Sleep(250);
 
                            try
                            {
                                byte[] inputByte = new byte[9];
                                target_port.Read(inputByte, 0, inputByte.Length);
                                string curr = Encoding.ASCII.GetString(inputByte);
                                curr = System.Text.RegularExpressions.Regex.Replace(curr, @"\s+", " ");
 
                                this.BeginInvoke(new delegate_for_monitoring_current_voltage(add_current_voltage), new object[] { curr });
                            }
                            catch (TimeoutException) { }
 
                            Thread.Sleep(20);
 
                            String current_ampere = "MEAS:CURR?;";
                            byte[] outAp = Encoding.UTF8.GetBytes(current_ampere);
                            target_port.Write(outAp, 0, outAp.Length);
 
                            Thread.Sleep(250);
 
                            try
                            {
                                byte[] inAp = new byte[9];
                                target_port.Read(inAp, 0, inAp.Length);
                                string ampere = Encoding.ASCII.GetString(inAp);
                                ampere = System.Text.RegularExpressions.Regex.Replace(ampere, @"\s+", " "); ;
 
                                this.BeginInvoke(new delegate_for_monitoring_current_ampere(add_current_ampere), new object[] { ampere });
                            }
                            catch (TimeoutException) { }
 
                            Thread.Sleep(20);
 
                            String current_power = "MEAS:POW?;";
                            byte[] outPower = Encoding.UTF8.GetBytes(current_power);
                            target_port.Write(outPower, 0, outPower.Length);
 
                            Thread.Sleep(250);
 
                            try
                            {
                                byte[] inPower = new byte[9];
                                target_port.Read(inPower, 0, inPower.Length);
                                string power = Encoding.ASCII.GetString(inPower);
                                power = System.Text.RegularExpressions.Regex.Replace(power, @"\s+", " ");
 
                                this.BeginInvoke(new delegate_for_moniroting_current_power(add_current_power), new object[] { power });
                            }
                            catch (TimeoutException) { }
 
                            if (proc_work.Items.Count > 0)
                                proc_work.SelectedItem = proc_work.Items.Count;
 
                            this.update_current();
                        }
                        else if(min_string <= min_user)
                        {
                            dataGridView1.Rows[0].Selected = true;
                            stage_timer.Stop();
                            timer_update_current.Stop();
                            target_port.Write("load off ;");
                            dataSource.Add("__________________________________________________________________");
                            dataSource.Add(DateTime.Now.ToLongDateString() + DateTime.Now.ToLongTimeString() +
                                " - тест завершен по достижению \n минимального значения напряжения.");
                            dataSource.Add("Значение напряжения по окончанию: " + current_vol.Text);
                            dataSource.Add("Этапов пройдено: " + count_stage);
                            dataSource.Add("Затраченное время: " + stopw.Elapsed.ToString());
                            
                            MessageBox.Show("Процесс тестирования завершен по достижению минимального значения напряжения." + "\n" +
                            "Количество пройденных этапов: " + num_stage.Text + "\n" + "\n" +
                            "Затраченное время: " + stopw.Elapsed.ToString(), 
                            "Конец тестирования", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    else
                    {
                        control_tab.SelectedIndex = 2;
                        qDebug.Items.Add(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() +
                                " >> " + "Устройство не доступно! Проверьте подкючение..." + "\n");
                    }
                }
            }
            catch (Exception error)
            {
                qDebug.Items.Add(DateTime.Now.ToLongDateString() + " " + DateTime.Now.ToLongTimeString() + " >> " + error.Message + "\n" + error.ToString() + "\n");
                return;
            }
        }
В ней все работает, хорошо.

Теперь о проблеме:
В данной функции я испольную задержки с помощью
C#
1
Thread.Sleep(250);
Данные приходят хорошо, без потерь.
Но когда я убираю задержку, данные начинаю приходить как то... не совсем так как нужно. Скрины предоставлены.

Вопрос:
Что мне сделать, чтобы при чтении, данные приходили нормально, без использования остановок.

1 Скрин - с использованием Thread.Sleep();
2 Скрин - без использования Thread.Sleep();
Миниатюры
Чтение COM - порта   Чтение COM - порта  
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.01.2017, 13:28
Ответы с готовыми решениями:

Быстрое чтение COM порта
Здравствуйте. Есть мк, который по com порту передает данные. Например, 110 байт каждые 0.04с. Скорость передачи ~7000байт/с. Требуется их...

Чтение данных с COM порта
Есть два оборудования которые между собой подключены через COM. Одно все время передает данные другому. Хочу данные перехватить. Написал...

Чтение данных с COM-порта
Добрый день. Помогите пожалуйста. Я подаю команду, чтобы поменялись цифры на приборе и нужно чтобы эти цифры отобразились у меня в...

24
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
23.01.2017, 09:30  [ТС]
Неужели никто не сталкивался с подобным?
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
23.01.2017, 09:55
Откажитесь от sleep и от таймера вообще. Это потребует изменения кода обмена.
Отдельный поток постоянно посылает запрос и ждёт ответа. После получения посылает новый запрос.
Пример я тут приводил где-то, и в блоге немного есть.
0
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
25.01.2017, 16:14  [ТС]
Rius, Я прочитал ваш блог, попробовал реализовать на своем коде, но к сожалению ничего не вышло..
Не могли бы вы привести простенький пример асинхронного чтение порта, не в консольном приложении, а Form?
Буду очень благодарен)
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
25.01.2017, 16:46
Лучший ответ Сообщение было отмечено Dragon7788 как решение

Решение

Вот.
Вложения
Тип файла: zip Dragon7788.zip (17.3 Кб, 43 просмотров)
1
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
25.01.2017, 16:58  [ТС]
Rius, Спасибо большое за пример.
Вот еще вопрос. А как данные получить в виде строки? То есть мне должны приходить показания прибора, как показано на скрине в вопросе.
По поводу Encoding я знаю.
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
25.01.2017, 17:19
C#
1
2
string answerString = Encoding.ASCII.GetString(answerBytes, 0, receivedCount);
Task.Factory.StartNew(() => this.Text = answerString, token, TaskCreationOptions.None, this.mContextUI);
Добавлено через 16 минут
Второй строкой можно передать строку из отдельного потока в поток UI.
Аналогично и в RichTextBox, и куда угодно в UI.
0
36 / 25 / 12
Регистрация: 08.04.2013
Сообщений: 269
25.01.2017, 17:19
Rius, а если между пакетами производителем предусмотрены определенные таймауты, то как без Sleep?
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
25.01.2017, 17:20
Покажите, о чём речь. "Таймаут" тут может быть не подходящее слово.
0
36 / 25 / 12
Регистрация: 08.04.2013
Сообщений: 269
25.01.2017, 17:26
Мне надо отправить 300 байт в устройство. Межбайтовый интервал 5мс. Отправили 300 байт за условных 1500мс, потом устройство ждем интервал, убеждается что мы ему больше ничего не шлем и отправляет ответ.
0
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
25.01.2017, 17:32  [ТС]
Rius,
Цитата Сообщение от Rius Посмотреть сообщение
Task.Factory.StartNew(() => this.Text = answerString, token, TaskCreationOptions.None, this.mContextUI)
Тут мы создаем процесс, который при получении данных, выводит текст в форму. Я правильно понял?
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
25.01.2017, 17:40
lemeserg, не видел ни одного устройства, которое не может принять некоторый непрерывный пакет байт на поддерживаемой им скорости, а требует огромной задержки между байтами. Допускаю, что такие существуют, но работу с ними не рассматриваю.

Интервал между пакетом запроса и ответа указывается во 2 и 3 параметрах функции SendRecv.
2 - интервал t1, от отправки запроса до получения первого байта ответа. Если ответ за это время не начал передаваться, то больше не ждём.
3 - интервал t2, от приёма последнего байта ответа до возврата. На случай запоздавших байт.


Dragon7788, не процесс, а задачу. В общем да. Это один из способов обращения из потока к UI.
0
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
25.01.2017, 17:50  [ТС]
Rius, Прощу прощение, ошибся.
У меня еще есть таймер работы, где задается интервал считывания в ручную.
Получается мне нужно отправлять запросы к устройству в нем.
А чтобы получить данные как у меня в скринах, то есть последовательно, нужно:
отправлять запрос, по приходу ответа записывать его в строку, а после отправлять новый запрос и так писать в новую строку?
Пример:
C#
1
2
3
4
port.Write(buffer, 0, buffer.Lengh);
string a = <<полученные данные>>
port.Write(...);
string b = <<полученные данные>>
Что то типа такого?
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
25.01.2017, 17:54
Типа того.
Интервал между запросами можно ограничить через
C#
1
token.WaitHandle.WaitOne(int millisecondsTimeout);
В отличие от Sleep, отсюда при необходимости возможен мгновенный выход.
0
36 / 25 / 12
Регистрация: 08.04.2013
Сообщений: 269
25.01.2017, 18:13
Rius, что это за функция? Не нашел про SendRecv
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
25.01.2017, 18:14
lemeserg, в исходниках, в архиве. И здесь: https://www.cyberforum.ru/blog... g4357.html
1
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
26.01.2017, 09:33  [ТС]
Rius, Утро доброе.
Попробовал я сегодня ваш пример на оборудовании, но ничего не работает...
Порт настроен и подключен, отправка данных идет. Но ответа нет...
В чем может быть проблема?
0
Эксперт .NET
 Аватар для Rius
13075 / 7636 / 1669
Регистрация: 25.05.2015
Сообщений: 23,234
Записей в блоге: 14
26.01.2017, 09:43
Доброго.
Он и не должен работать сразу. У вас свои настройки последовательного порта. Скорость там, чётность, контроль передачи...
И интервалы времени тоже свои.
0
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
26.01.2017, 12:24  [ТС]
Rius, Спасибо большое, помогло. Читает без потерь даже)
Только вот у меня вопрос еще...
Как я писал выше, у меня есть таймер этапов тестирования, в котором отправляется запрос к устройству, то есть напряжение мощность ток.
Сам процесс идет, но вот только через одно место...

В таймере я отправляю запрос вот так:
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
 if (target_port.IsOpen)
                    {
                        if (min_string > min_user)
                        {
                            //String current_volt = "MEAS:Volt?;";
                            //byte[] outByte = Encoding.UTF8.GetBytes(current_volt);
                            //target_port.Write(outByte, 0, outByte.Length);
                            //
                            //Thread.Sleep(250);
 
                            command = "MEAS:Volt?;";
 
                            string voltResult = resultString;
                            
                            voltResult = System.Text.RegularExpressions.Regex.Replace(voltResult, @"\s+", " ");
                            char[] del = {
                                     '+'
                                         };
                            voltResult = voltResult.TrimStart(del);
 
                            current_vol.Text = voltResult;
 
                            dataSource.Add(DateTime.Now.ToLongTimeString() + " >> " + " Значение напряжения: " + voltResult);
 
                            chart1.Series[0].ChartType = SeriesChartType.Spline;
                            DataPoint dp = new DataPoint();
                            dp.SetValueY(voltResult);
                            dp.MarkerStyle = MarkerStyle.Circle;
                            dp.IsValueShownAsLabel = false;
                            chart1.Series[0].Points.Add(dp);
                            chart1.Invalidate();
 
                            //try
                            //{
                            //    byte[] inputByte = new byte[9];
                            //    target_port.Read(inputByte, 0, inputByte.Length);
                            //    string curr = Encoding.ASCII.GetString(inputByte);
                            //    curr = System.Text.RegularExpressions.Regex.Replace(curr, @"\s+", " ");
                            //
                            //    this.BeginInvoke(new delegate_for_monitoring_current_voltage(add_current_voltage), new object[] { curr });
                            //}
                            //catch (TimeoutException) { }
                            //
                            //Thread.Sleep(20);
 
                            //String current_ampere = "MEAS:CURR?;";
                            //byte[] outAp = Encoding.UTF8.GetBytes(current_ampere);
                            //target_port.Write(outAp, 0, outAp.Length);
                            //
                            //Thread.Sleep(250);
 
                            command = "MEAS:CURR?;";
 
                            string currResult = resultString;
 
                            currResult = System.Text.RegularExpressions.Regex.Replace(currResult, @"\s+", " ");
                            char[] del1 = {
                             '+'
                                         };
                            currResult = currResult.TrimStart(del1);
 
                            dataSource.Add(DateTime.Now.ToLongTimeString() + " >> " + " Значение тока: " + currResult);
 
                            chart1.Series[1].ChartType = SeriesChartType.Spline;
                            DataPoint dp1 = new DataPoint();
                            dp1.SetValueY(currResult);
                            dp1.MarkerStyle = MarkerStyle.Circle;
                            dp1.IsValueShownAsLabel = false;
                            chart1.Series[1].Points.Add(dp1);
                            chart1.Invalidate();
 
                            //try
                            //{
                            //    byte[] inAp = new byte[9];
                            //    target_port.Read(inAp, 0, inAp.Length);
                            //    string ampere = Encoding.ASCII.GetString(inAp);
                            //    ampere = System.Text.RegularExpressions.Regex.Replace(ampere, @"\s+", " "); ;
                            //
                            //    this.BeginInvoke(new delegate_for_monitoring_current_ampere(add_current_ampere), new object[] { ampere });
                            //}
                            //catch (TimeoutException) { }
                            //
                            //Thread.Sleep(20);
                            //
                            //String current_power = "MEAS:POW?;";
                            //byte[] outPower = Encoding.UTF8.GetBytes(current_power);
                            //target_port.Write(outPower, 0, outPower.Length);
                            //
                            //Thread.Sleep(250);
                            //
                            //try
                            //{
                            //    byte[] inPower = new byte[9];
                            //    target_port.Read(inPower, 0, inPower.Length);
                            //    string power = Encoding.ASCII.GetString(inPower);
                            //    power = System.Text.RegularExpressions.Regex.Replace(power, @"\s+", " ");
                            //
                            //    this.BeginInvoke(new delegate_for_moniroting_current_power(add_current_power), new object[] { power });
                            //}
                            //catch (TimeoutException) { }
                            //
                            //if (proc_work.Items.Count > 0)
                            //    proc_work.SelectedItem = proc_work.Items.Count;
                            //
                            this.update_current();
                        }
command типа string использую для отправки команды в порт.

При работе у меня приходят значение: (Скрин)


Подскажи пожалуйста, как это можно исправить?
Миниатюры
Чтение COM - порта  
0
36 / 34 / 20
Регистрация: 17.03.2015
Сообщений: 175
26.01.2017, 15:20  [ТС]
Или как можно последовательно делать запрос ответ?
То есть:
port.Write("meas:volt?;");
ответ
port.Write("meas:Pow?;");
ответ
port.write("meas:curr?;");
Ответ

А после повтор.

Добавлено через 1 час 47 минут
Просто с одним запросом все хорошо... а вот как с остальными, что то не могу понять...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
26.01.2017, 15:20
Помогаю со студенческими работами здесь

Чтение и проверка троек байт с последовательного порта, serialPort.Read()
Доброго времени суток! Буду рад Вашему совету о дальнейшем направлении разработки. Читаю данные с порта. Нужные данные...

Чтение из com порта
есть устройство посылающее данные в ком порт. нужно их прочитать и сделать запрос на sql сервер. я открываю порт и в таймере читаю функцией...

Чтение из серийного порта
Доброго времени суток! Снова нужна ваша помощь. Надо читать информацию из последовательного порта пока не получим некоторую строку: ...

Чтение COM-порта с заданным периодом
Есть необходимость в режиме реального времени читать данные с порта и выводить на экран. Скорость данных достаточно большая, поэтому если...

Чтение из COM-порта, странная ошибка
Работаю с СОМ-портом, алгоритм обмена следующий : послали команду - подождали 100 мс - посмотрели, что пришло в ответ. В целом все...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes. А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru