Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23

Работа с COM-портом

22.09.2021, 08:37. Показов 3594. Ответов 63
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Имеется такая задача: получать данные с com порта и строить графики от полученных данных. Это удалось реализовать, но происходит запаздывание, т.к. таймер не даёт делать опрос чаще, чем нужно. Как увеличить быстродействие опроса?
Как сейчас у меня это реализовано:
Delphi
1
2
3
4
5
6
7
8
procedure TForm2.Timer1Timer(Sender: TObject);
var
  D1 := Form1.a[5] + Form1.a[6] + Form1.a[7] + Form1.a[8];
  val : double;
  hi := hi+1;
  val := StrToFloat(StringReplace(D1, '.', ',', [rfReplaceAll, rfIgnoreCase]));
  Series1.AddXY(hi,val,'',clred);
end;
Интервал у таймера выставлен 1, меньше не даёт.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.09.2021, 08:37
Ответы с готовыми решениями:

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

Работа с COM-портом
Ребят, помогите, пожалуйста, сделать работу с 7 COM-портом, вывести на него 12 вольт, чтобы заработало подключенное к нему реле. просто...

Работа с Портом RS232
Народ подскажите книгу где есть информация по работе с портом RS232 с помощю Делфи. Зарание спасибо.

63
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
27.09.2021, 11:28  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Verevkin Посмотреть сообщение
В треде ты принимаешь данные, идущие из порта,
Суть в том, что данные он ловит один раз и не обновляются, т.е. порт поймал только первую строку из порта и она в цикле действует, он не обновляет полученные данные. Обманул. Она больше обрабатывает, буквально первые полсекунды ловит нормально, и если в этот момент останавливаю поток, вылета программы нет.
0
Модератор
4156 / 2365 / 814
Регистрация: 15.11.2015
Сообщений: 9,502
27.09.2021, 11:30
Цитата Сообщение от WinKarbik Посмотреть сообщение
таймер с частотой 1мс обеспечивает 1000Гц
Да. А с какой частотой данные идут в порт?
0
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
27.09.2021, 11:32  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Да. А с какой частотой данные идут в порт?
Микроконтроллер 72 МГц. Если идёт речь о скорости порта, то 115200.
0
Модератор
4156 / 2365 / 814
Регистрация: 15.11.2015
Сообщений: 9,502
27.09.2021, 11:34
Получается, надо в потоке взять память под буфер для 10-100 значений, когда буфер заполнится, то можно отправить основному окну сообщение с адресом этого буфера (PostMessage), и тут же браться за приём нового буфера данных. А основной поток программы получит сообщение, построит график сразу на весь буфер и освободит память буфера.

Добавлено через 1 минуту
Цитата Сообщение от WinKarbik Посмотреть сообщение
Если идёт речь о скорости порта, то 115200.
Не совсем. Частота опроса датчиков какая?
0
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
27.09.2021, 11:54  [ТС]
Цитата Сообщение от AzAtom Посмотреть сообщение
Частота опроса датчиков какая?
Я так понимаю такая же, как и частота микроконтроллера, программно не ограничивал. STM32F103, могу на обычной Arduino Nano реализовать это.

А вообще частоты 1 кГц для опроса должно хватать под цели.

Добавлено через 17 минут
Проблема была с синхронизацией. Поборол, теперь пока дальше сам разберусь.
0
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
28.09.2021, 07:35  [ТС]
Сейчас не могу побороть другую проблему. Почему то именно в треде не работает как должно. У меня приходит строка вида:
Code
1
D1: 1.70 D2: 1.60 D3: 1.83 D4: 1.71 D5: 1.65 D6: 1.64 D7: 1.80 D8: 1.69 D9: 1.71
Но иногда почему то она приходит не в таком формате, а например:
Code
1
D1: 1.70 D2: 1.60 D3: 1.8
И программа вылетает при попытке построить график. Если же в таймере я начал мерить длину полученных данных:
Code
1
if Length(Form1.a) = 245 then begin
То в треде почему то это не работает и периодически ловлю ошибку. Код:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
procedure TMyThread.DoSync;
begin
  Form2.Memo1.Lines.Add(b);
  Form2.Chart1.MaxPointsPerPage := 200;
  Form2.Chart1.NextPage;
  Form2.Series1.AddXY(hi,val,'',clred);
end;
 
