Параллельный порт на PC до сих пор имеет некоторую привлекательность для разработчика. По сравнению с последовательным портом (RS232), параллельный порт может обеспечить более высокую скорость передачи данных. LPT-порт имеет уровни сигналов ТТЛ, поэтому для сопряжения его с простыми устройствами не требуется дополнительных согласователей. По сравнению с USB и RS232 на LPT-порту можно добиться более быстрой реакции выходного сигнала на команды управляющей программы. В отличие от специализированных PCI-карточек ввода-вывода, параллельный порт является широко распространенным, имеется почти в каждом компьютере, дешев и не зависит от монополиста-производителя.
Именно поэтому я через этот порт осуществляю вывод ТТЛ-сигнала, управляющего внешним устройством, от одной моей программы. И выбор оказался очень удачным. Чтобы создать новую систему на базе этой программы, не требуется заказывать экзотические PCI- или USB-карточки ввода-вывода. Почти нет ограничений на тип персонального компьютера - лишь бы в нем был параллельный порт.
Многие, вероятно слышали об усовершенствованиях параллельного порта по сравнению с тем, каким он был на заре эры PC. (речь идет о EPP/ECP). Порт стал истинно двунаправленным, повысилась пропускная способность и даже появился режим DMA - для скоростной передачи данных под управлением многозадачной ОС.
Да только все эти усовершенствования, почему-то, оказались похоронены заживо фирмой Microsoft. Почитайте Microsoft Windows SDK. Сколько там всего написано про API для работы с последовательным портом (RS232). Насколько все развито и доступно для рядового программиста. Не надо писать никакие драйверы - все доступно из пользовательских приложений.
Для параллельного порта ничего этого нет. Чтобы работать с ним из-под Windows NT/2000/XP, обычно люди пишут специализированные драйверы для своих устройств, либо используют программные пакеты, предоставляющие прямой доступ к портам ввода-вывода, такие как SHA. Оба эти варианта некрасивые: в первом случае требуется особо высокая квалификация программиста, чтобы написать драйвер. Во втором случае пользовательское приложение становится опасным: в случае сбоя оно может легко привести к краху операционной системы (синий экран).
На самом деле в Windows NT/2000/XP есть красивый способ доступа к параллельному порту из приложений, наподобие API для работы с COM-портами. Только он не документирован в SDK. Наткнулся я на него случайно, изучая DDK (Driver development kit).
Собрав вместе сведения из документации DDK, изучая исходники драйверов параллельного порта для NT/2000/XP (parport.sys & parallel.sys), а также заголовочных файлов DDK (ntddpar.h), я получил информацию, необходимую для доступа к параллельному порту из пользовательских приложений.
Работа происходит по типичному для винды сценарию. Сначала открывается устройство через CreateFile. Потом настраивается режим обмена путем серии вызовов DeviceIoControl. И начинается обмен данными через ReadFile / WriteFile.
Коды, которые необходимо передавать в DeviceIoControl, а также структуры данных, которые надо подавать в качестве параметров - все это описано в документации DDK и файле ntddpar.h. Этот файл необходимо вытащить из DDK и включить в состав своего приложения.
Виндошные драйверы параллельного порта довольно сложные. Они реализуют все тонкости протоколов Centronics / Nibble / EPP / ECP. Но для простого устройства - допустим если это просто светодиод, управляемый от одной из линий данных - все это излишне и даже нежелательно. А режима "прямого управления сигналами" в виндошных драйверах нет. Тем не менее, я нашел простой способ настроить драйвер на управление светодиодами. Для этого нужно подключить входной сигнал BUSY на землю и настроить порт на режим Centronics. При этом порт можно использовать как 8 выходных цифровых линий и управлять ими из программы с помощью WriteFile.
К сожалению, без внешних микросхем нельзя использовать таким образом параллельный порт для ввода информации. Если на любой из сигналов (BUSY,ACK,ERROR,PAPER_OUT,SELECT) подать не тот уровень, то драйвер не сможет производить в порт вывод.
Упрощенный сценарий Centronics, таким образом, выглядит так:
1. CreateFile("LPT1",GENERIC_READ | GENERIC_WRITE) // exclusive sharing
2. Negotiate Centronics:
PARCLASS_NEGOTIATION_MASK imsk;
imsk.usReadMask = NONE; //0000
imsg.usWriteMask = CENTRONICS; //0001
PARCLASS_NEGOTIATION_MASK omsk;
DeviceIoControl(IOCTL_IEEE1284_NEGOTIATE,&imsk,&omsk);
PAR_QUERY_INFORMATION pqi;
DeviceIoControl(IOCTL_PAR_QUERY_INFORMATION,NULL,pqi);
if(pqi.Status != PARALLEL_SELECTED)
{
// Error - device not properly connected
}
3. На этом этапе можно пользоваться WriteFile
Надеюсь, кому-нибудь это поможет!