|
Вопрос # 5 835/ вопрос решён / |
|
Приветствую, уважаемые эксперты!
Помогите решить проблему: не могу корректно наладить опрос железяки по COM порту в цикле.
Использую компонент BComport.
Для примера: произвожу настройки порта, открываю его, засылаю в модем AT команду 'AT&V' (свою железяку опрашивать буду по другому протоколу).
Если 1 раз послать запрос - то все в порядке, а вот в цикле - не получается. Программа посылает сразу 10 запросов, а надо после первого запроса ждать окончания приема всего пакета (около 400 байтов), а уж потом переходить к следующему запросу. Если в тело цикла вставить метку и переходить по условию на неё через GOTO - программа зацикливается и никакого приёма не происходит вообще.
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
Приложение: Переключить в обычный режим- procedure TForm1.StartCiklClick(Sender: TObject);
- var
- Str: String;
- begin
- Str:='AT&V'+#13;
- for i := 1 to 10 do
- BEGIN
- InitAsync(Operation1);
- try
- BComPort1.WriteAsync(Str[1], Length(Str), Operation1);
- repeat
-
-
- until BComPort1.IsAsyncCompleted(Operation1);
- BComPort1.WaitForAsync(Operation1);
- finally
- DoneAsync(Operation1);
- end;
- END;
- end;
-
- procedure TForm1.BComPort1RxChar(Sender: TObject; Count: Integer);
- var
- n:Integer;
- StrRec:String;
- begin
- InitAsync(Stat);
- try
- BComPort1.ReadStrAsync(StrRec, Count, Stat);
- repeat
-
- until BComPort1.IsAsyncCompleted(Stat);
- N := BComPort1.WaitForAsync(Stat);
- if N <> Count then SetLength(StrRec, Count);
- finally
- DoneAsync(Stat);
- end;
- end;
 |
Вопрос задал: 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 (статус: Посетитель), 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 (статус: Посетитель), 21 декабря 2011, 16:41 [#3]:
Вот именно - я хочу писать команды не подряд - а последовательно. Но я не знаю как мне делать задержку перед отправлением очередной команды. Если я ставлю в теле цикла
repeat until Cont? где Cont- булевая величина, то в этом месте прога клинит - и даже передав в порт команду, например: ATI, уже из неё не возвращается.
|
|
vitalik32 (статус: Посетитель), 21 декабря 2011, 16:48 [#4]:
Вроде бы логично было предположить, что передав в порт пакет и зациклившись в goto процедура BComPort1RxChar отловит входящие байтики и там я этот Cont поменяю в другое состояние, и зцикл продолжится. Но к сожалению до BComPort1RxChar уже не доходит никаких байтов.
|
|
Вадим К (статус: Академик), 21 декабря 2011, 17:01 [#5]:
потому что как только Вы зацикливаете, Вы останавливаете главный поток. И приложение не обрабатывает событий. А поэтому и скорее всего и с порта не может читать.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
vitalik32 (статус: Посетитель), 21 декабря 2011, 19:00 [#6]:
Так как же обойти этот камень?
|
|
Вадим К (статус: Академик), 21 декабря 2011, 19:07 [#7]:
Я же написал выше несколько вариантов решения.
Запомните одну простую истину - если обработчик нажатия кнопки (да и другие) выполняется долго (например, больше пол секунды), то это первый признак того, что дизайн приложения неверный. Прикручивание различных костылей (таких как Application.ProcessMessage() ) только затягивают агонию приложения.
Правильным решением будет либо создания потока (совет 3), который будет всем этим заниматься, либо "статической машинки", которая будет переключать состояния (совет 1). Совет 2 является комбинацией.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
vitalik32 (статус: Посетитель), 22 декабря 2011, 07:57 [#8]:
Спасибо.
Перешел на синхронную передачу- приём.
|
22 декабря 2011, 09:32: Статус вопроса изменён на решённый (изменил автор вопроса — vitalik32): Может и не правильно поступил - но помог Application.ProcessMessage(). Хотя процессор основной поток грузит на 50%....
Спасибо экспертам!
|
vitalik32 (статус: Посетитель), 22 декабря 2011, 09:35 [#9]:
Кстати, поставил перед Application.ProcessMessage() строчку sleep(10)- процессор кушать стал 2% ресурсов!!!
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|