Радиоэлектроника начинающим и не только!
Уроки начинающим.
НОВОСТИ
Главная
Введение
Урок-1
Урок-2
Урок-3
Урок-4
Урок-5
Урок-6
Урок-7
Урок-8
Урок-9
Урок-10
Уроки по темам.
Транзисторные УНЧ
Ламповые УНЧ-УМ
Мультивибратор
Схемы начинающим
Библиотека начинающего радиолюбителя
Начинающим
Радио КВ - УКВ
Справочники по радиоэлементам.
Диоды
Стабилитроны

Маркировка

Резисторы-Конденсаторы
Диоды
Стабилитроны
Транзисторы
Измерение параметров электрических цепей.
Измерение напряжения
Проверка транзистора
Радиолюбительские технологии.
Основы пайки
Изготов. печатных плат
Связь КВ-УКВ.
Азбука коротких волн
Приемник прямого усил.
КВ-приемник начинающим
Микроконтроллеры начинающим.
Светодиодное информ. табло на PIC контроллере
Программатор “ICProg 105”
Осваиваем LPT порт
Программирование LPT под DOS
Программирование LPT под Windows
Программирование LPT под WinNT
Вспомогательные радиолюбительские программы.
Вспомогательные программы
Радиолюбительский калькулятор
Онлайн расчет антенн
Рассчет КФ
Мастерская радиолюбителя.
Лабораторный БП
Консультации-предложения.
Форум
Связь с автором

Программирование LPT порта в Delphi, под Win9x, WinXP на основе драйвера LPTWDMIO

Нужно конечно согласится с тем, что программирование под ДОС, на языке Паскаль, достаточно не сложно и удобно, но время движется в перед и нужно осваивать новые подходы и методы в программировании. Интерфейсы написанные на языке высокого уровня, коим является Delphi, намного дружелюбнее и наглядней. В этой части статьи, я постараюсь подробней описать основные методы программирования LPT порта под WinXP. Сложного здесь ничего нет, тем более, если вы знакомы со средой программирования Delphi

Начиная с Delphi 2.0, в языке Object Pascal отсутствуют массивы Port и PortW, которые мы применяли ранее, программируя на Паскале. Предпринималось множество попыток обойти эту проблему, но большинство из них сводилось к тривиальным ассемблерным вставкам и использованию команд in и out. Это являлось достаточно эффективным решением при программировании для платформы Windows 9x, но не работало под управлением WinNT, так как там требовалось писать драйвер уровня ядра для получения возможности доступа к портам. Большинство нуждавшихся в доступе к портам ввода/вывода, испытывали необходимость обращаться к стандартным портам RS232 (Com) или IEEE 1284 (LPT). Найдя стандартные функции Win API, эти люди успокаивались и забывали о массиве Port, но те, кому требовалось работать с нестандартными устройствами, продолжали ломать свою голову об защиту WinNT, ибо писать драйвер не хотелось, да и мало кто умел. Но нашёлся добрый человек, который написал библиотеку функций для работы с портами процессора, и имя ему Фред Булбак (Fred Bulback). Библиотека называется io.dll. Я конечно не буду приводить исходный код данной библиотеки и вдаваться в тонкости проблемы программирования под NT системы (коей является и WinXP), кто захочет глубже разобраться, по ссылке все есть. Для нас важно то, что данная библиотека существует и благодаря ей, мы имеем возможность работать с LPT портом под WinXP. Эта библиотека содержит все необходимые для работы функции.

Все выше сказанное о данной библиотеке, я привел как пример того, что существует вариант работать в Delphi c LPT портом. Покопавшись в дебрях интернета, я увидел, что существует не только этот вариант, есть и другие варианты, которые использовал я в своих разработках и которые для новичка, на мой взгляд, будут намного проще для понимания и использования. Эти варианты мы сейчас и рассмотрим.

