Другая жизнь lpt порта (часть 2)

Параллельный интерфейс: LPT-порт (стр. 2 из 6)

Процедура вывода байта по интерфейсу Centronics через стандартный порт включает следующие шаги (в скобках приведено требуемое количество шинных операций процессора):

Вывод байта в регистр данных (1 цикл IOWR#).

Ввод из регистра состояния и проверка готовности устройства (бит SR.7 — сигнал BUSY).

По получении готовности выводом в регистр управления устанавливается строб данных, а следующим выводом строб снимается (2 цикла lOWRff).

Стандартный порт сильно асимметричен — при наличии 12 линий (и бит), нормально работающих на вывод, на ввод работает только 5 линий состояния.

Если необходима симметричная двунаправленная связь, на всех стандартных портах работоспособен режим полубайтного обмена — Nibble Mode.

В этом режи­ме, называемым также и Hewlett Packard Bitronics, одновременно передаются 4 бита данных, пятая линия используется для квитирования.

Функции BIOS для LPT-порта

BIOS обеспечивает поддержку LPT-порта, необходимую для организации вы­вода по интерфейсу Centronics.

В процессе начального тестирования POST BIOS проверяет наличие парал­лельных портов по адресам ЗВСЬ, 378h и 278h и помещает базовые адреса обнаруженных портов в ячейки BIOS DATA AREA 0:0408h, 040Ah, 040СП, 040ЕП. Эти ячейки хранят адреса портов с логическими именами LPT1-LPT4. В ячейки 0:0478, 0479, 047А, 047В заносятся константы, задающие выдержку тайм-аута для этих портов.

Поиск портов обычно ведется по базовому адресу. Если считанный байт совпал с записанным, считается, что найден LPT-порт, и его адрес помещают в ячейку BIOS DATA AREA. Адрес порта LPT4 BIOS самостоятельно установить не может, поскольку в списке стандартных адресов поиска имеются только три вышеука­занных.

Обнаруженные порты инициализируются — записью в регистр управления формируется и снимается сигнал Initff, после чего записывается значение 00h, соответствующее исходному состоянию сигналов интерфейса.

Программное прерывание BIOS I NT 17h обеспечивает следующие функции поддержки LPT-порта:

00h — вывод символа из регистра AL по протоколу Centronics. Данные помещаются в выходной регистр и после готовности принтера формируется строб.

01h — инициализаия интерфейса и принтера.

02h — опрос состояния принтера.

При вызове INT 17h номер функции задается в регистре АН, номер порта — в регистре DX (0 — LPT1, 1 — LPT2…). При возврате после любой функции регистр АН содержит код состояния — биты регистра состояния SR[7:3] (биты 6 и 3 инвертированы) и флаг тайм-аута в бите 0. Флаг тайм-аута устанавливается при неудачной попытке вывода символа.

Расширения параллельного порта

Недостатки стандартного порта частично устраняют новые типы портов, поя­вившихся в компьютерах семейства PS/2.

Двунаправленный порт 1 (Typel parallel port) — интерфейс, введенный с PS/2. Такой порт кроме стандартного режима может работать в режиме ввода или двунаправленном. Протокол обмена формируется программно, а для указания направления передачи в регистр управления порта введен специальный бит: при CR.5=0 буфер данных работает на вывод, при CR.5=1 — на ввод.

Порт с прямым доступом к памяти (Type 3 DMA parallel port) применялся в PS/2 моделей 57, 90, 95. Этот тип был введен для повышения пропускной способности и разгрузки процессора при выводе на принтер. Программе, рабо­тающей с данным портом, требовалось только задать блок данных в памяти, подлежащих выводу, и вывод по протоколу Centronics производился без участия процессора.

Физический и электрический интерфейс

Стандарт IEEE 1284 определяет физические характеристики приемников и пе­редатчиков сигналов.

К передатчикам предъявляются следующие требования:

Уровни сигналов без нагрузки не должны выходить за пределы -0,5… +5,5 В.

Уровни сигналов при токе нагрузки 14 мА должны быть не ниже +2,4 В для высокого уровня (voh) и не выше +0,4 В для низкого уровня (vol) на постоянном токе.

Выходной импеданс ro, измеренный на разъеме, должен составлять 50(±)5 Ом на уровне voh-vol. Для обеспечения заданного импеданса в некоторых случаях используют последовательные резисторы в выходных цепях передатчика. Согласование импеданса передатчика и кабеля снижа­ет уровень импульсных помех.

Скорость нарастания (спада) импульса должна находиться в пределах 0,05-0,4 В/нс.

Требования к приемникам:

Допустимые пиковые значения сигналов -2,0…+7,0.

Пороги срабатывания должны быть не выше 2,0 В (vih) для высокого уровня и не ниже 0,8 В (vil) для низкого.

Приемник должен иметь гистерезис в пределах 0,2-1,2 В.

Входной ток микросхемы не должен превы­шать 20 мкА.

Входная емкость не должна превышать 50 пФ.

Стандарт IEEE 1284 определяет три типа используемых разъемов. Типы Л (DB-25) и В (Centronics-36) используются в традиционных кабелях подклю­чения принтера, тип С — новый малогабаритный 36-контактный разъем.

Интерфейсные кабели, традиционно используемые для подключения принте­ров, обычно имеют от 18 до 25 проводников, в зависимости от числа провод­ников цепи GND.

Стандарт IEEE 1284 регламентирует и свойства кабелей:

Все сигнальные линии должны быть перевитыми с отдельными обратны­ми (общими) проводами.

Каждая пара должна иметь импеданс 62(±)6 Ом в частотном диапазоне 4-16 МГц.

Уровень перекрестных помех между парами не должен превышать 10%.

Кабель должен иметь экран (фольгу), покрывающий не менее 85% внеш­ней поверхности. На концах кабеля экран должен быть окольцован и со­единен с контактом разъема.

Кабели, удовлетворяющие этим требованиям, маркируются надписью IЕЕЕ Std 1284-1994 Compliant». Они могут иметь длину до 10 метров.

Режимы передачи данных

Стандарт IEEE 1284 определяет пять режимов обмена, один из которых пол­ностью соответствует традиционному стандартному программно-управляемому выводу по протоколу Centronics.

Остальные режимы используются для расшире­ния функциональных возможностей и повышения производительности интерфей­са.

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

Режимы нестандартных портов, реализующих протокол обмена Centronics аппаратно («Fast Centronics, «Parallel Port FIFO Mode»), могут и не являться режимами IEE1284, несмотря на наличие в них черт ЕРР и ЕСР.

При описании режимов обмена фигурируют следующие понятия:

Хост — компьютер, обладающий параллельным портом.

ПУ — периферийное устройство, подключаемое к этому порту (им может оказаться и другой компьютер). обозначениях сигналов Ptr обозначает передающее периферийное устройство.

Прямой канал — канал вывода данных от хоста в ПУ.

Обратный канал канал ввода данных в хост из ПУ.

Полубайтный режим ввода — Nibble Mode

Режим полубайтного обмена является наиболее общим решением задачи дву­направленного обмена данными, поскольку может работать на всех стандартных (традиционных) портах. Все эти порты имеют 5 линий ввода состояния, исполь­зуя которые периферийное устройство может посылать в PC байт тетрадами (nibble — полубайт, 4 бита) за два приема. Назначение сигналов порта приведено в табл 4.

Таблица 4.

Сигналы LPT-порта в полубайтном режиме ввода

Прием байта данных в полубайтном режиме состоит из следующих фаз:

1. Хост сигнализирует о готовности приема данных установкой низкого уров­ня на линии HostBusy.

2. ПУ в ответ помещает тетраду на входные линии состояния.

3. ПУ сигнализирует о действительности тетрады установкой низкого уровня на линии PtrClk.

4. Хост устанавливает высокий уровень на линии HostBusy, указывая на заня­тость приемом и обработкой тетрады.

5. ПУ отвечает установкой высокого уровня на линии PtrCLk.

6. Шаги 1-5 повторяются для второй тетрады.

Полубайтный режим работает на всех портах со скоростью обмена не выше 50 Кбайт/с . Его применяют в тех случаях, когда прием данных от устройства производится в небольших объемах (например, для связи с принтерами).

Двунаправленный байтный режим Byte Mode

Данный режим обеспечивает прием данных с использованием двунаправленного порта, у которого выходной буфер данных может отключаться установкой бита CR.5=1. Как и в стандартном и в полубайтном режиме, данный режим является программно-управляемым — все сигналы квитирования анализируются и уста­навливаются программным драйвером. Назначение сигналов порта приведено в табл. 5.

Таблица 5.

Сигналы LPT-порта в байтном режиме ввода/вывода

Прием байта данных в байтном режиме состоит из следующих фаз:

Источник: http://MirZnanii.com/a/111464-2/parallelnyy-interfeys-lpt-port-2

Драйвер для работы с LPT портом (интегрированным или в виде платы PCI)

Лет 10-15 назад параллельный порт был довольно востребованным интерфейсом для связи между устройствами. Сегодня производители различных устройств отдают предпочтение последовательным интерфейсам. Тем не менее, и сегодня LPT порт всё ещё можно встретить.

А некоторые разработчики ещё пишут под него программы (или поддерживают написанные во времена расцвета параллельных интерфейсов). Но в компьютерах сейчас LPT порт – достаточно большая редкость. Существуют, конечно, платы расширения для компьютера, которые реализуют интерфейс LPT. Они в основном представляют собой платы на шине PCI.

К сожалению, далеко не весь софт, который был написан для интегрированных в материнскую плату LPT портов, будет работать с LPT-PCI-платами.

Предлагается решение этой проблемы: программный класс, написанный под .NET, и динамическую библиотеку, которая работает с LPT. Данная реализация проверена на 32- и 64-разрядных Windows XP, Windows 7, 8 и 10 как со встроенными LPT портами, так и реализованными в виде плат расширения на шине PCI или PCI-Express. Скачать драйвер для LPT порта можно по ссылке внизу после статьи.

В приложенном архиве находятся две папки – для 32-разрядной и для 64-разрядной версий Windows. В одной из папок лежит файл InstallDriver.exe. Сначала запустите этот файл, он установит динамические библиотеки в систему. После этого компьютер следует перезагрузить.

Чтобы использовать предлагаемый драйвер, файлы inpout32.dll и inpoutx64.dll должны располагаться в одной директории с исполняемым файлом вашей программы.

2Программный класс использования библиотек работы с LPT портом

Мной был написан класс для .NET, который использует динамические библиотеки inpout32.dll и inpoutx64.dll и позволяет считывать из параллельного порта и записывать в его регистры данные.

Упомянутые библиотеки написаны не мной. Я предлагаю удобный класс-оболочку, упрощающий работу с данными библиотеками. Кроме того, автор библиотек в файле readme.txt сообщает, что его драйвер не поддерживает PCI устройства.

Мне удалось его запустить для работы как с интегрированным параллельным портом, так и LPT портом, реализованном в виде платы расширения на шине PCI-Express.

Причём порт отлично работает и на современной Windows10 x64, и на более старых системах.

Вот код класса LPT на языке VB.NET:

Код класса LPT на языке C#:

3Применение класса .NET для работы с LPT портом

Если мы посмотрим на список экспортируемых функций библиотеки inpout32.dll с помощью замечательного инструмента DLL Export Viewer от NirSoft, то увидим следующую картину:

Список экспортируемых функций библиотеки inpout32.dll

Это список функций, которые мы можем использовать. Фактически все они используются в классе LPT, но реализация скрыта, и из публичных методов пользователю доступны только два метода и одно свойство (они рассматриваются чуть далее).

При инстанцировании класс сам определит, библиотеку какой разрядности ему использовать – inpout32.dll или inpoutx64.dll. Поэтому от пользователя не требуется никаких действий по инициализации или определения разрядности используемой dll.

Вы можете сразу записывать или читать из LPT порта.

Одно «Но»: если драйвер не установлен, обращение к любому из методов динамической библиотеки вызовет исключение, поэтому рекомендую использовать блоки Try…Catch для перехвата и обработки исключений.

Несколько примеров использования класса LPT.

Для определения, используется ли 64-разрядная версия драйвера (inpoutx64.dll при True) или 32-разрядная (inpout32.dll при False) (на самом деле, это знать не обязательно, класс использует именно ту библиотеку, которая нужна, но вдруг вам для чего-то понадобится это узнать из своей программы):

bool is64bitDriver = LPT.IsX64DriverUsed;

Для записи числа “123” в регистр контроля LPT порта вызовите из своего класса:

LPT.Write(currentPort, LPT.Register.CONTROL, 123);

Для чтения одного байта из регистра данных LPT порта и чтения регистра статуса:

byte b = LPT.Read(currentPort, LPT.Register.DATA); byte s = LPT.Read(currentPort, LPT.Register.STATUS);

Здесь currentPort – адрес LPT порта. Причём, если у вас интегрированный LPT порт, то его адрес будет, скорее всего, 378h. А если у вас LPT порт на плате расширения, то адрес будет другой, например, D100h или C100h.

Чтобы узнать адрес LPT порта, зайдите в диспетчер устройств Windows, найдите раздел Порты COM и LPT, выберите используемый параллельный порт, и в окне свойств (щёлкнув по нему правой кнопкой мыши) посмотрите, какие ресурсы использует выбранный порт.

Ресурсы, используемые LPT портом, в диспетчере устройств Windows

  • Скачать драйвер для LPT порта (1560 Скачиваний)

Источник: https://soltau.ru/index.php/themes/dev/item/452-drajver-dlya-raboty-s-lpt-portom-integrirovannym-i-vide-platy-pci

Примеры схем для LPT порта

ПодробностиКатегория: Компьютер

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

выводы на схеме от 18 до 25 можно не замыкать между собой;

резисторы по 470 Ом можно подключить к любому из них.

Резисторы в схеме служат для ограничения потребляемого тока. Напряжение между сигнальным выводом LPT и общем проводом должен быть в не более  2,4V. Ток  – около 2.6 mA. Т.е. очень мало, но на самом деле современные материнские платы расчитаны на большую нагрузку и очень часто имеют защиту от короткого замыкания.

В любом случае, с портом нужно обращаться очень аккуратно, т.к. без него материнская плата компьютера может вообще отказаться работать.

Вот самая простая схема подключения реле:
Думаю, что объяснять здесь ничего не нужно. Data – это один из выходов LPT порта, например, вывод 2 (Data-0).

Если на нем появится log1, транзистор откроется, сработает реле K1 и подключит какую-то более мощную нагрузку..

В этой схеме LPT порт напрямую подключен к транзистору и в случае его пробоя на выходе data может оказаться опасное для порта напряжение. Чтобы защитить порт нужно использовать гальваническую развязку.

Схема с применением оптопары.

В данной схеме порт отделен от высоковольтной части и ему почти ничего не угрожает. В этой схеме я ставил опто изолятор 4N25 – самый дешевый и маленький. Катушка на схеме – это реле на 12 вольт. Во время экспериментов я подключил к этой схеме реле РЭС22, а к нему настольную лампу. Для пробы написал программку, которая управляла лампой по часам…

Есть спец. микросхемы работы с LPT портом. Они обеспечивают гальваническую развязку, инвертируют выходной сигнал и тд. Мне известна пока только две 74HCT573 и 74ALS373

Это схема подключения 74ALS373. Как она работает я не знаю, я не использовал микросхемы вообще, обходился просто связкой оптопара+транзистор или оптопара+симистор.

Кстати, вот примерчик управления симистором:

Эту схемку я просто воткнул вместо выключателя от основного освещения в своей комнате. Очень пригодилось когда настраивал LPT-стробоскоп. Можно было не вставая с места выключить на время свет. 

Ещё один пример практического использования LPT порта, наверно самый удачный.

Это стробоскоп управляемый через LPT интерфейс.

В предыдущей статье я обещал рассказать о чтении информации с LPT порта и привести несколько схем датчиков. Пока просто расскажу о программировании и о подключении кнопочек, а дальше по ситуации.

Схема подключения кнопок и переключателей оказалась такойже простой как и схема подключения светодиодов: 

Для ввода информации я использовал 5 стандартных входов – выводы 10, 11, 12, 13 и 15. Первоначальное состояние выводов – log1, т.е. на них напряжение 5V. Мой тестер сказал, что там не 5, а 4.

7V, может тестер не точно показывает, может блок питания в компе слабоват, а может так и надо – не важно. Следовательно, замкнув вывод порта на землю (выводы 18-25), мы переведем его в состояние Log0. Замыкать вывод прямо на землю я не рискнул и соединил его с землей через резистор в 470 ом.

Можно обойтись и без резистора – всё отлично работает, но лучше не рисковать. Для дальнейших экспериментов я собрал себе панельку из 5 кнопочек по приведенной выше схеме и достал с архивного диска компилятор Turbo Pascal 7.1 (то же что и Pascal 7.0). Тем, кто не умеет работать с портами, советую прочитать предыдущую статью “Основы программирования LPT”, тк.

сейчас я уже не буду подробно описывать как и почему.Как я уже говорил, считать значение на выходах порта можно одной строчкой: data := port[$378], где $378 – базовый адрес порта. Это выходы, ими управлять мы уже умеем. А входы нахотятся по адресу “базовый+1”, те.

$379 пробуем считать:Var data:byte; {переменная DATA типа byte} data := Port[$379]; {читаем значение порта в data} writeln(data); {выводим значение на экран}

В результате на экране останется число 120 (у меня так :)). Нажимаем одну из кнопок, запускаем программу ещё раз – число изменилось. Чтобы не мучиться с запуском программы и её закрытием, а просто жать на кнопки и смотреть, я немного доработал программу:

while not keypressed do {пока не нажата кнопка на клавиатуре…} begin {повторяем код от сюда…..} data := port[$379]; {читаем значение порта в data} gotoxy(1,1); {ставим курсор в позицию 1,1 на экране} write(' '); {пишем пробелы чтобы замазать текст} gotoxy(1,1); {возвращаем курсор назад в позицию 1,1} write(data); {выводим значение на экран} delay(100); {задержка в 100мс.(не точно!)}

Для тех кто работает в Delphi, маленькая вставочка на ассемблере, тк. я не знаю как в дельфи правильно работать с портами:

Эта программа будет делать следущее: выведет значение порта на экран, подождет 100мс, вернет курсор в начало строки и заменит старое значение на новое и так до тех пор, пока не нажата кнопка на клавиатуре.

Теперь можно запустить программу, убрать клавиатуру с мышкой в сторону и наблюдать за изменениями. Вот теперь начинается головоломка…

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

вывод значение
10 64
11 128
12 32
13 16
15 8

Я не случайно выделил 11 вывод жирным, он отличается от других – он логически инвертирован, те. если все наши кнопки система считает отжатыми, то эту она считает замкнутой. А если её замкнуть, то система будет думать что кнопка отжата. Теперь как это всё влияет на общее число которое мы считали (120): Если нажать на одну из наших кнопочек, то от общего числа отнимется значение этой кнопочки (см. таблицу). Например, мы нажимаем кнопку подключеную к выводу 10 и число сразу уменьшается на 64 (см. прогу), отпустим и значение снова увеличится на 64. А теперь, нажмем кнопку на выводе 15 – значение уменьшилось на 8, отпустили и оно опять увеличилось. А что будет если нажать особенную 11 кнопку? Нажимаем – значение не уменьшилось, а возрасло, отпустили и оно опять уменьшилось. Вот чем эта кнопка отличается от остальных 4. А теперь по русски, как узнать программе что нажато? Я делал так: Запоминаю что сейчас в порте, при изменении значения сравниваю что было и что получилось, если отличается на 64, значит нажата 10кнопка, если отличается на 32, значит 12 кнопка и тд. Чтобы определить нажата или отпущена, нужно учитывать увеличилось число или уменьшилось. То есть, если число стало меньше на 32, то нажата кнопка 12, а если число увеличилось на 32, значит кнопку 12 отпустили. НО! тут нужно учитывать, что кнопка со значением 128 (11вывод) работает наоборот.

