|
[Назад] [Далее] | |
Каждый компьютер обычно оборудован, по крайней мере, двумя последовательными портами, которые чаще всего используются для подключения мыши и модема, но также могут использоваться и для подключения других дополнительных устройств или соединения компьютеров между собой. Для работы с устройствами, подключенными к портам, такими как мышь, используются драйверы, которые общаются с последовательным портом непосредственно на уровне портов ввода-вывода и предоставляют программам некоторый набор функций более высокого уровня, так что прямая работа с последовательными портами оказывается необходимой только при написании таких драйверов, работе с нестандартными устройствами или с модемами.
DOS всегда инициализирует первый порт СОМ1 как 2400 бод, 8N1 (8 бит в слове, 1 стоп-бит, четность не проверяется) и связывает с ним устройство STDAUX. В это устройство можно записывать и считывать один байт функциями 3 и 4.
Функция DOS 03h — Считать байт из STDAUX
Ввод: | АН = 03h |
Вывод: | AL = считанный байт |
Функция DOS 04h — Записать байт в STDAUX
Ввод: | АН = 04h DL = байт |
Или же можно воспользоваться функциями записи в файл (40h) и чтения из файла (3Fh), поместив в ВХ число 3, как это было показано ранее для вывода на экран.
Хотя установленную DOS скорость работы порта (2400 бод) и можно изменить командой MODE, все равно отсутствие обработки ошибок, буферизации и гибкого управления состоянием порта делает эти функции DOS практически неприменимыми. BIOS позволяет управлять любым из портов, писать и читать один байт и считывать состояние порта с помощью функций прерывания 14h, но BIOS (так же как и DOS) не позволяет инициализировать порт на скорость выше, чем 9600 бод. Таким образом выясняется, что большинство программ вынуждено программировать порты напрямую, но, если в системе присутствует драйвер, предоставляющий набор сервисов FOSSIL (такие как Х00 или BNU), оказывается возможным пользоваться для полноценного буферированного обмена данными с последовательными портами только функциями прерывания 14h.
INT 14h АН = 04 — Инициализация FOSSIL-драйвера
Ввод: | АН = 04h DX = номер порта (0 — для СОМ1, 1 — для COM2 и т.д.) |
Вывод: | АХ = 1954h BL = максимальный поддерживаемый номер функции ВН = версия спецификации FOSSIL |
INT 14h АН = 05 — Деинициализация FOSSIL-драйвера
Ввод: | АН = 05h DX = номер порта (00h – 03h) |
INT 14h АН = 00 — Инициализация последовательного порта
Ввод: | АН = 00h AL = параметры инициализации: биты 7 – 5:
001 — 38 400 бод (150 бод без FOSSIL) 010 — 300 бод 011 — 600 бод 100 — 1200 бод 101 — 2400 бод 110 — 4800 бод 111 — 9600 бод бит 2: число стоп-бит (0 — один, 1 — два) биты 1 – 0: длина слова (00 — 5, 01 — 6, 10 — 7, 11 — 8) DX = номер порта (00h – 03h) |
Вывод: | АН = состояние порта
бит 6: буфер вывода пуст (без FOSSIL: регистр сдвига передатчика пуст) бит 5: в буфере вывода есть место (без FOSSIL: регистр хранения передатчика пуст) бит 4: обнаружено состояние BREAK бит 3: ошибка синхронизации бит 2: ошибка четности бит 1: ошибка переполнения — данные потеряны бит 0: в буфере ввода есть данные
бит 6: обнаружен звонок (состояние линии RI) бит 5: запрос для передачи (состояние линии DSR) бит 4: сброс для передачи (состояние линии CTS) бит 3: линия DCD изменила состояние бит 2: линия RI изменила состояние бит 1: линия DSR изменила состояние бит 0: линия CTS изменила состояние |
INT 14h АН =01 — Запись символа в последовательный порт
Ввод: | АН = 01h AL = символ DX = номер порта (00h – 03h) |
Вывод: | АН = состояние порта |
INT 14h АН = 02 — Чтение символа из последовательного порта с ожиданием
Ввод: | АН = 02h DX = номер порта |
Вывод: | АН = состояние порта AL = считанный символ, если бит 7 АН равен нулю (не было тайм-аута) |
INT 14h AH = 03 — Получить текущее состояние порта
Ввод: | АН = 03h DX = номер порта (00h – 03h) |
Вывод: | АН = состояние линии AL = состояние модема |
Воспользуемся этими функциями, чтобы написать короткую терминальную программу:
; term.asm ; Простая терминальная программа для модема на COM2. Выход по Alt-X ; .model tiny .code org 100h ; Начало СОМ-файла start: mov ah,0 ; инициализировать порт mov al,11100011b ; 9600/8n1 mov dx,1 ; порт COM2 int 14h main_loop: mov ah,2 int 14h ; получить байт от модема, test ah,ah ; если что-нибудь получено, jnz no_input int 29h ; вывести его на экран no_input: ; иначе: mov ah,1 int 16h ; проверить, была ли нажата клавиша, jz main_loop ; если да: mov ah,8 int 21h ; считать ее код (без отображения на экране), test al,al ; если это нерасширенный ASCII-код, jnz send_char ; перейти к посылке его в модем, int 21h ; иначе - получить расширенный ASCII-код, cmp al,2Dh ; если это Alt-X, jne send_char ret ; завершить программу send_char: mov ah, 1 int 14h ; послать введенный символ в модем jmp short main_loop ; продолжить основной цикл end start
Этот терминал тратит чрезмерно много процессорного времени на постоянные вызовы прерываний 14h и 16h. Более эффективным оказывается подход, состоящий в перехвате прерываний от внешних устройств, о котором рассказано далее.