Школа Перспектива
О школе | Условия приема | Контакты Версия для печати

Учеба
Лагеря
Походы
Ролевые игры
Мероприятия
Проекты
Методики
Расписание

Написать нам

  В начало / Проекты

Работа с параллельным портом (LPT)

А. Новожилов

     Отдельное спасибо Дмитрию Петрову, г.Борисоглебск за помощь в написании статьи

     В статье будут рассмотрены примеры чтения и записи данных в LPT порт, а также работа с некоторыми управляющими сигналами. Если Вы хотите что-либо считывать с порта, то Вам необходимо переключить режим работы порта компьютера в режим EPP (Enhanced Parallel Port - режим двунаправленной передачи данных). Это делается в BIOS. Во время загрузки компьютера когда появится надпись Press DEL to enter setup, нажмите DEL, чтобы попасть в меню BIOS. Затем выберите раздел INTEGRATED PERIPHERALS и там выберите строку PARALLEL PORT MODE: измените режим работы Вашего порта на EPP или SPP/EPP. Сохраните сделанные изменения. Если же на Вашем компьютере нет режима EPP, то Вы сможете только передавать данные.

     Параллельный порт для связи с принтером (или другим устройством) имеет базовый адрес &H378 (LPT1), &H278 (LPT2), &H3BC (LPT3). В данной статье мы будем рассматривать только LPT1. Адресное пространство порта занимает диапазон &H378-&H37F. Адрес &H378 называется базовым и служит для передачи или чтения данных, через контакты 2-9 разъема LPT-порта. Адрес &H37A служит для передачи управляющих сигналов к устройству, подключенного к этому порту (принтер, сканер и т.д.). И, наконец, адрес &H379 предназначен для приема управляющих сигналов с устройства, подключенного к этому порту (принтер, сканер и т.д.). Рассмотрим конкретные примеры для каждого из адресов. Для написания статьи я использовал VB5 и библиотеку Inpout32.dll. В принципе подойдет любая другая, которая имеет возможность общаться с LPT портом.

Начало программы.

     В самом начале программы необходимо указать с какой библиотекой мы будем работать:

     Option Explicit
     Private Declare Function Inp Lib "inpout32.dll" _
     Alias "Inp32" (ByVal PortAddress As Integer) As Integer
     Private Declare Sub Out Lib "inpout32.dll" _
     Alias "Out32" (ByVal PortAddress As Integer, ByVal Value As Integer)

     Передача числа 15 в LPT-порт адрес &H378

     Private Sub Command1_Click()
     Out &H378, 15
     End Sub

     Чтобы наглядно убедиться в работоспособности программы соберите для удобства вот такую схему:

     После нажатия кнопки Command1 на контактах 2-5 появиться уровень логической 1 (+5В) значит первые (сверху по схеме) 4 светодиода загорятся (1 + 2 + 4 + 8 = 15).

     Команда: Out &H378, 0 - погасит все светодиоды

     Команда: Out &H378, 255 - заставит все светодиоды светиться (1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 = 255)

     В таблице, расположенной внизу, можно увидеть основные сигналы при работе параллельного порта в режиме EPP. In - входящий сигнал, Out - исходящий сигнал. Например, когда на 14 контакте (Data Strobe - стробирование данных) появляется уровень логического 0, то принтер "понимает", что сейчас можно принимать данные.

№ контакта EPP Signal IN/OUT Функция
1 -Write Out

Низкий уровень сигнала - запись, высокий уровень сигнала - чтение

2-9 Data 0-7 In-Out

Данные

10 Interrupt In

Прерывание. Происходит на переднем положительном фронте импульса

11 Wait In

Ожидание. Используется для подтверждения связи. EPP цикл может быть начат, когда уровень низкий, и закончен когда высокий

12    

Не используется в EPP

13    

Не используется в EPP

14 -Data Strobe Out

Когда уровень низкий, сообщает о передаче данных

15    

Не используется в EPP

16 Reset Out

Reset - активный уровень низкий

17 -Address Strobe Out

Когда уровень низкий сообщает о передаче адреса

18-25 Ground GND

