Справочник программиста на персональном компьютере фирмы IBM. Принтер
Страница 4. Интерпретация  ошибок принтера и  восстановление  после них


     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          ;начинаем печать с начала страницы

 
« Предыдущая статья   Следующая статья »