[Назад] [Далее]

4.7.2. Последовательный порт

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

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:
    000 — 19 200 бод (110 бод без FOSSIL)
    001 — 38 400 бод (150 бод без FOSSIL)
    010 — 300 бод
    011 — 600 бод
    100 — 1200 бод
    101 — 2400 бод
    110 — 4800 бод
    111 — 9600 бод
биты 4 – 3: четность (01 — четная, 11 — нечетная, 00 или 10 — нет)
бит 2: число стоп-бит (0 — один, 1 — два)
биты 1 – 0: длина слова (00 — 5, 01 — 6, 10 — 7, 11 — 8)
DX = номер порта (00h – 03h)
Вывод: АН = состояние порта
    бит 7: тайм-аут
    бит 6: буфер вывода пуст (без FOSSIL: регистр сдвига передатчика пуст)
    бит 5: в буфере вывода есть место (без FOSSIL: регистр хранения передатчика пуст)
    бит 4: обнаружено состояние BREAK
    бит 3: ошибка синхронизации
    бит 2: ошибка четности
    бит 1: ошибка переполнения — данные потеряны
    бит 0: в буфере ввода есть данные
AL = состояние модема
    бит 7: обнаружена несущая (состояние линии DCD)
    бит 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. Более эффективным оказывается подход, состоящий в перехвате прерываний от внешних устройств, о котором рассказано далее.


п»ї
"target=_blank><\/a>") //-->