procedure TMyThread.Execute;
begin
  while not Terminated do begin
    if Length(Form1.a) = 245 then begin
      b := Form1.a;
      hi := hi+1;
      D1 := b[5] + b[6] + b[7] + b[8];
      val := StrToFloat(StringReplace(D1, '.', ',', [rfReplaceAll, rfIgnoreCase]));
      Form1.a :='';
      Synchronize(DoSync);
    end;
  end;
end;
ЧЯДНТ?
0
Нарушитель
10908 / 5836 / 1289
Регистрация: 12.03.2015
Сообщений: 26,934
28.09.2021, 08:21
Цитата Сообщение от WinKarbik Посмотреть сообщение
То в треде почему то это не работает и периодически ловлю ошибку. Код:
Тебе же 100500 раз сказали - не лезть в VCL внутри побочного треда.
Похоже, у тебя неизлечимый случай.
Кликните здесь для просмотра всего текста
0
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
28.09.2021, 08:57  [ТС]
Цитата Сообщение от Verevkin Посмотреть сообщение
не лезть в VCL внутри побочного треда.
Где же я сейчас то лезу? У меня всё связанное с VCL в DoSync
0
Нарушитель
10908 / 5836 / 1289
Регистрация: 12.03.2015
Сообщений: 26,934
28.09.2021, 09:02
Цитата Сообщение от WinKarbik Посмотреть сообщение
Где же я сейчас то лезу? У меня всё связанное с VCL в DoSync
0
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
28.09.2021, 09:14  [ТС]
Так это же переменная, переменная 'a' - это данные с компорта. Ладно, допустим, очистка переменной, я ещё могу понять, что обнуляю её в потоке - это плохо, но как я обращаюсь к визуализации? И как тогда реализовать?
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
procedure TMyThread.DoSync;
begin
  Form2.Memo1.Lines.Add(D1);
  Form2.Chart1.MaxPointsPerPage := 200;
  Form2.Chart1.NextPage;
  Form2.Series1.AddXY(hi,val,'',clred);
end;
 
procedure TMyThread.Execute;
begin
  while not Terminated do begin
    b := Form1.a;
    if Length(b) = 245 then begin
      hi := hi+1;
      D1 := b[5] + b[6] + b[7] + b[8];
      val := StrToFloat(StringReplace(D1, '.', ',', [rfReplaceAll, rfIgnoreCase]));
      Synchronize(DoSync);
      b := '';
    end;
  end;
end;
Если делаю так, то данные обновляются только полсекунды
0
Нарушитель
10908 / 5836 / 1289
Регистрация: 12.03.2015
Сообщений: 26,934
28.09.2021, 09:24
Цитата Сообщение от WinKarbik Посмотреть сообщение
И как тогда реализовать?
Выкинуть всё, что написал, открыть книжку на разделе "многопоточное программирование", прочитать пару раз, и, если допрёт, написать прогу с нуля.

Тред должен быть ПОЛНОСТЬЮ ОТВЯЗАН от ВСЕГО ОСТАЛЬНОГО, что происходит в программе, он ВАЩЕ не должен знать, что вокруг него что-то есть, и только выполнять СВОЮ задачу - приём данных и пихание этих данных в очередь (синхронно или внутри критической секции). Выниманием данных из этой очереди и их анализом должен заниматься ДРУГОЙ тред, например ГЛАВНЫЙ, но это необязательно.

Убери с формы компонент TComportDriver и создавай его динамически как дочернее поле треда. Обработчик события этого компонента OnReceiveData должен быть методом ТРЕДА, а не формы.

Вот с этого надо начинать.
0
Модератор
4156 / 2365 / 814
Регистрация: 15.11.2015
Сообщений: 9,502
28.09.2021, 09:33
Цитата Сообщение от WinKarbik Посмотреть сообщение
Так это же переменная, переменная 'a' - это данные с компорта.
Переменная "a" это массив, который заполняется в одном потоке, и независимо от него считывается в другом потоке.

