Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 5 835

/ вопрос решён /

Приветствую, уважаемые эксперты!
Помогите решить проблему: не могу корректно наладить опрос железяки по COM порту в цикле.
Использую компонент BComport.
Для примера: произвожу настройки порта, открываю его, засылаю в модем AT команду 'AT&V' (свою железяку опрашивать буду по другому протоколу).
Если 1 раз послать запрос - то все в порядке, а вот в цикле - не получается. Программа посылает сразу 10 запросов, а надо после первого запроса ждать окончания приема всего пакета (около 400 байтов), а уж потом переходить к следующему запросу. Если в тело цикла вставить метку и переходить по условию на неё через GOTO - программа зацикливается и никакого приёма не происходит вообще.

К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)

Приложение:
  1. procedure TForm1.StartCiklClick(Sender: TObject);
  2. var
  3. Str: String;
  4. begin
  5. Str:='AT&V'+#13;
  6. for i := 1 to 10 do
  7. BEGIN
  8. InitAsync(Operation1);
  9. try
  10. BComPort1.WriteAsync(Str[1], Length(Str), Operation1);
  11. repeat
  12.  
  13.  
  14. until BComPort1.IsAsyncCompleted(Operation1);
  15. BComPort1.WaitForAsync(Operation1);
  16. finally
  17. DoneAsync(Operation1);
  18. end;
  19. END;
  20. end;
  21.  
  22. procedure TForm1.BComPort1RxChar(Sender: TObject; Count: Integer);
  23. var
  24. n:Integer;
  25. StrRec:String;
  26. begin
  27. InitAsync(Stat);
  28. try
  29. BComPort1.ReadStrAsync(StrRec, Count, Stat);
  30. repeat
  31.  
  32. until BComPort1.IsAsyncCompleted(Stat);
  33. N := BComPort1.WaitForAsync(Stat);
  34. if N <> Count then SetLength(StrRec, Count);
  35. finally
  36. DoneAsync(Stat);
  37. end;
  38. end;


vitalik32 Вопрос решён, но можно продолжить его обсуждение в мини-форуме

Вопрос задал: vitalik32 (статус: Посетитель)
Вопрос отправлен: 21 декабря 2011, 11:51
Состояние вопроса: решён, ответов: 1.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, vitalik32!
Итак, есть несколько вариантов. Если хочется использовать асинхронные операции, то следующий пакет нужно отправлять по факту получения предыдущего. То есть, в методе StartCiklClick отправляем только один пакет. А в BComPort1RxChar отправлять все последующие. При этом нужно будет завести пару глобальных переменных(или полей класса), которые будут помнить, сколько пакетов было отправлено.
Способ 2. Отправка пакетов происходит в отдельном потоке. Поток, отправив пакет, засыпает (вызывает suspend), а BComPort1RxChar получив пакет, делает потоку resume.
Способ 3. перейти на синхронную отпавку-получение и вставить все это в отдельный поток.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 21 декабря 2011, 13:51


Мини-форум вопроса

Всего сообщений: 9; последнее сообщение — 22 декабря 2011, 09:35; участников в обсуждении: 2.
vitalik32