Существует проект LptWdmIo - некоммерческий проект программного обеспечения (ПО), ставящий целью, создание простого и надёжного компонента, для работы с параллельными портами IBM-совместимых персональных компьютеров, работающих под управлением ОС Windows. ПО, созданное в рамках проекта распространяется свободно (и бесплатно). Вы можете копировать, распространять и модифицировать ПО по своему усмотрению. Разрешается использование исходников для своих разработок, в т.ч. коммерческих. Этот проект, включает в себя специальный драйвер LPTWDMIO.sys, который предоставляет пользовательским приложениям, возможность управлять параллельными портами ПК. Обращение к драйверу из пользовательских приложений осуществляется через функцию DeviceIoControl( ). Он поддерживает два вида операций - чтение из порта и записи в порт. За одно обращение к драйверу возможны несколько (от одной и более) акций вывода (ввода) данных в (из) регистров порта. Это позволяет легко реализовывать сложные протоколы управления внешними устройствами.

Платформы Windows, на которых работает драйвер:

Windows 98

Проверено

Windows Me

Проверено

Windows NT4

НЕ проверено, но противопоказаний нет

Windows 2000 Prof.

Проверено

Windows XP Home Edition

Проверено

На ОС Windows 2000 Server и Windows XP Prof. драйвер не проверялся. Но противопоказаний к использованию нет. Как видите, драйвер поддерживается практически всеми пользовательскими операционными системами, что нам и нужно.
Итак, для того чтобы наши программы работали нужно скачать и установить данный драйвер в системе, а так же обзавестись средой визуального программирования, Borland Delphi 5.0 - 7.0. Как устанавливается драйвер, читайте далее.

Существует два варианта установки:

  1. Установка драйвера вручную.
  2. Автоматическая установка.

Установка драйвера вручную.

Установка вручную практикуется при использовании LPTWDMIO на ОС Windows 98/Me. В этом случае надо запустить Мастер установки оборудования и указать ему путь к .inf файлу в подкаталоге Driver, который находится в скаченном архиве. Там же должен находиться файл lptwdmio.sys. После установки потребуется перезагрузка компьютера. При желании удалить драйвер, можно через Диспетчер устройств (значок Система в панели управления). После удаления также может потребоваться перезагрузка.

При работе на ОС Windows 2000/XP также возможна установка вручную аналогичным способом. Но в отличие от Windows 98/Me при установке перезагрузка точно не потребуется, драйвер стартует сразу. Кроме того у ручной инсталляции есть одно преимущество: если клиентская программа была запущена от имени пользователя, не обладающего правами администратора, она всё равно сможет работать с портами через драйвер.

Автоматическая установка.

Автоматическая установка выполняется при создании объекта для работы с драйвером (см. след. пункт) в программе пользователя в том случае, если программа работает на платформе семейства NT - т.е. Windows NT4/2000/XP и драйвер не был ранее установлен вручную. При этом со стороны пользователя не требуется каких-либо дополнительных действий. Но если программа стартует от имени пользователя, не обладающего административными полномочиями, автоматическая установка не произойдёт, и программа пользователя не сможет управлять портами.

Мы подошли к самому интересному, непосредственно к программированию, через драйвер, при написании программ на Delphi.

Скачайте архив LPTWDMIO.rar, в котором находятся исходные тексты тестовой программы на Delphi и продолжим. Сразу сделаю оговорку: - дальнейшее описание модулей и исходников, для непосвященных новичков, будет конечно трудно осмыслить, посему не заостряйте на этом внимание, нам важно понять, как пишется непосредственно, сама программа с использованием готового модуля LPTIO.pas.Вот на практическом моменте написания программы и стоит сконцентрировать максимум внимания. Первым делом изучим содержимое архива:

В архиве LPTWDMIO.rar, находится три папки, Bonus, Delphi, Driver. О папке Bonus, будет сказано в конце статьи, в папке Delphi, находится базовый исходник - пример от разработчика и модуль LPTIO.pas, в папке Driver, находится сам драйвер который необходимо установить.

Чтобы облегчить программистам использование драйвера, был написан модуль LPTIO.pas. В этом модуле определён класс TLptPortConnection. Для того, чтобы работать с портами, пользовательская программа должна создать объект данного класса. Объект сам связывается с драйвером и пользователю остаётся только проверить результат - готов объект или нет:

// <...>
type
TForm1 = class(TForm) // Класс для пользовательской формы
// <...>
procedure FormCreate(Sender: TObject); // Обработчик создания формы
procedure FormDestroy(Sender: TObject); // Обработчик разрушения
Lpt : TLptPortConnection; // Указатель на объект для работы с портами
end; // class
// <...>
// Обработчик создания формы
procedure TForm1.FormCreate(Sender: TObject);
var msg : AnsiString;
begin
Lpt := TLptPortConnection.Create;
if not Lpt.Ready then
begin {объект не готов -- покажем код ошибки}
msg := 'Ошибка при создании объекта Lpt, код = ' + IntToStr(GetLastError());
Application.MessageBox(PChar(msg),'ERROR',MB_OK);
Application.Terminate;
end;
end;
// Обработчик разрушения формы
procedure TForm1.FormDestroy(Sender: TObject);
begin
Lpt.Destroy;
end;
// <...>

Объект класса TLptPortConnection предоставляет в распоряжение пользователя ряд функций, большая часть которых описана в следующих пунктах.

function Ready : boolean;

Возвращает признак готовности (true) или неготовности (false)

function IsNtPlatform : boolean;

Функцияя возвращает true, если работаем на платформе NT. Иначе -- false.

function IsPortPresent(LptNumber : byte) : boolean;

Ф-я тестирования наличия порта. Возвратит true, если порт присутствует

function IsPortBidirectional(LptNumber : byte) : boolean;

Ф-я тестирования порта на двунаправленность. Если порт двунаправленный, возвратит true.

Если ф-я Ready( ) сразу после создания объекта возвращает false, это значит, что объект не смог связаться с драйвером. При работе под ОС Windows 98/Me такой ситуации не возникает, т.к. если драйвер не установлен, объект класса TLptConnection будет использовать прямые обращения к регистрам портов. При работе под ОС семейства NT, это как правило означает неудачу при попытке старта сервиса - не найден драйвер (должен быть размещён в каталоге программы) или нет административных полномочий. И ещё одно замечание - не создавайте несколько экземпляров объекта типа TLptPortConnection в одном приложении. Это совершенно не нужно.

Нумерация портов и регистров

Обращения к регистрам портов производятся по их логическим номерам. Номер составляется из маски порта и маски регистра. Логический номер имеет размер 1 байт. В модуле LPTIO.pas определены следующие константы:

{ Номера портов LPT }
LPT1 : byte = $10; // база $3BC
LPT2 : byte = $20; // $378
LPT3 : byte = $30; // $278
{Смещения регистров порта}
LPT_DATA_REG : byte = 0; // Регистр данных
LPT_STATE_REG : byte = 1; // Регистр состояния
LPT_CONTROL_REG : byte = 2; // Регистр управления
LPT_EPP_ADDRESS : byte = 3; // Регистр адреса EPP
LPT_EPP_DATA : byte = 4; // Регистр данных EPP

Например, логический номер регистра управления порта LPT2:

(LPT2 or LPT_CONTOL_REG)

при этом обращение будет выполняться по адресу $378+2 = $37A.

Нумерация отдельных бит регистров

Побитная раскладка регистров порта LPT определена в виде двух наборов констант - для регистров управления и для регистров состояния:

{ Битовые расклады регистров / разъём 25 pin / разъём Centronic }
{ Битовый расклад регистра УПРАВЛЕНИЯ }
STROBE : byte = $01; { Строб, 1 /1 }
AUTOFEED : byte = $02; { Автопротяжка, 14/14 }
INIT : byte = $04; { Инициализация, 16/31 }
SELECTIN : byte = $08; { Выбор принтера, 17/36 }
IRQE : byte = $10; { Прерывание, ------ }
DIRECTION : byte = $20; { Направление ШД, ------ }
{ Битовый расклад регистра СОСТОЯНИЯ }
IRQS : byte = $04; { Флаг прерывания,------ }
ERROR : byte = $08; { Признак ошибки, 15/32 }
SELECT : byte = $10; { Признак выбора, 13/13 }
PAPEREND : byte = $20; { Конец бумаги, 12/12 }
ACK : byte = $40; { Готовность к приёму данных, 10/10}
BUSY : byte = $80; { Занятость, 11/11 }

Эти значения могут быть использованы, например для управления состоянием отдельных линий. Например, вот так можно установить бит INIT в регистре управления порта LPT1:
Lpt.WritePort(LPT1,LPT_CONTROL_REG, (INIT or Lpt.ReadPort(LPT1,LPT_CONTROL_REG)) )