Нужно при заполнении массива давать знак потоку, который обработает данные. А до тех пор поток не должен читать неполные данные.
0
0 / 0 / 0
Регистрация: 21.09.2021
Сообщений: 23
04.11.2021, 09:33  [ТС]
Всем спасибо, решил проблему с задержкой, осталась ещё одна беда. Когда я выдёргиваю USB, программа не даёт больше не подключиться и не отключиться от COM порта, подскажите, как решить это можно?
0
Нарушитель
10908 / 5836 / 1289
Регистрация: 12.03.2015
Сообщений: 26,934
04.11.2021, 15:42
Цитата Сообщение от WinKarbik Посмотреть сообщение
Когда я выдёргиваю USB, программа не даёт больше не подключиться и не отключиться от COM порта, подскажите, как решить это можно?
Не выдёргивай.
----
А если суръёзно, то надо проводить финализацию (аварийное отключение и закрытие всех открытых хэндлов) внутри обработчика сообщения WM_DEVICECHANGE. Вот с этого начни:

0
242 / 208 / 36
Регистрация: 19.02.2021
Сообщений: 1,431
04.11.2021, 17:26
Возможно, я что-то упустил, но разве данные с ком-порта не по событию приходят? Зачем таймер?
0
Нарушитель
10908 / 5836 / 1289
Регистрация: 12.03.2015
Сообщений: 26,934
04.11.2021, 17:42
Цитата Сообщение от Constcat Посмотреть сообщение
Зачем таймер?
Например, штоб не отрисовывать графики 1000 раз в секунду.
0
242 / 208 / 36
Регистрация: 19.02.2021
Сообщений: 1,431
05.11.2021, 00:45
Цитата Сообщение от Verevkin Посмотреть сообщение
Например, штоб не отрисовывать графики 1000 раз в секунду.
Я имел ввиду, что опрашивать ком-порт не по таймеру, а по событию.
Данные накапливать, а выводить уже с необходимой частотой.
0
Нарушитель
10908 / 5836 / 1289
Регистрация: 12.03.2015
Сообщений: 26,934
05.11.2021, 00:56
Цитата Сообщение от Constcat Посмотреть сообщение
Я имел ввиду, что опрашивать ком-порт не по таймеру, а по событию.
А я имел в виду - опрашивать так, как хочется (даже непрерывно, если это необходимо), а отображать - по таймеру (например). Вся суть - в разделении этих двух действий на независимые треды.
0
пофигист широкого профиля
4770 / 3207 / 862
Регистрация: 15.07.2013
Сообщений: 18,616
05.11.2021, 00:58
Цитата Сообщение от Constcat Посмотреть сообщение
Я имел ввиду, что опрашивать ком-порт не по таймеру, а по событию.
А этого уже никто не умеет, кроме стариков.
И вот что особенно важно. Вот такие проблемы с выдергиванием преобразователя из USB случаются с теми, кто читает порт в доппотоке! У тех кто работает с СОМ-портом в главном потоке используя асинхронный метод работы таких проблем нет.
Я как-то лет надцать назад наглядно продемонстрировал своим коллегам. Программа нашего программиста работающая с СОМ-портом в синхронном режиме вешалась наглухо при выдергивании кабеля из USB-порта. Моя тестовая программа при таком действии выдавала сообщение типа "Воткни разъём в зад зараза!"
А после втыкания продолжала нормально работать.
0
242 / 208 / 36
Регистрация: 19.02.2021
Сообщений: 1,431
05.11.2021, 01:54
Цитата Сообщение от Verevkin Посмотреть сообщение
А я имел в виду - опрашивать так, как хочется
Когда я задавал вопрос "Зачем таймер?", я имел ввиду именно опрос ком-порта, а не вывод.
Опрашивать устройство по таймеру считалось неэффективным способом (на моей памяти) еще в период DOS с его прерываниями (а скорее всего - и раньше). Для этого в портах и существуют различные Strob'ы и пр.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.11.2021, 01:54

Работа с ком портом
Все еще раз привет. Подскажите как можно поправить код, чтобы вывод был без задержек и слетевших строк в memo. Если в терминале ...

Работа с виртуальным com-портом
Пишу программу, которая передает и принимает данные с устройства через виртуальный com-порт (USB). Проблема следующая - вот фрагмент...

Delphi 10.1 Berlin работа с COM портом
Здравствуйте, друзья! Давненько мне не приходилось работать с Делфи, но жизнь опять заставляет. :scratch: Задача очень проста, нужно...

работа с COM портом
помогите, пожалуйста, наладить правильную работу с COM- портом. У меня есть аналогово-цифровой преобразователь, который преобразует...

Работа с COM Портом
Привет Всем! У меня тут такая проблема. Для работы с одним внешним устройством, которое заведомо неопределенным образом выдает сигналы...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru