ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 04.07.2020
Просмотров: 3146
Скачиваний: 1
такой сброс принтера, когда программа завершает работу с ним.
Языки высокого уровня инициализируют порт принтера автомати-
чески, но программы на языке ассемблера требуют для этой цели
короткую процедуру. С другой стороны, восстановление начальных
параметров печати требуется во всех программах. Некоторые принте-
ры, такие как новые Эпсоновские принтеры, имеют "главный код
сброса", который приводит к полному сбросу принтера. Но поскольку
не все принтеры имеют такой код, то программа должна предусматри-
вать в своей завершающей части восстановление всех измененных
параметров. Например, она может подать коды выключения курсива,
выключения плотной печати и т.д. Не забудьте включить вызов этой
процедуры в процедуру выхода по Ctrl-Break.
Имейте в виду, что на многих принтерах символы не печатаются
до тех пор, пока не получен код возврата каретки, завершающий
строку (или до тех пор пока не введена целая строка данных).
Символы могут спокойно ожидать в буфере принтера, даже после
того, как породившая их программа завершилась. Когда начинается
новая передача данных на принтер, то эти символы будут напечата-
ны. Чтобы избежать этой проблемы, не забывайте почистить буфер
перед началом печати; а в качестве правил хорошего тона, чистите
буфер также при завершении программы. Это делается посылкой на
принтер кода ASCII 24 (при этом параметры печати не меняются).
Средний уровень.
Функция 1 прерывания 17H BIOS инициализирует порт принтера и
возвращает байт, дающий статус порта. Поместите в DX номер порта
- число от 0 до 2 для LPT1 - LPT3, после чего вызовите прерыва-
ние. Байт статуса принтера (идентичный обсуждаемому в [6.1.2])
возвращается в AH.
;---инициализация LPT1
MOV AH,1 ;функция инициализации принтера
MOV DX,0 ;LPT1
INT 17H ;проводим инициализацию
Низкий уровень.
Ренистр управления выводом каждого адаптера принтера имеет
бит, который вызывает инициализацию адаптера. Этот регистр имеет
адрес порта на 2 больше, чем базовый адрес адаптера. Напоминаем,
что базовый адрес для LPT1 хранится в ячейке 0040:0008, для LPT2
- в 0040:000A и т.д. Имеют значение только младшие 5 битов ре-
гистра управления выводом. Бит 2 - бит инициализации принтера и
обычно он устанавливается в 1. Для инициализации адаптера надо
сбросить этот бит в 0 на тысячу тактов пустого цикла (3000 для AT
или на 1/20 секунды, используя счетчик времени суток BIOS
[2.1.5]). В этот момент нужно, чтобы был установлен только бит 3
(принтер выбран). Поэтому пошлите в порт значение 12, сделайте
задержку, а затем пошлите в порт обычное (без прерываний) неини-
циализонное значение, которое равно 8.
В данном примере инициализируется LPT1:
;---инициализируем LPT1
MOV DX,ES:[8] ;считываем базовый адрес в DX
INC DX ;прибавляем 2 к базовому адресу
INC DX ;
MOV AL,12 ;значение для инициализации
OUT DX,AL ;начинаем инициализацию
DELAY: MOV AX,1000 ;начало пустого цикла
DEC AX ;уменьшаем счетчик
JNZ DELAY ;повторяем 1000 раз
MOV AL,8 ;обычное значение для регистра
OUT DX,AL ;конец инициализации
6.1.2 Проверка того, что принтер связан с машиной.
Программа всегда должна проверить, что принтер связан с маши-
ной, перед тем, как послать на него вывод. Легко установить, что
принтер не готов, так как бит 3 регистра статуса принтера уста-
навливается в 1 в этом случае. Но намного сложнее точно опреде-
лить почему принтер не готов: выключен ли он, отменен выбор прин-
тера или в нем нет бумаги. Это происходит из-за того, что принте-
ры разных производителей посылают разные наборы битов в регистр
статуса принтера, даже когда они находятся в идентичном состоя-
нии. Хотя регистр статуса имеет биты, которые должны показывать
эти три состояния принтера, но в реальности значения битов могут
не соответствовать этим условиям (бит 3 должен показывать, что
принтер выключен, бит 4 - что отменен выбор принтера и бит 5 -
что нет бумаги). Нижеприведенные значения возвращаются в регистр
статуса по стандарту "Эпсон", которому обычно следует IBM:
Значение Цепочка битов Интерпретация
223 11011111 принтер готов
87 01010111 принтер не готов
119 01110111 нет бумаги в принтере
247 11110111 принтер выключен
Регистр статуса ввода имеет адрес порта на 1 больше, чем базо-
вый адрес принтера. Базовый адрес для LPT1 хранится по адресу
0040:0008, для LPT2 - по адресу 0040:000A и т.д. Имейте в виду,
что если принтер был выключен, то ему требуется некоторое время
на инициализацию после включения. Не начинайте печатать до тех
пор, пока регистр статуса ввода не сообщит, что принтер связан с
машиной и готов к приему данных.
Высокий уровень.
Данная процедура проверяет связан ли принтер с машиной и гово-
рит пользователю что делать, если нет. Она использует значения из
вышеприведенной таблицы. Как уже отмечалось, такой подход не
подходит для процедуры общего назначения, которая будет обслужи-
вать множество разных принтеров, но он вполне подходит, когда Вы
пишете драйвер данного печатающего устройства. Отметим, что в
строке 120 вычисляется двухбайтное число, путем умножения старше-
го байта на 256 и добавления к младшему байту. Для получения
адреса регистра статуса ввода к значению полученного базового
адреса добавляется 1.
100 '''Получаем адрес LPT1 и проверяем готов ли принтер
110 DEF SEG = &H40 'указываем на область BIOS
120 PRTRBASE = PEEK(9)+256*PEEK(8)+1 'адрес регистра статуса
130 IF INP(PRTRBASE) = 223 THEN 180 'если принтер готов
140 BEEP 'иначе звонок и проверки
150 IF INP(PRTRBASE) = 87 THEN LOCATE 1,1: PRINT"Strike the
SELECT key": GOTO 150
160 IF INP(PRTRBASE) = 247 THEN LOCATE 1,1: PRINT"Turn the
printer on": GOTO 160
170 IF INP(PRTRBASE) <> 223 THEN 170 'ждем инициализации
180 '''Теперь принтер on-line -- можно начинать печать
190 LPRINT Z$
Средний уровень.
Для получения байта статуса из порта принтера надо использо-
вать функцию 2 прерывания 17H. При входе DX содержит номер LPT
(0-2 для LPT1-3). Эта функция сбрасывает три неиспользуемых бита
байта и делает операцию исключающего ИЛИ над двумя другими, поэ-
тому значения отличаются от приведенных выше:
Значение Цепочка битов Интерпретация
144 10010000 принтер готов
24 00011000 принтер не готов
184 10111000 принтер выключен
И опять необходимо помнить, что эти значения меняются от принтера
к принтеру. Наиболее общую информацию "выключен или не готов"
дает бит 3 статуса равный 0.
Низкий уровень.
Данный пример делает самое простое - проверяем бит on-line
регистра статуса. Для получения байта статуса используется базо-
вый адрес LPT1.
;---в сегменте
MESSAGE DB 'Printer not ready - strike any key when OK$'
;---проверка связан ли принтер с машиной (on-line)
MOV AX,40H ;ES указывает на область данных BIOS
MOV ES,AX ;
MOV DX,ES:[8] ;получаем базовый адрес
INC DX ;смещение для регистра статуса
IN AL,DX ;получаем байт статуса в AL
TEST AL,1000B ;проверяем бит 3
JNZ GO_AHEAD ;если принтер on-line, то вперед
;---печатаем сообщение об ошибке и ждем нажатия клавиши
MOV AH,9 ;функция вывода строки
LEA DX,MESSAGE ;DS:DX указывают на сообщение
INT 21H ;печатаем сообщение
MOV AH,7 ;функция ожидания ввода
INT 21H ;ожидаем нажатия клавиши (без эха)
GO_AHEAD: ;продолжение программы
6.1.3 Интерпретация ошибок принтера и восстановление после них.
Проверка ошибок не должна прекращаться на том, что Вы убеди-
лись, что принтер связан с машиной. Ошибки принтера могут проис-
ходить в любой момент печати и программа должна быть готова восс-
тановить ситуацию при сбоях. Хотя на принтере могут происходить
самые разнообразные ошибки, только три типа ошибок возвращают
информацию о себе в компьютер. Это ошибка "отсутствия бумаги",
ошибка "отсутствия связи с машиной" и общее сообщение "произошла
ошибка". Как уже говорилось в [6.1.2], не все принтеры сообщают
об этих ошибках одинаковым образом, но теоретически регистр ста-
туса ввода использует следующие биты:
бит 3 = 0 когда произошла ошибка на принтере
бит 4 = 0 когда принтер не связан с машиной (off-line)
бит 5 = 1 когда кончилась бумага на принтере
В частности, бит 4 может не использоваться указанным образом.
Регистр статуса ввода имеет адрес порта, который на 1 больше, чем
базовый адрес принтера. Базовый адрес для LPT1 хранится по адресу
0040:0008, для LPT2 - по адресу 0040:000A и т.д.
На низком уровне, когда программа посылает данные на принтер,
то она постоянно обращается к биту 7 этого регистра, чтобы прове-
рить готов ли принтер принять очередной символ. Несложно при этом
проверить при этом и бит 3, чтобы узнать о произошедшей ошибке.
Если происходит ошибка, индицируемая битами 4 и 5, то по крайней
мере бит 3 будет равен 0. Программа должна постараться проанали-
зировать ошибку, а затем может попросить пользователя исправить
ситуацию. Отметим, что функцию DOS, которая выводит символы на
принтер (функция номер 5 прерывания 21H - см. [6.3.1]), можно
заставить непрерывно проверять принтер на ошибку таймаута пос-
редством команды MODE. Перед загрузкой программы, использующей
функцию 5, надо ввести команду MODE LPT1: ,,P (еще лучше помес-
тить эту команду в файл AUTOEXEC.BAT, с тем чтобы она всегда
выполнялась при загрузке системы).
Все эти ошибки приводят к тому, что печать останавливается и
должны быть предприняты какие-то действия прежде чем она будет
продолжена. Слишком огорчительно для пользователя программы, если
большая порция документа должна будет печататься заново при воз-
никновении ошибки на принтере. Тщательное продумывание процедуры
восстановления по ошибке позволит программе возобновить печать с
начала той страницы, на которой произошла ошибка. Необходимо
всегда запоминать указатель выводимых данных при начале печати
новой страницы. При начале работы процедуры восстановления она
может попросить пользователя вставить новый лист бумаги, а затем
продолжить печать с начала той страницы, на которой произошла
ошибка.
Высокий уровень.
В Бейсике распознаются два ошибочных условия для принтера. Код
ошибки 24 возвращается когда был отменен выбор принтера, а код 27
- когда принтер выключен или в нем отсутствует бумага. Эти коды
можно получить с помощью техники обнаружения ошибок, приведенной
в [7.2.5]. К сожалению эффективно отлавливается только код 27.
Чтобы зарегистрировать код 24 требуется примерно полминуты, в
течение которых программа заморожена. Не слишком полезно прямо
читать регистр статуса перед каждой операцией печати. Этот метод
сработает перед началом печати, но ничем не поможет, если во
время печати произойдет отмена выбора принтера. Приводим процеду-
ру обработки ошибок принтера:
100 ON ERROR GOTO 1000 'устанавливаем обработку ошибок
.
.
1000 '''проверяем произошла ли ошибка на принтере
1010 IF ERR = 24 OR IF ERR = 27 THEN GOSUB 2000: RESUME
.
.
2000 BEEP: LOCATE 1,1: PRINT"Printer not ready"
2010 PRINT "Strike any key when ready"
2020 IF INKEY$ = "" THEN 2020 'ожидаем ввода
2030 RETURN
Средний уровень.
Когда функция 0 прерывания 17H выводит символ на принтер, то
она возвращает байт статуса принтера в AH. Проверяйте значение
этого байта после посылки каждого символа. BIOS слегка модифици-
рует байт статуса. Обычно бит 0 не имеет значения, но в данном
случае он устанавливается, когда происходит ошибка таймаута
(принтер не связан с машиной). В следующем примере проверяются
два типа ошибок: общая ошибка "принтер не готов" и ошибка "от-
сутствия бумаги". В примере предполагается, что в начале каждой
страницы (т.е. после каждого перевода формата) программа запоми-
нает указатель на начало выводимых данных, помещая его в перемен-
ную STARTING_PTR. Это позволяет программе при возникновении ошиб-
ки повторить печать с начала страницы, а не с начала всего доку-
мента. Конечно принтер должен быть повторно инициализирован перед
повторной печатью и должны быть восстановлены все его параметры.
(Данный пример просто иллюстрирует проверку ошибок - он ни в коей
мере не является рабочей процедурой.)
;---в сегменте данных
MESSAGE1 DB 'Printer off-line - strike any key when ready$'
MESSAGE2 DB 'Printer out of paper - strike any key when ready$'
;---посылаем символ и проверяем на ошибку
NEXT_CHAR: MOV AH,0 ;номер функции
MOV DX,0 ;выбираем LPT1
MOV AL,[BX] ;BX указывает на данные
INC BX ;увеличиваем указатель
INT 17H ;посылаем символ на принтер
TEST AH,00001000B ;выделяем бит 3 (флаг ошибки)
JZ NEXT_CHAR ;если нет ошибки, то печатаем дальше
TEST AH,00100000B ;выделяем бит 5 (отсутствие бумаги)
JZ OFF_LINE ;переход если с бумагой все в порядке
MOV AH,9 ;готовим печать сообщения
LEA DX,MESSAGE2 ;DS:DX указывает на строку
INT 21H ;выводим строку
JMP SHORT RECOVER ;уходим на восстановление
OFF_LINE: MOV AH,9 ;готовим печать сообщения
LEA DX,MESSAGE1 ;DS:DX указывают на строку
INT 21H ;выводим строку
RECOVER: MOV BX,STARTING_PTR ;восстанавливаем указатель
MOV AH,0 ;функция ожидания ввода
INT 16H ;ждем
CALL PRTR_INIT ;инициализация принтера
JMP NEXT_CHAR ;начинаем печать с начала страницы
6.1.4 Переключение между двумя или несколькими принтерами.
Компьютеры, оснащенные несколькими параллельными портами могут
иметь одновременно подсоединенными два или более принтеров. Вывод
может перенаправляться с одного принтера на другой двумя способа-
ми. Один способ состоит в том, чтобы использовать только такие
операторы вывода на печать, которые указывают на какой принтер
надо осуществлять вывод. Вы можете написать такой код, который
позволит Вам изменять спецификацию.
Второй способ переключения принтеров состоит в использовании
вывода по умолчанию на LPT1, но указания другого принтера, кото-
рый будет использоваться в качестве LPT1. Это достигается измене-
нием базового адреса, относящегося к LPT1. Этот базовый адрес
хранится в области данных BIOS в ячейке 0040:0008. Поменяйте его
с базовым адресом для LPT2 или 3 (хранящимися в ячейках 0040:000A
и 0040:000C) и в качестве LPT1 будет использоваться другой адап-
тер.
Высокий уровень.
В Бейсике, если принтер был открыт оператором OPEN "LPT1" AS
#1, то чтобы переключиться на другой принтер надо сначала напи-
сать оператор CLOSE #1, а затем открыть другой принтер с помощью
оператора OPEN "LPT2" AS #1. Впоследствии все операторы PRINT #1
будут направлять свой вывод на второй принтер. Это изменение
труднее осуществить в программах, использующих оператор LPRINT,
поскольку LPRINT по умолчанию посылает весь вывод на LPT1. В этом
случае Вам необходимо поменять базовые адреса принтеров. Следую-