Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Аппаратное обеспечение IBM PC

© Александр Фролов, Григорий Фролов
Том 2, книга 1, М.: Диалог-МИФИ, 1992.

[Назад] [Содеожание] [Дальше]

7.3. Средства BIOS для работы с принтером

BIOS использует для работы с принтером функции 0, 1, 2 прерывания INT 17h.

Функция 00h предназначена для печати одного символа:

На входе:       AH = 00h;

                AL = ASCII-код символа для печати;

                DX = номер принтера: 0, 1 или 2.

На выходе:      AH = слово состояния принтера (см. ниже).


Эта функция выводит на принтер один символ, заданный в регистре AL. В регистр DX необходимо записать номер используемого принтера, для LPT1 это 0, для LPT2 - 1 и т.д.

После выполнения прерывания регистр AH будет содержать слово состояния, имеющее следующий формат:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦ ¦ ¦ ¦ ¦ ¦   ¦ ¦
LT+T+T+T+T+T+T+T-
 ¦ ¦ ¦ ¦ ¦ L=¦ L= таймаут, слишком большая задержка при
 ¦ ¦ ¦ ¦ ¦   ¦    выполнении операции печати, возможно,
 ¦ ¦ ¦ ¦ ¦   ¦    что принтер неисправен;
 ¦ ¦ ¦ ¦ ¦   ¦
 ¦ ¦ ¦ ¦ ¦   L=== не используются;
 ¦ ¦ ¦ ¦ ¦
 ¦ ¦ ¦ ¦ L======= ошибка ввода/вывода;
 ¦ ¦ ¦ ¦
 ¦ ¦ ¦ L========= 1 - принтер выбран для работы;
 ¦ ¦ ¦            0 - принтер в состоянии offline;
 ¦ ¦ ¦
 ¦ ¦ L=========== конец бумаги;
 ¦ ¦
 ¦ L============= подтверждение;
 ¦
 L=============== 1 - принтер готов, 0 - принтер занят.


Вызвав функцию 0 прерывания INT 17h, программа должна проверить отдельные биты слова состояния и убедиться в том, что вывод байта произошел без ошибок. Наиболее часто оператор забывает перевести принтер в состояние ONLINE, либо вставить бумагу, либо вообще включить принтер. В этом случае целесообразно напомнить оператору о необходимости выполнения этих действий и затем повторить печать символа.

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

Обратите внимание на бит 1 байта состояния - таймаут. Если принтер находится в состоянии OFFLINE, функция 0 прерывания INT 17h ожидает некоторое время готовности принтера, после чего если принтер так и не перешел в состояние готовности, устанавливает бит 1 в байте состояния. Область данных BIOS по адресу 0000h:0478h содержит четыре байта, которые используются в качестве счетчиков времени при ожидании готовности принтера.

Прерывание INT 17h имеет еще две функции, выпоняющие инициализацию принтера и получающую текущее состояние принтера.

Функция 01h инициализирует принтер:

На входе:       AH = 01h;

                DX = номер принтера: 0, 1 или 2.

На выходе:      AH = слово состояния принтера.


Эта функция выполняет аппаратный сброс принтера. Если вы загрузили в принтер какой-либо шрифт (например, кириллицу), после сброса загрузку шрифта придется выполнять заново. Поэтому не следует выполнять сброс принтера, если это действительно не требуется. Обычно принтер приходится сбрасывать либо перед настройкой его на заданный режим работы, которая выполняется один раз, либо при изменении этого режима.

Слово состояния принтера может быть получено с помощью функции 02h:

На входе:       AH = 02h;

                DX = номер принтера: 0, 1 или 2.

На выходе:      AH = слово состояния принтера.


Эту функцию удобно использовать перед началом печати для определения готовности принтера к работе.

Приведем программу, которая распечатывает содержимое файла с использованием функции 0 прерывания INT 17h.

Программа считывает содержимое файла, открытого в двоичном режиме по байтам. Считанные файлы передаются в качестве параметра функции printchar(), которая и выводит их на принтер. После вызова прерывания INT 17h проверяется состояние принтера, и в случае, когда произошла ошибка ввода/вывода, вызывается обработчик ошибки - функция error(). Эта функция выводит на экран состояние принтера (в развернутом виде, с объяснением каждого бита байта состояния) и запрашивает оператора о дальнейших действиях.

Если оператор может устранить причину ошибки (перевести принтер в состояние ONLINE, вставить бумагу, если она кончилась и т.д.), он нажимает любую клавишу кроме ESC и тогда функция error() возвращает 0. В противном случае возвращается значение 1.

Если оператор решил повторить печать, и, соответственно, если функция error() возвратила значение 0, функция printchar() повторяет печать символа. В противном случае выдается сообщение об ошибке и работа программы завершается.

Итак, приведем исходный текст программы печати содержимого текстовых файлов:

#include <dos.h>
#include <stdio.h>


union REGS rg;

int main(int argc, char *argv[]) {

        FILE *srcfile;

// Открываем файл, заданный первым параметром
// в командной строке.
// Если при запуске программы оператор забыл
// указать имя файла, выводим напоминающее сообщение.

        if( (srcfile = fopen( argv[1], "rb" )) == NULL ) {
                printf("\nЗадайте имя файла в качестве параметра");
                exit(-1);
        }

// Читаем файл по одному символу, полученный из файла
// символ выводим на принтер при помощи функции printchar().

        for(;;) {
                printchar(fgetc(srcfile));
                if(feof(srcfile)) break;
        }

// Закрываем файл.

        fclose(srcfile);

}

// ------------------------------------
// Эта функция выводит один символ
// на первый принтер (LPT1)
// ------------------------------------


int printchar(int chr) {

        int status;

// Повторяем в цикле выдачу символа на принтер
// до тех пор, пока он не будет выведен без
// ошибок, либо пока оператор не отменит
// распечатку файла.

        for(;;) {

// Дублируем распечатываемый символ на экране

                putch(chr);

// Вызываем функцию 0 прерывания INT 17h -
// распечатка символа на принтере.
// В регистре DX задаем номер принтера LPT1 - это 0.

                rg.h.ah = 0;
                rg.h.al = chr;
                rg.x.dx = 0;

                int86(0x17, &rg, &rg);

// Запоминаем байт состояния принтера
// после вывода символа.

                status = rg.h.ah;

// Проверяем наличие ошибок. Нас интересуют биты:
//
//    0 - таймаут (задержка при печати слишком велика)
//    3 - ошибка ввода/вывода
//    4 - принтер в состоянии ONLINE (1) или OFFLINE (0)
//    5 - конец бумаги

                if((status & 0x39) != 0x10) {

// Вызываем функцию обработки ошибки error(). Эта
// функция возвращает 0, если оператор желает
// повторить печать символа, или 1 - если
// оператор отменяет печать.

                        if(error(chr, status)) {
                                printf("\nПечать завершилась аварийно");
                                exit(-2);
                        }
                }
                else break;
        }
}

// ------------------------------------
// Функция выводит на экран состояние
// принтера и запрашивает у оператора
// требуемые действия - повторить
// печать символа или отменить печать.
// ------------------------------------

int error(char chr, int status) {

// Выводим состояние принтера после ошибки

                printf("\nОшибка принтера %02.2X"
                "\n\nСостояние принтера:"
                  "\n-------------------", status);

                if(status & 1)
                        printf("\nТаймаут при печати");

                if(status & 8)
                        printf("\nОшибка ввода/вывода");

                if(!(status & 0x10))
                        printf("\nПринтер находится в состоянии OFFLINE");

                if(status & 0x20)
                        printf("\nКонец бумаги");

                printf("\n\nДля отмены печати нажмите клавишу ESC,"
                                "\nдля повтора - любую другую клавишу\n");

                if(getch() == 27) return(1);
                else return(0);

}


[Назад] [Содеожание] [Дальше]