Корпус

     Теперь немного о командах, которые помогут Вам управлять Вашими устройствами.

     Минус впереди названия сигнала (напр. - Write) означает, что сигнал инверсный (обратный). Что это такое? Когда мы зажигали светодиоды (передавали данные), мы отправляли логическую единицу (высокий уровень) в том или ином бите, чтобы светодиод загорелся. Для того, чтобы "зажечь" светодиод подключенный к контакту 1 (-Write) мы должны подать на этот контакт уровень логического нуля. Контроллер проинвертирует этот сигнал, т.е. изменит на противоположный (на лог.1) и зажжет светодиод. Подали 0 получили 1, подали 1 получили 0.

     Схема вот такая

     "Зажигаем" сигнал -Writeадрес &H37A

     Private Sub Command1_Click()
     Out &H37A, 10
     End Sub

     Сразу возникает вопрос, почему передаем 10 (0 + 2 + 0 + 8 = 10) . В самом младшем бите D0 уровень лог.0. Сигнал -Write инверсный, значит на выходе будет лог.1 (светодиод горит), во втором бите D1 уровень лог.1, сигнал -Data Strobe инверсный, значит на выходе будет лог.0 (светодиод не горит), в третьем бите D2 лог.0, сигнал Reset обычный, значит на выходе будет лог.0 (светодиод не горит), в четвертом бите D3 уровень лог.1, сигнал -Address Strobe инверсный, значит на выходе будет лог.0 (светодиод не горит). Вот и весь секрет J. В таблице показаны некоторые комбинации "зажигания" светодиодов на контактах -Write, -Data Strobe, Reset, -Address Strobe

Разряды D0 D1 D2 D3
D0 D1 D2 D3 D4 D5 D6 D7 -WRITE -DATA STROBE RESET -ADDRESS STROBE
1 2 4 8 16 32 64 128
0 1 0 1                
1 0 0 1                
1 1 1 1                
1 1 0 0                
0 1 0 0                
0 1 1 1                
0 0 0 1                
1 0 1 1                
1 1 1 0                

     Прием данных из LPT-портаАдрес &H378 или &H37B-&H37F

     Во время экспериментов я пришел к следующему результату. Можно принимать данные либо по адресу &H378 либо в диапазоне адресов, начиная с &H37B - &H37F (по любому из них). В первом случае я подавал сначала команду, переводящую порт в режим приема, а потом считывал данные по адресу &H378

     Private Sub Command1_Click()
     Out &H37A, 32
     Text1.Text = Inp(&H378)
     End Sub

     Во втором случае я просто читал данные по адресу &H37F, без всякой подготовки порта

     Private Sub Command1_Click()
     Text1.Text = Inp(&H37F)
     End Sub

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

     Для наглядности работы программы соберите такую схему.

     При всех разомкнутых кнопках на разрядах D0-D7 присутствует уровень логической единицы и если выполнить такую команду,

     Private Sub Command1_Click()
     Text1.Text = Inp(&H37F)
     End Sub

     то в TextBox появится число 255 (1 + 2 + 4 + 8 + 16 + 32 + 64 + 128 = 255). Если же замкнуть, например, нижнюю по схеме кнопку, на разряде D7

     и выполнить команду,

     Private Sub Command1_Click()
     Text1.Text = Inp(&H37F)
     End Sub

     то в TextBox появится число 127 (1 + 2 + 4 + 8 + 16 + 32 + 64 = 127). Если Вы замкнете все кнопки, то прочитаете 0 (ноль)

     Как принять команду со своего устройства адрес &H379

     Из самой первой таблицы можно взять два сигнала, которые могут только принимать команды от Вашего устройства, это контакт 10 (Interrupt - прерывание) и контакт 11 (Wait - ожидание).

     Код программы такой:

     Private Sub Command1_Click()
     Text1.Text = Inp(&H379)
     End Sub

     Попробуйте соединить контакт 11 через резистор 10 кОм на землю и выполните код,

     а теперь посадите этот же резистор на +5В (от отдельного источника питания), выполните код и Вы увидите совсем другой результат.