Главная » Delphi » Прием и передача в реальном времени

0

В DOS для организации режима реального времени было достаточно просто зациклить процедуру, которая все время определяет, поступил ли байт в приемный регистр UART, и при поступлении немедленно его обрабатывает. Второй вариант— организовать работу по аппаратным прерываниям от СОМ-порта. По прерыванию принятый байт складывается в некий буфер в памяти, сама же прогрвмма при этом мало чем отличается от первого варианта — она так или иначе в цикле должна проверять наличие байтов в буфере.

В Windows же в некотором отношении все даже проще — любая программа и так представляет собой цикл. Причем к прерываниям СОМ-порта вас непосредственно там не пустят2, и остается только работать через указанные ранее функции Windows. Иа практике для организации подобной процедуры лучше всего организовать в программе параллельный процесс, в котором только опрашивать порт и складывать в буфер полученные байты, а в основной программе обрабатывать их, например, по таймеру. Но крупнейший недостаток этого напрашивающегося способа, который, к сожалению, иногда рекомендуют — нам надо все устроить так, чтобы обработка происходила своевременно. Подогнать событие таймера точно под период следования данных нам не удастся даже теоретически, единственный вариант— чтобы оно происходило заведомо чаще, иначе данные попросту будут пропадать. Поэтому такая процедура не является универсальной — она годится, если данные поступают максимум раз в секунду (ну хорошо, несколько раз в секунду). А в общем случае ее удовлетворительной признать нельзя. Теоретически можно обрабатывать данные в самом потоке при возникновении события, но это еще более неправильно: мы для того и организовывали параллельный поток, чтобы максимально разгрузить систему на момент приема данных. И много ли смысла в том, что вся наша программа постепенно "переедет" в этот поток?

Самым правильным и наиболее универсальным решением будет организовать в приемном потоке некое событие, которое посылается главному окну, как только из буфера прочитан очередной символ, и в его обработчике уже производить все нужные манипуляции с данными. Тогда мы можем быть уверены, что данные не потеряются, и что мы неоправданно не перегружаем систему. Хочу заметить, что в зависимости от характера входной последовательности событие это можно средствами Windows организовать самым различным способом — например, если мы знаем, что некую последовательность замыкает символ <cr>, то можно посылать событие при приеме этого символа, остальные байты при этом будут к тому времени уже накоплены в буфере. Но в целях универсальности процедуры мы сделаем все же асинхронный прием каждого байта по мере поступления. В сущности, мы тоша получим прототип "эмулятора терминала" — программы, которая принимает произвольный поток входных данных, отображая их в том или ином виде на экране и/или складывая их в дисковый файл, и одновременно может по командам посылать данные. Модернизация, которой мы должны подвергнуть нашу программу, не так уж сложна: авторы учебников no Delphi сделали, кажется все, чтобы организация параллельных потоков приложения выглядела в глазах пользователей мероприятием, по сложности сравнимым с постройкой Эйфелевой башни. На самом деле никаких специальных модулей типа Thread Object не требуется, надо только помнить, что в организованном попке нельзя обращаться к свойствам визуальных компонентов формы. Куда сложнее с самими коммуникационными функциями. Но обо всем по порядку.

Источник: Ревнч Ю. В.  Нестандартные приемы программирования на Delphi. — СПб.: БХВ-Петербург, 2005. — 560 е.: ил.

По теме:

  • Комментарии