17.2. Низкоуровневые средства работы с принтером
Вывод данных или специальных командных кодов на принтер через связанный с ним файл Lst или ему подобный — не единственный способ управлять печатью. Существует и другой путь посылки символа или их последовательности в принтер — через прерывание БСВВ 17H. Кроме того, используя это прерывание, можно опрашивать состояние устройства печати.
Прерывание 17H обеспечивает доступ к трем функциям обслуживания принтера:
— печати символа на принтере (функция номер 0);
— инициализации порта принтера (функция номер 1);
— чтению состояния принтера (функция номер 2).
При вызове прерывания регистр процессора AH должен содержать номер функции, а регистр DX — номер параллельного порта (0 соответствует LPT1, 1 — LPT2, 2 — LPT3). При вызове функции 0 надо дополнительно загрузить в регистр AL ASCII-код посылаемого в принтер символа. Прерывание после выполнения всегда возвращает в регистре AH байт состояния принтера. Некоторое исключение составляет функция 0. Если она закончилась неудачей, то после небольшой задержки в регистре AH вернется значение 01H.
Наиболее полезна для программ, работающих с принтерами, функция номер 2, опрашивающая байт состояния принтера. Этот байт имеет следующую структуру (рис. 17.2).
Бит 7 — принтер занят (0) или ждет символ (READY) (1)
Бит 6 — если 1, то принтер подключен
Бит 5 — если 1, то кончилась бумага (PAPER OUT)
Бит 4 — если 1, то принтер в состоянии принять сигнал
Бит 3 — если 1, то ошибка ввода-вывода
Бит 2 — не используется (зарезервирован)
Бит 1 — не используется (зарезервирован)
Бит 0 — если 1, то задержка (timeout
Рис. 17.2
- 389 -
В специальной литературе оговаривается, что результаты опроса состояния принтера через прерывание 17H могут меняться на различных ПЭВМ и с различными принтерами. Это не значит, что прерывание нельзя использовать. Практически всегда должно выполняться условие возможности получения очередного символа на бумаге. Оно заключается в том, что перед выводом символа на печать биты 4 и 7 байта состояния принтера должны содержать единицы, т.е. в регистре AH после опроса должно быть значение 10H+80H=90H. Более «тонкие» проверки следует протестировать на конкретных ПЭВМ. На рис. 17.3 приводится пример функции опроса состояния принтера и связанной с ней процедуры печати файла из программы. В большинстве случаев эти подпрограммы должны работать корректно.
| DOS, CRT, Printer;
| { Функция возвращает код состояния принтера LPT1 (PRN).
| При работе требуется подключение модуля DOS. }
| FUNCTION TestPrinter : ShortInt;
| VAR
| R : Registers; { служебная переменная }
| BEGIN
| TestPrinter := 100; { исходное значение }
| R.AH:=$02; { функция номер 2 }
| R.DX:=$00; { принтер в LPT1 }
| Intr( $17, R ); { прерывание 17H }
| if (R.AH and $10) = $00 { проверка наличия }
| then begin
| TestPrinter := -1; { принтер не подключен }
| Exit { выход из функции }
| end;
| if (R.AH and $80) = $00 { проверка готовности: }
| then TestPrinter := 0 { подключен, но OFF LINE }
| else TestPrinter := +1; { подключен, и ON LINE }
| END;
{ Процедура печатает файл FileName на принтере, подключенном к LPT1, анализируя состояние принтера. Можно прервать процедуру, нажав клавишу Esc. X и Y - координаты сообщения на экране. Для работы нужны модули Printer и CRT. }
Рис. 17.3
- 390 -
| PROCEDURE PrintFile( X, Y : Byte; FileName : String );
| LABEL
| mStop; { метка выхода no Esc }
| VAR
| f : Text; s : String; { служебные переменные }
| Т : ShortInt; { результат опроса принтера }
| BEGIN
| REPEAT { цикл опроса состояния LPT1 }
| Т := TestPrinter; { см. предыдущую страницу }
| if KeyPressed { опрос клавиш }
| then if ReadKey=#27 then
| Exit; { Esc – выход }
| GotoXY( X,Y );
| case Т of { анализ LPT1: }
| -1 : Write( ' ПРИНТЕР НЕ ПОДКЛЮЧЕН...' );
| 0 : Write( ' НАЖМИТЕ <ON LINE> !... ');
| +1 : Write( ' РЕЗУЛЬТАТЫ ВЫВОДЯТСЯ... ' );
| else Write( ' ПРОБЛЕМЫ С ПРИНТЕРОМ... ' );
| end;
| Write( ' (ОТКАЗ - Esc)' );
| UNTIL ( T=1 ); { при Т=1 уже можно печатать }
| Assign( f, FileName ); { связывание файла FileName }
| Reset( f ); { открытие его для чтения }
| while not EOF(f) do begin { печать файла по строкам }
| ReadLn( f, s ); { чтение строки }
| if KeyPressed then { опрос клавиш }
| if ReadKey=#27 then
| Goto mStop; { Esc – выход }
| WriteLn( 1st, s ) { печать строки }
| end; {while} { конец цикла печати файла }
| mStop : Close( f ) { закрытие файла FileName }
| END;
| BEGIN
| PrintFile(10,10, 'ris17-3.pas'); { печать текст-файла }
| END.
Рис.17.3 (Окончание)