Функции для вывода данных

Этих ф-ций две: WritePorts( ) и WritePort( ). WritePorts( ), предназначена для вывода пакета данных (множество значений). Определена следующим образом:

function WritePorts(PairArray : PADRDATASTRUCT; PairCount : cardinal) : boolean;
PairArray должен указывать на массив структур типа ADRDATASTRUCT:
{Структура Адрес-Данные}
ADRDATASTRUCT = record
Adr : byte; {адрес == <Номер порта> or <Смещение регистра>}
Data : byte; {данные для вывода или место для прочитанного байта}
end;

Массив передаётся в драйвер полностью, цикл по структурам происходит внутри самого драйвера. Для каждой структуры выполняется вывод данных в регистр порта. Это позволяет выдавать данные в порты с максимальной скоростью, причём акт выдачи такого блока данных не может быть прерван до его завершения другими пользовательскими приложениями, что весьма удобно для реализации протоколов передачи, критичных ко времени. Параметр PairCount -- должен содержать количество структур в массиве PairArray. WritePort( ) предназначена для вывода одиночного байта в указанный порт:
procedure WritePort (LptNumber : byte; RegOffset : byte; Value : byte);
Здесь LptNumber - одна из констант LPT1..LPT3, определяет номер порта,
RegOffset -- одна из констант LPT_DATA_REG, LPT_STATE_REG, LPT_CONROL_REG, определяет номер регистра порта. Value -- значение, которое будет выведено в указанный регистр.

Функции для ввода данных

Для ввода данных предназначены функции ReadPorts( ) и ReadPort( ). function ReadPorts (PairArray : PADRDATASTRUCT; PairCount : cardinal) : boolean;
Параметры задаются аналогично WritePorts( ), отличие в том, что при выполнении этой процедуры в поля Data каждой структуры ADRDATASTRUCT будут записаны значения, прочитанные из регистров портов, номера которых (<порт> or <регистр>) были указаны в полях Adr.

Функция возвращает false, если объект TLptConnection не готов к работе или если произошла ошибка в драйвере.
function ReadPort (LptNumber : byte; RegOffset : byte) : byte;
Параметры задаются аналогично WritePort( ). Возвращаемое значение - результат чтения регистра порта.

Автозагрузка драйвера

Автозагрузка драйвера выполняется объектом типа TLptConnection при работе на NT-платформах Windows в том случае, если драйвер не был установлен вручную. Однако, для успешного старта драйвера необходимо, чтобы программа запускалась от имени пользователя, обладающего административными полномочиями.

А теперь давайте отвлечемся, от сложных теоретических повествований и попробуем написать пару простейших программ, к примеру, помигаем диодом и заставим нашу программу как то реагировать на внешнее событие (замыкание одного из тумблеров, нашей схемки см. рис. ниже).

Демонстрационная схема, для работы с LPT портом

Подключив данную схемку к LPT порту, из распакованного архива, в папке Bonus (о которой я говорил выше), запустите на выполнение файл Project1.exe. Эта программка написанна мной, специально для демонстрации практически всех возможностей программирования LPT порта с помощью LPTWDMIO метода. Попробуйте, поиграйтесь элементами управления, измените некоторые участки программного кода относящиеся непосредственно к выводу и чтению информации с порта. Таким образом, вы досконально разберетесь, как работает данная система.

Как видите, кто знаком с азами программирования на Delphi, все достаточно просто. Благодаря замечательному проекту LPTWDMIO, программисты получили возможность работать с LPT портом, не вдаваясь в API функции Windows и прочие извороты. В папке Delphi, архива LPTWDMIO.rar, как выше было сказано, лежит исходник программы test.exe, от разработчика проекта, его так же необходимо внимательно изучить. В представленных исходниках программ Test и Project1, много полезного, тем более исходный текст снабжен подробными комментариями, как говорят в стиле лучших традиций программирования. Программа Project1 в папке Bonus, написана для новичков, с подробными комментариями и в принципе представляет собой готовый исходник, для реализации программ любой сложности.

Вверх | Главная | Далее..



Hosted by uCoz