| 
| 
 | Вопрос # 5 835/ вопрос решён / | 
 |  Приветствую, уважаемые эксперты! Помогите решить проблему: не могу корректно наладить опрос железяки по COM порту в цикле.
 Использую компонент BComport.
 Для примера: произвожу настройки порта, открываю его, засылаю в модем AT команду 'AT&V' (свою железяку опрашивать буду по другому протоколу).
 Если 1 раз послать запрос - то все в порядке, а вот в цикле - не получается. Программа посылает сразу 10 запросов, а надо после первого запроса ждать окончания приема всего пакета (около 400 байтов), а уж потом переходить к следующему запросу. Если в тело цикла вставить метку и переходить по условию на неё через GOTO - программа  зацикливается и никакого приёма не происходит вообще.
 К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса) Приложение:Переключить в обычный режим procedure TForm1.StartCiklClick(Sender: TObject);varStr: String;beginStr:='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);varn: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% ресурсов!!!   |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |