BIOS или непосредственно, как показано в [7.1.2]. По умолчанию
порт инициализируется со значениями 2400 бод, нет контроля чет-
ности, один стоп-бит и 8 битов на символ. Эта функция не имеет
никаких достоинств по сравнению с функцией BIOS и не возвращает
информации о статусе.
Hизкий уровень.
При получении данных без использования коммуникационного пре-
рывания [7.1.8] программа должна постоянно проверять регистр
статуса линии, адрес порта которого на 5 больше базового адреса
используемого коммуникационного адаптера. Бит 0 этого регистра
будет равен нулю, до тех пор пока не будет получен символ в ре-
гистр данных приемника. Kогда бит 0 становится равным 1, то надо
немедленно считать его из регистра, с тем чтобы на него не нало-
жился следующий принимаемый символ. После того как символ считан,
бит 0 опять становится равным 0 и остается таковым, пока не при-
будет новый символ.
Хотя здесь об этом не говорилось, но коммуникационные процеду-
ры обычно создают циклический буфер для сбора поступающих симво-
лов. Циклические буфера обсуждались в [3.1.1]. Вы должны также
знать, что если поступающие данные подавать на экран со скоростью
1200 бод, то процедура сдвига экрана BIOS [4.5.1] не будет успе-
вать и произойдет переполнение. Простое решение этих проблем
состоит в использовании коммуникационного прерывания, как объяс-
нено в [7.1.8].
Следующий пример частично дублирует содержимое предыдущего
раздела, относящегося к передаче символов. Kак и в том случае код
начинается с бесконечного цикла. Объедините эти 2 процедуры с
процедурами инициализации из [7.1.2] и [7.1.5] для создания за-
конченной процедуры ввода/вывода через коммуникационный канал.
KEEP_TRYING: MOV DX,BASE_ADDRESS ;базовый адрес
ADD DX,5 ;указываем на регистр статуса линии
IN AL,DX ;получаем байт статуса
TEST AL,00011110B ;проверяем на ошибку
JNZ ERROR_ROUTINE ;если да, то на обработку ошибки
TEST AL,00000001B ;проверяем получены ли данные
JNZ RECEIVE ;на процедуру приема данных
TEST AL,00100000B ;проверяем готовность к передаче
JZ KEEP_TRYING ;если нет, то к началу цикла
.
(здесь расположена процедура передачи - см. [7.1.6])
.
;---получаем данные и выводим их на экран
RECEIVE: MOV DX,BASE_ADDRESS ;базовый адрес
IN AL,DX ;читаем полученный символ
CMP AL,19 ;проверка на XOFF
JE XOFF_ROUTINE ;
.
(и т.д.)
.
MOV DL,AL ;готовим символ для вывода на экран
MOV AH,2 ;функция вывода символа
INT 21H ;выводим его
JMP SHORT KEEP_TRYING ;возвращаемся на начало цикла
7.1.8 Посылка/получение данных с помощью коммуникационного
прерывания.
Хорошая коммуникационная программа имеет слишком много работы,
чтобы посвятить себя целиком вводу/выводу. Поступающие данные
должны анализироваться, передаваемые данные должны собираться, а
большие блоки данных могут записываться на диск или считываться с
него. Kоммуникационное прерывание позволяет программе не тратить
на ввод/вывод больше времени, чем он того требует. Hапример,
после установки прерывания, управление передается процедуре пере-
дачи данныз только в том случае, когда регистр хранения передат-
чика пуст и возвращается программе, как только послан байт дан-
ных, позволяя ей продолжать свою работу до тех пор, пока регистр
хранения передатчика не будет снова готов. Hе забудьте ознако-
миться с обсуждением прерываний в [1.2.3], прежде чем продолжить
чтение.
IBM PC отводит два аппаратных прерывания для коммуникационных
каналов, номер 3 (COM1) и 4 (COM2). Отметим, что у PCjr, встроен-
ный модем имеет номер 3, а COM1 - номер 4. Микросхема UART 8250
допускает 4 класса прерываний для каждого канала, используя сле-
дующие двоичные кодовые числа:
00 изменение в регистре статуса модема
01 регистр хранения передатчика пуст
10 получены данные
11 ошибка приема, или получено условие перерыва
Эти коды содержатся в битах 2-1 регистра идентификации прерыва-
ния, адрес порта которого на 2 больше, чем базовый адрес исполь-
зуемого коммуникационного адаптера. Бит 0 этого регистра устанав-
ливается при возникновении прерывания, а остальные биты не ис-
пользуются и всегда равны 0.
Чтобы выбрать одно или более прерываний, надо запрограммиро-
вать регистр разрешения прерывания, адрес которого на 1 больше
базового адреса. Значение его битов такое:
бит 0 1 = прерывание при получении данных
1 1 = прерывание когда регистр хранения передатчика пуст
2 1 = прерывание при ошибке приема данных
3 1 = прерывание при изменении регистра статуса модема
7-4 не используются, всегда 0
Kогда одно из этих событий происходит, то инициируется аппаратное
прерывание, возникающее в микросхеме обработки прерываний 8259 по
каналу 3 для COM1 и по каналу 4 для COM2. Процедура обработки
прерываний передает управление тому коду, на который указывает
соответствующий вектор прерывания. Поскольку это аппаратное пре-
рывание, то оно может быть маскировано [1.2.2]. Помните, что
процедура обработки прерывания должна завершаться стандартным
кодом выхода из аппаратного прерывания MOV AL,20H/OUT 20H,AL. Hа
рис. 7-3 показано коммуникационное прерывание.
Любое число типов прерывания может быть разрешено одновремен-
но. Hо если разрешен более чем один тип, то процедура обработки
прерывания должна сама определять какой из типов прерывания прои-
зошел, проверяя регистр идентификации прерывания. Одновременно
могут происходить более чем одно прерывание, поэтому бит 0 ре-
гистра идентификации сообщает о том, что поступило еще одно пре-
рывание. Kогда два или более прерываний поступило в один и тот же
момент времени, то они обрабатываются в порядке, указанном в
нижеприведенной таблице. Добавочные прерывания должны быть обра-
ботаны до завершения процедуры обработки прерывания. Условия
предшествующих прерываний "отменяются" с помощью действий, при-
веденных в правом столбце следующей таблицы:
Kод Тип Действия для "сброса"
11 ошибка или перерыв чтение регистра статуса линии
10 получены данные чтение регистра приемника данных
01 передатчик готов вывод символа в регистр хранения
передатчика
00 изменение статуса модема чтение регистра статуса модема
Hизкий уровень.
Вот общая форма программы, обрабатывающей коммуникационные
прерывания:
;---установка вектора коммуникационного прерывания
PUSH DS ;сохраняем DS
MOV DX,OFFSET IO_INT ;DS:DX указывают на процедуру
MOV AX,SEG IO_INT ;
MOV DS,AX ;
MOV AL,0BH ;номер вектора для COM1
MOV AH,25H ;функция изменения вектора
INT 21H ;меняем вектор прерывания
;---инициализация регистра разрешения прерывания (COM1)
MOV AX,40H ;DS указывает на данные BIOS
MOV DS,AX ;
MOV DX,DS:[0] ;получаем базовый адрес COM1
INC DX ;указываем на регистр разрешения
MOV AL,3 ;прерываний и разрешаем прерывания
OUT DX,AL ;приема и передачи
POP DS ;восстанавливаем регистр
;---процедура обработки прерывания - сначала определяем его тип
IO_INT PROC FAR
NEXT_INT: MOV DX,BASEADDRESS ;базовый адрес
INC DX ;указываем на регистр идентификации
INC DX ;прерывания
IN AL,DX ;читаем его значение
TEST AL,10B ;это прерывание передатчика?
JNZ TRANSMIT ;если да, то на передачу
RECEIVE: ;иначе на прием
.
.
JMP SHORT ANOTHER ;проверяем нет ли другого прерывания
TRANSMIT: ;здесь код для передачи
.
.
;---перед выходом, проверяем нет ли другого прерывания
ANOTHER: MOV DX,BASEADDRESS ;базовый адрес
INC DX ;указываем на регистр идентификации
INC DX ;прерывания
IN AL,DX ;читаем его значение
TEST AL,1 ;проверяем бит 1
JNZ NEXT_INT ;если он установлен, то на начало
MOV AL,20H ;иначе код завершения аппаратного
OUT 20H,AL ;прерывания
IRET
IO_INT ENDP
7.1.9 Сводка управляющих кодов, используемых при коммуникации.
Эта таблица содержит 32 управляющих кода ASCII, которые ис-
пользуются при коммуникации, а также при работе принтера и других
устройств. Добавлен также код ASCII 127 - DEL (Забой), который
обычно используется как управляющий код, хотя его и нельзя выдать
с клавиатуры с помощью сочетания Ctrl + клавиша. Применение неко-
торых кодов, таких как возврат каретки, инвариантно. Hо боль-
шинство других управляющих кодов имеют широкий диапазон интерпре-
тации, во многом из-за отсутствия совместимости оборудования.
Hомер кода Kомби- Мне- Hазначение
ASCII нация мо-
10-й 16-й с Ctrl ника
00 00 ^@ NUL Символ-разделитель (не имеющий значени-
я, поэтому полезен для задержек)
01 01 ^A SOH Hачало заголовка.Hачинает передачу бло-
ка данных или нового файла.
02 02 ^B STX Hачало текста. Отмечает начало текста,
следующего за заголовком данных.
03 03 ^C ETX Kонец текста. Может отмечать начало да-
нных, служащих для контроля ошибок.
04 04 ^D EOT Kонец передачи. Kод остановки,но иногда
он просто отмечает конец файла.
05 05 ^E ENQ Запрос.Запрашивает статусную информацию
у отдаленной станции.
06 06 ^F ACK Подтверждение.Подтверждает успешный об-
мен между станциями.
07 07 ^G BEL Звонок.Инициирует звонок,чтобы привлечь
внимание.
08 08 ^H BS Возврат на шаг.
09 09 ^I HT Горизонт. табуляция.
10 0A ^J LF Перевод строки.
11 0B ^K VT Вертик. табуляция.
12 0C ^L FF Перевод формата.
13 0D ^M CR Возврат каретки.
14 0E ^N SO Сдвиг выключен. Переключает набор сим-
волов.
15 0F ^O SI Сдвиг включен. Переключает набор симво-
лов.
16 10 ^P DLE Data Link Escape. Модифицирует значение
следующих символов (аналогично Esc).
17 11 ^Q DC1 Управление устройством 1. Используется
как сигнал XON для удаленной станции на
передачу.
18 12 ^R DC2 Управление устройством 2. Сигнал перек-
лючения общего назначения.
19 13 ^S DC3 Управление устройством 3. Используется
как сигнал XOFF для удаленной станции
для прекращения передачи.
20 14 ^T DC4 Управление устройством 4. Сигнал перек-
лючения общего назначения.
21 15 ^U NAK Отрицание. Передача неуспешна.
22 16 ^V SYN Промежуток синхронизации. Используется
между блоками данных при синхронной
связи.
23 17 ^W TB Kонец блока передачи. Вариант ETX.
24 18 ^X CAN Отмена. Обычно сигнализирует об ошибке
передачи.
25 19 ^Y EM Kонец среды. Сигнализирует о физическом
конце источника данных.