BEPCTAK
РАБОТА С LPT
Курс Молодого бойца
Пластиковые карты
Работа с LPT
Радиомикрофоны и передатчики
Счетчик Энергии
Таксофонные Смарт-карты
Телепередатчик
РАБОТА С LPT
  1. АППАРАТНАЯ часть - разъем порта
  2. ДОСТУП и управление портом

  1. Аппаратная часть - разъем порта

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

розетка порта

Назначение контактов (специфика работы с принтером) следующее:

1 STROBE - Строб (НИЗКИЙ означает что можно читать данные)
2 DATA 1 - линия данных 1
3 DATA 2 - " 2
4 DATA 3 - " 3
5 DATA 4 - " 4
6 DATA 5 - " 5
7 DATA 6 - " 6
8 DATA 7 - " 7
9 DATA 8 - " 8
10 ACKNLG - Принято (НИЗКИЙ показывает что данные считаны устройством)
11 BUSY - Занято (ВЫСКОЙ в следующих случаях:
(a) прием данных
(b) печать
(c) принтер офф-лайн
(d) ошибка принтера)
12 PE - Нет бумаги (ВЫСОКИЙ если в принтере не бумаги)
13 SLCT - Выбор (ВЫСОКИЙ если принтер выбран)
14 AUTO FEED XT - Авто-перевод строки (НИЗКИЙ показывает принтер будет автоматически переводить строку
после знака "возврат каретки". Зависит от установки DIP переключателей принтера.
15 n.c.
16 0V - Логичексая земля
17 CHASSIS GND - Шасси (земля)
18 n.c.
19-30 GND - Сигнальная земля (оплетки жил от контактов 1-12)
31 INIT - Инициализация (НИЗКИЙ импульс для сброса принтера)
32 ERROR - Ошибка (НИЗКИЙ если:
(a) кончилась бумага
(b) устройство офф-лайн
(c) состояние ошибки)
33 GND - Сигнальная земля
34 n.c.
35 LOGIC 1 - Логический ВЫСОКИЙ (обычно от источника +5 В через 3.3 кОм)
36 SLCT IN - Разрешение ввода (данные вводятся в принтер только если на линии НИЗКИЙ,
однако зависит от установки DIP переключателей)
Как видно из этой таблицы, порт имеет достаточное количество входных и выходных линий, что позволяет подключать множество самых разнообразных устройств, требующих управления от компьютера. Нагрузочная способность выходов в нормальном режиме не более 1 мА, максимум 5 мА и зависит от чипа, на котором реализован интерфейс. Наибольшую нагрузку допускают порты, реализованные в виде отдельной мультикарты, наименьшую - интергрированный в одном чипе контроллер периферии, встроенный в материнскую плату. Для экспериментальной работы лучше использовать отдельные MIO карты, так как при случайных повреждениях страдает дешевая карта, в то время как при повреждении интегрированного контроллера в негодность приходит вся материнская плата.

Порт можно использовать и для питания подсоединенных устройств и позволяет обойтись без внешнего источника питания в случае, если потребляемый ток не превышает 10 мА (КМОП-схемы). Для этого через диоды объединяют неиспользуемые выходы шиной (аноды к выходам, катоды на шину), последовательно устанавливают резистор сопротивлением не менее 100 оМ (для защиты от перегрузки выходов при случайном коротком замыкании), и параллельно на землю - конденсатор емкостью не менее 10 мкФ, для сглаживания пульсаций питающего тока. Так как микросхемы КМОП потребляют ток только в момент переключения, напряжение на конденсаторе будет примерно равно напряжению логической единицы, т.е. не менее 3.6 вольта, что вполне достаточно для питания большинства микросхем.

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

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

Порт можно использовать для превращения компьютера в мощный контроллер, для управления чипами, программирования ПЗУ, в качестве светомузыки, и т. п. В случае, если требуется посдоединять не-ТТЛ оборудование или управлять цепями с повышенной нагрузкой/напряжением, используйте стандартные ТТЛ-развязки и адаптеры. Ключ +22 В показан на схеме читалки в статье ТАКСОФОННЫЕ СМАРТ-КАРТЫ. Для управления сетевыми устройствами рекомендуется использовать гальванически развязанный через оптрон адаптер, гарантирующий полную безопасность:

Номиналы указаны для оптрона с индексом Б. Для оптрона с индексом А номинал входного резистора надо уменьшить с 470 Ом до 330 Ом, а резистор базы с 82 кОм до 15 кОм.

Наверх

  2. Доступ и управление портом

Компьютер IBM может управлять тремя параллельными портами LPT1-LPT3. Базовый адрес LPT1 находится в ячейке BIOS 0040:0008 (слово), LPT2 - 0040:000A и т. д. Какой адаптер назначен какому LPT не определено и зависит от конфигурации компьютера и ОС, поэтому программа должна определить используемые ими адреса. При инициализации базовому адресу присваивается 0, если адаптер не установлен.

Адаптер Регистр
входных данных
Регистр
статуса
Регистр
управления
LPT1 378h 379h 37Ah
LPT2 278h 279h 27Ah

Регистр выходных данных - тот адрес порта, через который проходит каждый байт данных, посылаемый в порт. Регистр статуса сообщает различную информацию о входных линиях; процессор может постоянно опрашивать его, чтобы распознать момент, когда все в порядке и можно посылать данные. Регистр статуса сообщает также, что произошла ошибка (линия ERROR). Регистр управления инициализирует адаптер и управляет выводом данных. Он может также подготавливать параллельный порт для операций преры- вания, с тем чтобы устройство посылало прерывание к процессору, когда оно готово к приему очередной порции данных, оставляя процессор свободным для других дел. Ниже перечислены значения битов регистров статуса и управления:

Регистр управления
бит 0 0 = нормальная установка 1 = вызывает вывод байта данных
бит 1 0 = нормальная установка 1 = автоматический перевод строки после
возврата каретки
бит 2 0 = инициализировать порт принтера 1 = нормальная установка
бит 3 0 = отмена выбора принтера 1 = нормальная установка
бит 4 0 = прерывание принтера запрещено 1 = разрешено
бит 5-7 не используются

Регистр статуса
бит 0-2 не используются
бит 3 0 = ошибка принтера 1 = нет ошибки
бит 4 0 = принтер off-line 1 = принтер on-line
бит 5 0 = бумага вставлена 1 = нет бумаги
бит 6 0 = принтер подтверждает прием символа 1= нормальная установки
бит 7 0 = принтер занят 1 = принтер свободен

Из этих таблиц видно, как соотностятся входные линии порта и биты регистров управления и статуса.

Мы можем управлять отдельно каждой выходной линией порта, послыая соответствующий байт в базовый регистр, и знать состояние каждой входной линии, читая из регистров статуса/управления. Для получения базового адреса порта прочитаем его из BIOS:

(ASM):

MOV AX,0040h
MOV ES,AX ; записали сегмент BIOS в ES
MOV DX,ES:[8] ; прочитали базовый адрес
MOV LPT_BASE, DX ; и запомнили
INC DX
MOV LPT1_CONTROL,DX ; добавили 1 и получили рег. управления
INC DX
MOV LPT1_STATUS,DX ; добавили еще 1 и получили рег. статуса
...
MOV AL,... ; что-то занесли в AL
OUT DX,AL ; и записали в порт статуса

(BASIC):

Def Seg = &h40 ' установили сегмент
BIOS
LPT1Base = Peek (9) + &hFF * Peek (8)
LPT1Control = LPTBase + 1
LPT1Status = LPTBase + 2
...
OUT LPT1Base, MyByte ' вывод данных в порт
...
Status = INP (LPTControl) ' чтение регистра управления

Если нам необходимо изменить состояние только одного из битов регистра, сначала надо прочитать из него значение и с произвести с ним логическиую операцию OR или AND с маской, где выставлен изменяемый бит, в зависимости от того, хотим мы установить или сбросить этот бит.
Например, требуется установить ВЫСОКИЙ уровень на линии SLCT IN (выбор принтера). Из таблиц видим, что этой линией управляет бит 3 регистра управления. Проделаем следующее:

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

Для сброса этой линии в НИЗКИЙ уровень делаем так:

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

Рассмотрим фрагмент кода для таких операций:

(ASM):

; установим ВЫСОКИЙ уровень
MOV DX,LPT1_CONTROL ; загрузили адрес регистра в DX
MOV AH, 00001000b ; маску - в AH
IN AL,DX ; прочитали регистр
OR AL,AH ; отмаскировали
OUT DX,AL ; записали обратно
...
; установим НИЗКИЙ
MOV DX,LPT1_CONTROL ; загрузили адрес регистра в DX
MOV AH, 11110111b ; маску - в AH (для циклического изменения используем NOT)
IN AL,DX ; прочитали регистр
AND AL,AH ; отмаскировали
OUT DX,AL ; записали обратно
...

(BASIC):

...
' установка ВЫСОКОГО уровня
Mask=8 ' 00001000b
Value = INP (LPT1Control)
Value = Value OR Mask
OUT LPT1Control, Value
...
' установка НИЗКОГО уровня
Mask=247 ' 11110111b
Value = INP (LPT1Control)
Value = Value AND Mask
OUT LPT1Control, Value
...

В статье ТАКСОФОННЫЕ СМАРТ-КАРТЫ описана читалка карточек, подсоединяемая к LPT. Ниже помещен текст программы, использовавшейся для отладки читалки, написанный на языке Basic, которую можно запускать под интерпретатором, входящим в поставку МС-ДОС. Подпрограмма writecard() пишет 0 или 1 во все адреса карточки.

' ---
' --- PayPHONE CARDS ---
' ---
DECLARE SUB writecard ()
DECLARE FUNCTION iif$ (arg AS INTEGER, truepath AS STRING, falsepath AS STRING)
DECLARE SUB shortdelay ()
DECLARE SUB delay (value AS INTEGER)
DECLARE SUB readcard ()
DECLARE SUB cardreset ()
' using LPT#1 port
CONST lptbase = &H378
CONST lptstatus = lptbase + 1
CONST lptctrl = lptbase + 2
DIM SHARED cardtype
' --------------------------
' PinOut Connection:
' --------------------------
' Wire Signal Reader
' --------------------------
' 2 D0 Reset
' 3 D1 Clock
' 4 D2 R/W
' 11 BUSY I/O
' 25 GND GND
' --------------------------
start:
CLS ' clear screen
PRINT "Select casd type ISO1 - [1] or ISO2 - [2]:"
locr0: ' loop cicle waiting when user press a key
a$ = UCASE$(INKEY$)
IF a$ = "1" THEN cardtype = 1: GOTO locr1
IF a$ = "2" THEN cardtype = 2: GOTO locr1
GOTO locr0

locr1:

PRINT "Insert a card and press [R] for Reading; [W] for Writing."

loc0: ' loop cicle waiting when user press a key
a$ = INKEY$
a$ = UCASE$(a$) ' this function make upper-case char
IF a$ = "R" THEN GOTO reading
IF a$ = "W" THEN GOTO writing
GOTO loc0

reading:

OUT lptctrl, datanorm ' port initialization

CLS ' clear screen

PRINT "Resetting card. Please wait..."

cardreset

CLS

PRINT "Reading card:"
PRINT
PRINT " byte number bit number value descrtption"
PRINT " Dec Hex 7 6 5 4 : 3 2 1 0 Dec Hex (optional)"
PRINT "--8<------------ | | | | | | | | --------------------------"

readcard

PRINT "--8<---------------------------------------------------------"
PRINT
PRINT "[N] for new card or [Q] for quit"

loc1: ' loop cicle waiting when user press a key
a$ = INKEY$
a$ = UCASE$(a$)
IF a$ = "N" THEN GOTO start
IF a$ = "Q" THEN END
GOTO loc1

writing:

CLS
PRINT "Resetting card..."
cardreset
CLS
PRINT "Writing card"
LOCATE 2, 2: PRINT STRING$(32, "ё")

writecard

PRINT "Now test reading card. Press a key"
SLEEP ' wait for user press a key
GOTO reading

tr1:
PRINT "Ops! An error "; ERR; " occured."

END

' ------------------------------
' SubRoutines & Functions
' ------------------------------

SUB cardreset
IF cardtype = 2 THEN
OUT lptbase, &H4 ' CLK & RESET DOWN
delay 1
OUT lptbase, &H6 ' CLK UP
delay 1
OUT lptbase, &H4 ' CLK DOWN
delay 1
OUT lptbase, &H0 ' RESET UP - to normal position
delay 1
ELSE
OUT lptbase, &H0 ' CLK & RESET DOWN
delay 1
OUT lptbase, &H2 ' CLK UP
delay 1
OUT lptbase, &H0 ' CLK DOWN
delay 1
OUT lptbase, &H1 ' RESET UP - to normal position
delay 1
END IF
END SUB

' ---------------------------

SUB delay (value AS INTEGER)
DIM t AS SINGLE
t = TIMER + value / 100
WHILE t > TIMER: WEND
END SUB

' ---------------------------

FUNCTION iif$ (arg AS INTEGER, truepath AS STRING, falsepath AS STRING)
IF arg THEN iif$ = truepath ELSE iif$ = falsepath
END FUNCTION

' ---------------------------

SUB readcard
DIM i AS INTEGER
DIM j AS INTEGER
DIM bit AS INTEGER
DIM value AS INTEGER
DIM french AS INTEGER
CONST true = -1, false = 0

FOR i = 1 TO 32

' right align the columns

IF i < 10 THEN
PRINT "Byte " + STR$(i) + " (0x" + iif(LEN(HEX$(i)) = 2, HEX$(i), "0" + HEX$(i)) + ")
";
ELSE
PRINT "Byte" + STR$(i) + " (0x" + iif(LEN(HEX$(i)) = 2, HEX$(i), "0" + HEX$(i)) + ")
";
END IF

' start to reading new byte

FOR j = 1 TO 8

' after chip has reseted
' we already have bit #1
' on I/O pin, then get it:

bit = -NOT (-(INP(lptstatus) AND &H80) \ &H80)
PRINT STR$(bit);

IF j = 4 THEN PRINT " :";

value = value + (2 ^ (8 - j) * bit)

IF cardtype = 2 THEN

OUT lptbase, &H0 ' drop CLK, RESET still raised
shortdelay
OUT lptbase, &H2 ' raise CLK
shortdelay
OUT lptbase, &H0 ' drop CLK
shortdelay

ELSE

OUT lptbase, &H1
shortdelay
OUT lptbase, &H3 ' raise CLK
shortdelay
OUT lptbase, &H1 ' drop CLK
shortdelay

END IF

' now card have a next bit

NEXT j

PRINT " " + STR$(value);
PRINT SPACE$(5 - LEN(STR$(value)));
PRINT "(0x" + HEX$(value) + ") ";

' check what screen filled and scrollup after key press
IF i= 16 THEN
PRINT
PRINT "Press a key to continue...";
SLEEP
END IF

PRINT

value = 0

NEXT i
END SUB

' ---------------------------

SUB shortdelay
FOR t = 0 TO 1000: NEXT
END SUB

' ---------------------------

SUB writecard
OUT lptbase, 0
delay 5
zero = -1 ' (pisat nuli ili edinici)
FOR i = 1 TO 256
IF zero THEN
OUT lptbase, 4
shortdelay
OUT lptbase, 0
shortdelay
OUT lptbase, 2
shortdelay
OUT lptbase, 0
shortdelay
OUT lptbase, 2
shortdelay
OUT lptbase, 0
shortdelay
ELSE
OUT lptbase, 4
delay 1
OUT lptbase, 0
delay 1
OUT lptbase, 2
delay 1
OUT lptbase, 0
delay 1
OUT lptbase, 4
delay 1
OUT lptbase, 0
delay 1
OUT lptbase, 2
delay 1
OUT lptbase, 0
delay 1
OUT lptbase, 2
delay 1
OUT lptbase, 0
delay 1
END IF
LOCATE 2, 2: PRINT STRING$(i / 8, "_")
NEXT i
END SUB

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

Наверх