Вот то же самое, только на программерском:

var bylo,stalo : word; razn : integer ;-64 : writeln('нажата кнопка 10 !'); 64 : writeln('отпущена кнопка 10 !'); -32 : writeln('нажата кнопка 12 !'); 32 : writeln('отпущена кнопка 12 !'); 128 : writeln('нажата кнопка 11 !'); -128 : writeln('отпущена кнопка 11 !');

Надеюсь, что этого кода достаточно для начала, дальше уже можно самостоятельно разобраться или спросить помощи на форуме Теперь снова об электронике… В простейшем варианте можно использовать кнопочки или переключатели как в экспериментальной панельке, можно поставить геркон, тк.

это тоже кнопочка, только магнитная, можно контакты реле… Но тут нужно помнить про такую нехорошую вешь, как “дребезг” контактов – расшатаный или просто некачественный выключатель обязательно будет давать повторные срабатывания в программе.

Если точность не нужна, то можно просто увеличить задержку с 100 мс до, например, 1 секунды и тогда программа просто не обработает повторные нажатия. А если нужна точность, то нужно что-то придумывать.

Теоретически, связать порт можно с любым низковольтным устройством через транзистор, те.

замыкать контакты не кнопкой, а транзистором.

Например, у нас есть схема, в которой светодиод загорается когда кто-то проходит рядом с устройством, если светодиод подключен прямо к выводу микросхемы, просто подпиваем к ножке микросхемы вместо светодиода резистор, а резистор к базе транзистора эмиттер с коллектором которого подключены вместо выключателя к ножке. Ух, во сказал, аж сам не понял. Просто лень рисовать схему, а примерчик этот из моей практики…

Источник: zps-еlесtrоnics.cоm

Источник: http://radiofanatic.ru/kompyuter/503-primery-skhem-dlya-lpt-porta.html

VB FAQ: § 4.7. Работа с устройствами, подключенными к LPT-порту

Источник: http://vbfaq.a1nt.ru/c07.htm

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}
");let k=document.querySelector(".flat_pm_modal[data-id-modal=\""+a.ID+"\"]");if(-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(k,d):jQuery(k).html(b+d),"px"==a.how.popup.px_s)e.bind(h,()=>{e.scrollTop()>a.how.popup.after&&(e.unbind(h),f.unbind(i),j())}),void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{e.unbind(h),f.unbind(i),j()});else{let b=setTimeout(()=>{f.unbind(i),j()},1e3*a.how.popup.after);void 0!==a.how.popup.close_window&&"true"==a.how.popup.close_window&&f.bind(i,()=>{clearTimeout(b),f.unbind(i),j()})}f.on("click",".flat_pm_modal .flat_pm_crs",()=>{jQuery.arcticmodal("close")})}if(void 0!==a.how.outgoing){let b,c="0"==a.how.outgoing.indent?"":" style=\"bottom:"+a.how.outgoing.indent+"px\"",e="true"==a.how.outgoing.cross?"":"",f=jQuery(window),g="scroll.out"+a.ID,h=void 0===flatPM_getCookie("flat_out_"+a.ID+"_mb")||"false"!=flatPM_getCookie("flat_out_"+a.ID+"_mb"),i=document.createElement("div"),j=jQuery("body"),k=()=>{void 0!==a.how.outgoing.cookie&&"false"==a.how.outgoing.cookie&&h&&(jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show"),j.on("click",".flat_pm_out[data-id-out=\""+a.ID+"\"] .flat_pm_crs",function(){flatPM_setCookie("flat_out_"+a.ID+"_mb",!1)})),(void 0===a.how.outgoing.cookie||"false"!=a.how.outgoing.cookie)&&jQuery(".flat_pm_out[data-id-out=\""+a.ID+"\"]").addClass("show")};switch(a.how.outgoing.whence){case"1":b="top";break;case"2":b="bottom";break;case"3":b="left";break;case"4":b="right";}jQuery("body > *").eq(0).before("
"+e+"
");let m=document.querySelector(".flat_pm_out[data-id-out=\""+a.ID+"\"]");-1===d.indexOf("go"+"oglesyndication")?flatPM_setHTML(m,d):jQuery(m).html(e+d),"px"==a.how.outgoing.px_s?f.bind(g,()=>{f.scrollTop()>a.how.outgoing.after&&(f.unbind(g),k())}):setTimeout(()=>{k()},1e3*a.how.outgoing.after),j.on("click",".flat_pm_out .flat_pm_crs",function(){jQuery(this).parent().removeClass("show").addClass("closed")})}countMode&&(flat_count["block_"+a.ID]={},flat_count["block_"+a.ID].count=1,flat_count["block_"+a.ID].click=0,flat_count["block_"+a.ID].id=a.ID)}catch(a){console.warn(a)}}function flatPM_start(){let a=flat_pm_arr.length;if(0==a)return flat_pm_arr=[],void jQuery(".flat_pm_start, .flat_pm_end").remove();flat_body=flat_body||jQuery("body"),!flat_counter&&countMode&&(flat_counter=!0,flat_body.on("click","[data-flat-id]",function(){let a=jQuery(this),b=a.attr("data-flat-id");flat_count["block_"+b].click++}),flat_body.on("mouseenter","[data-flat-id] iframe",function(){let a=jQuery(this),b=a.closest("[data-flat-id]").attr("data-flat-id");flat_iframe=b}).on("mouseleave","[data-flat-id] iframe",function(){flat_iframe=-1}),jQuery(window).on("beforeunload",()=>{jQuery.isEmptyObject(flat_count)||jQuery.ajax({async:!1,type:"POST",url:ajaxUrlFlatPM,dataType:"json",data:{action:"flat_pm_ajax",data_me:{method:"flat_pm_block_counter",arr:flat_count}}})}).on("blur",()=>{-1!=flat_iframe&&flat_count["block_"+flat_iframe].click++})),flat_userVars.init();for(let b=0;bflat_userVars.textlen||void 0!==a.chapter_sub&&a.chapter_subflat_userVars.titlelen||void 0!==a.title_sub&&a.title_subc&&cc&&c>d&&(b=flatPM_addDays(b,-1)),b>e||cd||c-1!=flat_userVars.referer.indexOf(a))||void 0!==a.referer.referer_disabled&&-1!=a.referer.referer_disabled.findIndex(a=>-1!=flat_userVars.referer.indexOf(a)))&&(c=!0),c||void 0===a.browser||(void 0===a.browser.browser_enabled||-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser))&&(void 0===a.browser.browser_disabled||-1==a.browser.browser_disabled.indexOf(flat_userVars.browser)))){if(c&&void 0!==a.browser&&void 0!==a.browser.browser_enabled&&-1!=a.browser.browser_enabled.indexOf(flat_userVars.browser)&&(c=!1),!c&&(void 0!==a.geo||void 0!==a.role)&&(""==flat_userVars.ccode||""==flat_userVars.country||""==flat_userVars.city||""==flat_userVars.role)){flat_pm_then.push(a),flatPM_setWrap(a),flat_body.hasClass("flat_pm_block_geo_role")||(flat_body.addClass("flat_pm_block_geo_role"),flatPM_ajax("flat_pm_block_geo_role")),c=!0}c||(flatPM_setWrap(a),flatPM_next(a))}}}let b=jQuery(".flatPM_sticky");b.each(function(){let a=jQuery(this),b=a.data("height")||350,c=a.data("top");a.wrap("
");let d=a.parent()[0];flatPM_sticky(this,d,c)}),debugMode||countMode||jQuery("[data-flat-id]:not([data-id-out]):not([data-id-modal])").contents().unwrap(),flat_pm_arr=[],jQuery(".flat_pm_start, .flat_pm_end").remove()}

На внешний порт компьютера (COM, LPT, Game; про USB отдельный разговор) может быть подключено любое устройство, начиная простейшим переключателем гирлянд и заканчивая АЦП/ЦАП-преобразователями в составе сложного измерительного прибора. Однако в любом из этих случаев, работа с внешним устройством сводится к чтению состояния одних ножек порта и управлению выходными сигналами на других ножках порта.

Примечание: Вообще это не совсем так, и пример тому — работа USB-портов или модемов на COM-портах, однако в данной статье не рассматривается последовательное управление устройствами, только параллельное, как наиболее простое и доступное для реализации.

Для примера изготовим простейшее устройство, показанное на схеме электрической принципиальной. Это устройство полностью демонстрирует описанный выше принцип.

OUT:

К ножке D0 (контакт 2) LPT-порта через резистор подключен анод («+») светоизлучающего диода. Резистор R1 номиналом 500 ом выполняет роль балластного, ограничивая ток из ножки порта и ток через светодиод, предотвращая сгорание светодиода и выход из строя порта. Катод («−») светодиода соединен с «землей» порта (выводы с 18 по 25).

Этот участок схемы выполняет роль устройства, которым управляют, взводя логический 1 или 0 на выходе D0 порта. То есть, в данном случае, программно включают и выключают светодиод.

Установка логического 0 на выходе D0 приводит к появлению потенциала, близкого к 0 (относительно «земли», здесь и в дальнейшем), установка же логического 1 на том же выходе приводит к появлению потенциала, близкого к +5 вольт.

IN:

К ножке ACK (контакт 10) того же порта через резистор подключена нормально разомкнутая кнопка SB1.

Резистор R2 номиналом 500 ом выполняет роль балластного, ограничивая ток в ножку и предотвращая выход из строя порта. Другой контакт кнопки соединен с землей.

Эта часть схемы является примером датчика, который в зависимости от своего состояния устанавливает низкий или высокий потенциал на входе.

Если датчик устанавливает низкий потенциал на входе (менее 1 вольта, то есть «притягивая» входной контакт к  «земле»), то это означает логический 0 на входе, и наоборот, если датчик устанавливает высокий потенциал на входе (более 3 вольт, «притягивая» входной контакт к +U или оставляя его неподключенным (хотя вообще это не рекомендуется)), то это означает логический 1 на входе.

То есть устанавливая лог. 1 на выходе D0, мы включаем светодиод, а установка лог. 0 на том же выходе его выключает.

Аналогично, нажмимая кнопку, мы устанавливаем на входе ACK лог. 0, а отжимая — лог. 1.

Замечу, что COM порт используется аналогичным образом. В отличие от LPT порта, который содержит 12 выходных и 5 входных линий, COM поддерживает 3 входных и 2 выходных линии. Для выходных линий нулем является напряжение −12 вольт, единицей — +12 вольт. Соответственно, для входных линий Gnd или −U распознаются как 0, и +U как 1.

Детали можно использовать любые подходящие, резисторы мощностью от 0,125 Вт и выше, номиналом 400 ом—620 ом, светодиод любой марки (лучше буржуйские, они ярко светят даже при токах в 2 mA, в то время как отечественным образцам нужен ток в 10 раз больше) и любого цвета, например LG2040; кнопка любая без фиксации, но подойдет и с фиксацией, или вообще любой тумблер.

Для подключения устройства к компьютеру потребуется разъем D25 male (25-пиновый тип “D”, «папа»). Крайне не рекомендую вместо использования ответного разъема засовывать в гнезда LPT-разъема проволочки. Можно легко ошибится, что-либо закоротить или механически вывести разъем из строя.

Саму схему можно смонтировать на куске текстолита, геттинакса, картона или фанеры и соединить с ответным разъемом трехпроводным шлейфом или кабелем. Учтите, длина кабеля не должна превышать 30 сантиметров, в противном случае придется установить блокирующий конденсатор между землей и входом ACK. Конденсатор любой, например, керамический марки КМ5, КМ6, номиналом 0,1—1,0 мкФ.

Программа для работы с данным устрйоством приведена в архиве lptio. В модуле Declare установите константу LPT в зависимости от номера того порта, к которому вы подключаете устройство. Но обычно в компьютере только один порт LPT, который к тому же часто занят под принтер, поэтому менять константу обычно нет необходимости, и требуется лишь отключить принтер, чтобы освободить порт.

Свойство ButtonState в том же модуле возвращает состояние кнопки: True = кнопка нажата, False = отжата.

Метод LedControl управляет светодиодом; если параметр метода равен True — светодиод зажжется, False — погаснет.

На форме отображаются номер и базовый порт выбранного LPT-порта, состояние кнопки SB1 и кнопка для переключения светодиода.

Для доступа к хардверным портам (LPT, Game) можно использовать любую подходящую бибилиотеку из WinIo, DLPortIo, VBIO (последняя не работает под NT), а для работы с COM-портом вполне подойдет входящий в поставку VB5/6 Microsoft Comm Control. Но допустимо использовать те же библиотеки, что и для доступа к LPT/Game-портам.

Чтобы запустить пример, положите файлы winio.dll, winio.vxd и winio.sys в папку с проектом и в каталог VB. В скомпилированном приложении, думаю, достаточно, чтобы эти файлы лежали только в его программы.

Домашнее задание.

  1. Переделайте программу таким образом, чтобы при нажатии кнопки SB1 загорался светодиод VD1, а при отпускании кнопки — погасал.
  2. Затем реализуйте обратный вариант: нажатие кнопки SB1 гасит светодиод, а отпускание той же кнопки его зажигает.
  3. И наконец, реализуйте программный счетчик-делитель с коэффициентом пересчета 2: при первом (нечетном) нажатии на кнопку SB1 светодиод VD1 загорается и продолжает гореть, даже если кнопку отпустят. При втором (четном) нажатии на кнопку SB1 светодиод гаснет, и его состояние не изменяется после отпускания кнопки.
  4. Поэкспериментируйте с устройством, например, определите, при каком максимальном значении сопротивления R1 светодиод перестает зажигаться, при каком максимальном значении R2 порт перестает реагировать на кнопку. Замерьте миллиамперметром проходимые токи через светодиод и кнопку при прежних значениях сопротивлений и при пороговых. Замерьте вольтметром напряжения на ножках порта D0 и ACK при этих экспериментах.

Примечание: лучше использовать комбинированный прибор типа мультиметра, который не только измеряет токи и напряжения, но и позволяет замерять сопротивления, а наиболее «продвинутые» модели приборов — годность полупроводниковых элементов, емкости конденсаторов, индуктивности катушек, средневзвешенную частоту. Цена цифрового прибора колеблется от 250 рублей (мыльница) до 2500 рублей и выше (профессиональные комбайны, с цифровым осциллографом и т. д.)

Дополнительные примеры.

Если вы увлекаетесь радиолюбительством, попробуйте изготовить конструкцию, несущую практическое применение, и написать управляющую программу («драйвер») для нее.

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

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

Еще один пример — считыватель чип или смарт-карты (сама карта мажет быть любой использованной: чип-карты телефонов или симкарта от сотового телефона); использование этого оборудования позволяет реализовать пропускной доступ в помещение или к компьютеру.

Гораздо удобнее выполнять логон, просто установив чип/смарт-карту в считыватель, нежели вводить имя пользователя и пароль. Также нетрудно реализуется цифровой термометр, если использовать в качестве измерительной головки (датчика) микросхему от Dallas Semiconductor DS1821. Несложно (на микросхемах K561ТВ1 и К561ЛА7) собрать устройство для управления сильноточной нагрузкой, например, кофеваркой. Разве не замечательно, когда утром вас будит терпкий аромат свежесваренного кофе? 🙂

Обратите свое внимание, что ни LPT, ни COM-порт не содержат выхода источника питания (в противоположность Game-порту, на котором присутствует +5 в), и в большинстве случаев нагрузочная возможность выходных ножек порта не превышает 3—7 mA (милиампер) на каждую ножку.

Попытка взять с ножек больший ток в лучшем случае приводит к падению напряжения на ножках, в худшем (при токах более 20 mA) — к возможности выхода порта из строя. Поэтому, если есть возможность — установите в компьютер мультикарту с портами либо переходник USB  COM или USB  LPT.

Литература.

Привести рекомендуемый список литературы просто невозможно — он огромен. 🙂 Ограничусь лишь особо рекомендуемой литературой:

TechHelp