vitalik32 (статус: Посетитель), 21 декабря 2011, 15:07 [#1]:

Спасибо. Буду пробовать.
Но запрос у меня будет меняться - по протоколу железки. AT&V- привел в качестве примера.
А у меня должно получиться такое - меняется 13-й байт в запросе и соответственно контрольная сумма запроса (2 последних байта):

15 14:41:31 | IRP_MJ_WRITE Serial0 Length 15: ATD89379550207.
15 14:41:31 SUCCESS
19 14:41:54 | IRP_MJ_READ Serial0 Length 3
19 14:41:54 SUCCESS Length 3: 34 39 0D
23 14:41:58 | IRP_MJ_WRITE Serial0 Length 14: FE 01 41 02 00 00 00 00 00 01 0C 1D D4 9D
23 14:41:58 SUCCESS
26 14:41:59 | IRP_MJ_READ Serial0 Length 1
26 14:41:59 SUCCESS Length 1: 41
29 14:41:59 | IRP_MJ_READ Serial0 Length 8
29 14:41:59 SUCCESS Length 8: 01 02 30 00 F1 01 00 00
34 14:41:59 | IRP_MJ_READ Serial0 Length 8
34 14:41:59 SUCCESS Length 8: 00 00 00 00 FA 00 00 00
39 14:41:59 | IRP_MJ_READ Serial0 Length 8
39 14:41:59 SUCCESS Length 8: 00 00 00 00 0B 04 00 00
44 14:41:59 | IRP_MJ_READ Serial0 Length 8
44 14:41:59 SUCCESS Length 8: 00 00 00 00 C6 01 00 00
49 14:41:59 | IRP_MJ_READ Serial0 Length 8
49 14:41:59 SUCCESS Length 8: 00 00 00 00 C6 02 00 00
54 14:41:59 | IRP_MJ_READ Serial0 Length 8
54 14:41:59 SUCCESS Length 8: 00 00 00 00 41 01 00 00
59 14:42:00 | IRP_MJ_READ Serial0 Length 6
59 14:42:00 SUCCESS Length 6: 00 00 00 00 04 B2
65 14:42:01 | IRP_MJ_WRITE Serial0 Length 14: FE 01 41 02 00 00 00 00 00 01 0C 1C 54 98
65 14:42:01 SUCCESS
68 14:42:03 | IRP_MJ_READ Serial0 Length 1
68 14:42:03 SUCCESS Length 1: 41
71 14:42:03 | IRP_MJ_READ Serial0 Length 8
71 14:42:03 SUCCESS Length 8: 01 02 30 00 F8 01 00 00
76 14:42:03 | IRP_MJ_READ Serial0 Length 8
76 14:42:03 SUCCESS Length 8: 00 00 00 00 01 01 00 00
81 14:42:03 | IRP_MJ_READ Serial0 Length 8
81 14:42:03 SUCCESS Length 8: 00 00 00 00 1E 04 00 00
86 14:42:03 | IRP_MJ_READ Serial0 Length 8
86 14:42:03 SUCCESS Length 8: 00 00 00 00 C4 01 00 00
91 14:42:03 | IRP_MJ_READ Serial0 Length 8
91 14:42:03 SUCCESS Length 8: 00 00 00 00 CC 02 00 00
96 14:42:03 | IRP_MJ_READ Serial0 Length 8
96 14:42:03 SUCCESS Length 8: 00 00 00 00 3A 01 00 00
101 14:42:03 | IRP_MJ_READ Serial0 Length 6
101 14:42:03 SUCCESS Length 6: 00 00 00 00 64 82
107 14:42:05 | IRP_MJ_WRITE Serial0 Length 14: FE 01 41 02 00 00 00 00 00 01 0C 1B D4 89
107 14:42:05 SUCCESS
110 14:42:07 | IRP_MJ_READ Serial0 Length 2
110 14:42:07 SUCCESS Length 2: 41 01
115 14:42:07 | IRP_MJ_READ Serial0 Length 8
115 14:42:07 SUCCESS Length 8: 02 30 00 F6 01 00 00 00
120 14:42:07 | IRP_MJ_READ Serial0 Length 8
120 14:42:07 SUCCESS Length 8: 00 00 00 F6 00 00 00 00
125 14:42:07 | IRP_MJ_READ Serial0 Length 8
125 14:42:07 SUCCESS Length 8: 00 00 00 1D 04 00 00 00
130 14:42:07 | IRP_MJ_READ Serial0 Length 8
130 14:42:07 SUCCESS Length 8: 00 00 00 CA 01 00 00 00
135 14:42:07 | IRP_MJ_READ Serial0 Length 8
135 14:42:07 SUCCESS Length 8: 00 00 00 D4 02 00 00 00
140 14:42:07 | IRP_MJ_READ Serial0 Length 8
140 14:42:07 SUCCESS Length 8: 00 00 00 39 01 00 00 00
145 14:42:07 | IRP_MJ_READ Serial0 Length 5
145 14:42:07 SUCCESS Length 5: 00 00 00 08 59


Но на самом деле пока вот так:

15 14:41:31 | IRP_MJ_WRITE Serial0 Length 15: ATD89379550207.
15 14:41:31 SUCCESS
19 14:41:54 | IRP_MJ_READ Serial0 Length 3
19 14:41:54 SUCCESS Length 3: 34 39 0D
15 14:57:35 | IRP_MJ_WRITE Serial0 Length 14: FE 01 41 02 00 00 00 00 00 01 0C 1D D4 9D
15 14:57:35 SUCCESS
16 14:57:35 | IRP_MJ_WRITE Serial0 Length 14: FE 01 41 02 00 00 00 00 00 01 0C 1C 54 98
16 14:57:35 SUCCESS
17 14:57:35 | IRP_MJ_WRITE Serial0 Length 14: FE 01 41 02 00 00 00 00 00 01 0C 1B D4 89
17 14:57:35 SUCCESS
26 14:41:59 | IRP_MJ_READ Serial0 Length 1
26 14:41:59 SUCCESS Length 1: 41
29 14:41:59 | IRP_MJ_READ Serial0 Length 8
29 14:41:59 SUCCESS Length 8: 01 02 30 00 F1 01 00 00
34 14:41:59 | IRP_MJ_READ Serial0 Length 8
34 14:41:59 SUCCESS Length 8: 00 00 00 00 FA 00 00 00
39 14:41:59 | IRP_MJ_READ Serial0 Length 8
39 14:41:59 SUCCESS Length 8: 00 00 00 00 0B 04 00 00
44 14:41:59 | IRP_MJ_READ Serial0 Length 8
44 14:41:59 SUCCESS Length 8: 00 00 00 00 C6 01 00 00
49 14:41:59 | IRP_MJ_READ Serial0 Length 8
49 14:41:59 SUCCESS Length 8: 00 00 00 00 C6 02 00 00
54 14:41:59 | IRP_MJ_READ Serial0 Length 8
54 14:41:59 SUCCESS Length 8: 00 00 00 00 41 01 00 00
59 14:42:00 | IRP_MJ_READ Serial0 Length 6
59 14:42:00 SUCCESS Length 6: 00 00 00 00 04 B2
Вадим К

Вадим К (статус: Академик), 21 декабря 2011, 15:39 [#2]:

Если Вы пишете подряд несколько команд, то нужно знать, как железяка будет отвечать на них. Может у нее нет буфера.
Предлагаю посмотреть на чудную библиотеку http://synapse.ararat.cz/doku.php/download - она хорошо работает с портами в последовательном режиме. В свое время она мне очень помогла.
Галочка "подтверждения прочтения" - вселенское зло.
vitalik32

vitalik32 (статус: Посетитель), 21 декабря 2011, 16:41 [#3]:

Вот именно - я хочу писать команды не подряд - а последовательно. Но я не знаю как мне делать задержку перед отправлением очередной команды. Если я ставлю в теле цикла
repeat until Cont? где Cont- булевая величина, то в этом месте прога клинит - и даже передав в порт команду, например: ATI, уже из неё не возвращается.
vitalik32

vitalik32 (статус: Посетитель), 21 декабря 2011, 16:48 [#4]:

Вроде бы логично было предположить, что передав в порт пакет и зациклившись в goto процедура BComPort1RxChar отловит входящие байтики и там я этот Cont поменяю в другое состояние, и зцикл продолжится. Но к сожалению до BComPort1RxChar уже не доходит никаких байтов. :-(
Вадим К

Вадим К (статус: Академик), 21 декабря 2011, 17:01 [#5]:

потому что как только Вы зацикливаете, Вы останавливаете главный поток. И приложение не обрабатывает событий. А поэтому и скорее всего и с порта не может читать.
Галочка "подтверждения прочтения" - вселенское зло.
vitalik32

vitalik32 (статус: Посетитель), 21 декабря 2011, 19:00 [#6]:

Так как же обойти этот камень?
Вадим К

Вадим К (статус: Академик), 21 декабря 2011, 19:07 [#7]:

Я же написал выше несколько вариантов решения.
Запомните одну простую истину - если обработчик нажатия кнопки (да и другие) выполняется долго (например, больше пол секунды), то это первый признак того, что дизайн приложения неверный. Прикручивание различных костылей (таких как Application.ProcessMessage() ) только затягивают агонию приложения.
Правильным решением будет либо создания потока (совет 3), который будет всем этим заниматься, либо "статической машинки", которая будет переключать состояния (совет 1). Совет 2 является комбинацией.
Галочка "подтверждения прочтения" - вселенское зло.
vitalik32

vitalik32 (статус: Посетитель), 22 декабря 2011, 07:57 [#8]:

Спасибо.
Перешел на синхронную передачу- приём.

22 декабря 2011, 09:32: Статус вопроса изменён на решённый (изменил автор вопроса — vitalik32): Может и не правильно поступил - но помог Application.ProcessMessage(). Хотя процессор основной поток грузит на 50%....
Спасибо экспертам!

vitalik32

vitalik32 (статус: Посетитель), 22 декабря 2011, 09:35 [#9]:

Кстати, поставил перед Application.ProcessMessage() строчку sleep(10)- процессор кушать стал 2% ресурсов!!! :-)

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:37
Выполнено за 0.02 сек.