Файл: jourdain_spravochnik_programmista.docx

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 04.07.2020

Просмотров: 3144

Скачиваний: 1

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

возвращает статусной информации и не позволяет назначать какой из

коммуникационных портов надо использовать (всегда используется

COM1).

Чтобы вывести строку данныз используйте функцию 40H прерывания

21H. Это обычная функция вывода для всех файлов и устройств при

использовании метода доступа дескриптора файлов. COM1 имеет пре-

лопределенный номер #3. Поместите номер файла в BX, а число пере-

даваемых байтов в CX. Пусть DS:DX указывают на буфер выводимых

данных и вызывайте функцию.


MOV AH,40H ;номер функции

MOV BX,3 ;предопределенный номер файла для COM1

MOV CX,50 ;выводим 50 байтов

LEA DX,DATA_BUFFER ;DS:DX указывают на буфер данных

INT 21H ;посылаем данные

JC COM_ERROR ;уход на обработку ошибки


Отметим, что при использовании предопределенных номеров файлов их

не надо открывать. Если произошла ошибка, то устанавливается флаг

переноса, а в AX возвращается 5 если коммуникационный порт не

готов и 6 при указании неверного номера файла.


Низкий уровень.


Когда байт данных помещается в регистр хранения передатчика,

то он автоматически выводится в последовательный канал через

регистр сдвига передатчика, который сериализует данные. Нет необ-

ходимости в импульсе бита строба, как это делается в случае па-

раллельного адаптера. Бит 5 регистра статуса линии показывает

свободен ли регистр хранения передатчика для приема данных. Ре-

гистр постоянно проверяется до тех пор, пока бит 5 не станет

равным 1. После этого в регистр хранения передатчика посылается

очередной байт из того места, откуда они берутся. В процессе

передачи бит 5 равен 0 и только когда он опять станет равным 1,

то в регистр хранения передатчика может быть послан следующий

символ. Этот процесс повторяется до тех пор, пока это нужно.

В следующем примере даны основные понятия об этой процедуре.

Конечно, она может быть сделана необычайно сложной (в частности,

программирование связи требует особо тщательных процедур обнару-

жения ошибок и восстановления при сбоях). В примере предполагает-

ся, что коммуникационный порт и модем уже инициализированы, как

показано в [7.1.2] и [7.1.5]. Первая часть это цикл проверки

ошибок и приема символов. В [7.1.7] приведен код для процедуры

приема данных.


;---ждем пока все будет готово для посылки символа

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 ;если нет, то возвращаемся назад

;---передаем символ принимаемый с клавиатуры

MOV AH,1 ;функция проверки нажатия клавиши

INT 16H ;прерывание клавиатуры BIOS

JZ KEEP_TRYING ;возврат, если не было нажатия


MOV AH,0 ;функция получения кода с клавиатуры

INT 16H ;теперь нужный символ в AL

SUB DX,5 ;адрес регистра хранения передатчика

OUT DX,AL ;посылаем символ

JMP SHORT KEEP_TRYING ;возвращаемся к началу цикла



7.1.7 Получение данных.




Коммуникационная программа готова принимать данные как только

инициализирован коммуникационный порт [7.1.2] и установлена связь

с удаленной станцией [7.1.5]. Прием данных никогда полностью не

отделен от передачи данных, поскольку программе может потребо-

ваться послать сигнал XOFF (ASCII 19), чтобы остановить поток

данных, если они поступают слишком быстро и она не успевает их

обрабатывать. Код XON (ASCII 17) сообщает удаленной станции, что

можно продолжить передачу. Отметим, что PCjr не может принимать

данные во время дисковых операций; чтобы снять это ограничение

можно использовать XON и XOFF.

В зависимости от сложности используемого протокола обмена,

принимаемые данные могут требовать простой или сложной обработки.

Может быть получен один из набора управляющих кодов, приведенных

в [7.1.9]. Те из них, которые являются ограничителями данных чаще

обнаруживаются при синхронном обмене. При выводе получаемых сим-

волов на экран учитывайте влияние символов перевода строки (ASCII

10), поскольку некоторые языки (включая Бейсик) автоматически

вставляют перевод строки после возврата каретки; в этом случае

исключайте переводы строки из принимаемых данных, чтобы избежать

пустых строк при выводе. На рис. 7-2 показана коммуникационная

процедура, включающая также код передачи, обсуждаемый в [7.1.6].


Высокий уровень.


Для коммуникационной процедуры, написанной на интерпретируемом

Бейсике, время очень существенно. Обработка медленна, поэтому

если процедура приема неверно сконструирована, то входной буфер

может заполниться (т.е. произойдет переполнение) в то время как

программа еще будет анализировать ранее полученные данные. Оче-

видным решением этой проблемы является максимально возможный

размер буфера. При загрузке Бейсика размер буфера ввода устанав-

ливается добавлением к команде ключа /C:. BASICA /C:1024 создает

буфер размером в 1K и это минимальное число для скорости обмена

1200 бод (сложным процедурам может понадобиться 4096 байт). По

умолчанию используется размер буфера равный 256 байтам и такой

буфер имеет то преимущество, что он может быть целиком помещен в

одну символьную переменную. Такой размер буфера можно использо-

вать только при скорости обмена 300 бод и ниже.

Бейсик читает из буфера с помощью оператора INPUT$ (можно



использовать также INPUT# и LINE INPUT#, но INPUT$ более гибок).

Этот оператор имеет форму INPUT$(числобайт,номерфайла). Например,

INPUT$(10,#1) читает 10 байтов из коммуникационного канала, отк-

рытого как файл #1. Если размер буфера не превышает 256 байтов,

то очень удобно читать все содержимое буфера за один раз. LOC


сообщает сколько байтов данных находится в буфере в данный мо-

мент. Поэтому напишите оператор INPUT$(LOC(1),#1) и в S$ будут

записаны все данные с момента последнего доступа к буферу. Конеч-

но, если LOC(1) = 0, то буфер пуст и процедура должна ожидать

пока данные будут получены. Отметим, что EOF(1) также можно ис-

пользовать для проверки состояния буфера, так как эта функция

возвращает -1 если буфер пуст и 0, если там есть хотя бы один

символ.

После того как данные записаны в S$ программа должна проверить

не содержатся ли там управляющие коды. Функция INSTR выполняет

эту задачу быстрее всего. Напомним, что ее параметрами являются

сначала позиция, с которой надо вести поиск в строке, затем имя

строки и, наконец, символ (или строка) который ищется. Чтобы

найти символ XOFF (ASCII 19) оператор должен иметь вид

INSTR(1,S$,CHR$(19)). Чтобы найти второе появление нужного управ-

ляющего символа повторите поиск в строке, начиная с символа,

следующего за позицией, в которой найден первый.

Обычно процедура ввода исключает большинство управляющих сим-

волов из принимаемых данных, с тем чтобы они нормально выглядели

при выводе. Затем данные выводятся на экран, пересылаются в дру-

гое место в памяти, а иногда записываются на диск или выводятся

на принтер. В процессе всей этой деятельности программа должна

постоянно возвращаться к просмотру не поступили ли новые данные.

Если оказалось, что буфер заполняется слишком быстро, то програм-

ма может послать сигнал XOFF, останавливая поток данных. Затем,

после того как полученные данные буду декодированы, можно снова

разрешить передачу данных. Конечно, необходимо чтобы протокол

обмена поддерживал XON и XOFF. Программы, написанные на интерпре-

тируемом Бейсике, обычно могут использовать XON/XOFF для установ-

ления соответствия скоростей при приеме данных, но при передаче

данных такая программа часто не может достаточно быстро отреаги-

ровать на получение сигнала XOFF.


.

.

500 '''здесь находится процедура передачи (см. [7.1.6])

.

.

600 IF LOC(1)>100 THEN XOFF = 1: PRINT #1,CHR$(19)

610 C$ = INPUT$(LOC(1),#1) 'читаем содержимое буфера

620 '''выделяем из данных управляющие символы

630 IF INSTR(1,C$,CHR$(19))>0 THEN 800 'получен XOFF

640 IF INSTR(1,C$,CHR$(17))>0 THEN 900 'получен XON

.

(здесь удаляются ненужные управляющие символы

.

700 PRINT C$ 'выводим данные на экран

710 IF LOC(1) > 0 THEN 600 'если получены данные, то читаем их



720 IF XOFF = 1 THEN XOFF = 0: PRINT #1,CHR$(17)

.

.

800 'реакция на XOFF

.

900 'реакция на XON


Если функция LOF применяется к коммуникационному порту, то она

возвращает количество свободного места, оставшееся в буфере вво-

да. Например, если COM1 открыт как #1, то LOF(1) сообщит свобод-

ного пространства. Это может быть полезно для определения, что

буфер почти полон. Отметим, однако, что оператор LOC возвращает

позицию указателя в буфере и это значение может быть использовано

для той же цели. Например, если COM1 открыт как #3, а размер


буфера ввода равен 256 байтам, то до тех пор, пока LOC(3) не

будет равен 256, буфер не полон.


Средний уровень.


Функция 2 прерывания 14H BIOS ожидает символ из последователь-

ного порта, помещает его в AL при получении и затем возвращается

в программу. При входе надо поместить номер порта (0-1) в DX. При

возврате AX равен нулю, если не было ошибки. Если AH не равен 0,

то может быть возвращен байт статуса, в котором имеют значение

только 5 битов. Это следующие биты:


бит 1 ошибка переполнения (новый символ поступил раньше, чем

был удален старый)

2 ошибка четности (вероятно, из-за проблем в линии)

3 ошибка оформления (стартовый или стоп-биты неверны)

4 обнаружен перерыв (получена длинная строка битов 0)

5 ошибка таймаута (не получен сигнал DSR)


MS DOS также предоставляет коммуникационную функцию для приема

одного символа, это функция 3 прерывания 21H. Функция ожидает

символ из COM1 и помещает его в AL. Отметим, что при этом нет

функции инициализации порта, которую надо делать через процедуру

BIOS или непосредственно, как показано в [7.1.2]. По умолчанию

порт инициализируется со значениями 2400 бод, нет контроля чет-

ности, один стоп-бит и 8 битов на символ. Эта функция не имеет

никаких достоинств по сравнению с функцией BIOS и не возвращает

информации о статусе.


Низкий уровень.


При получении данных без использования коммуникационного пре-

рывания [7.1.8] программа должна постоянно проверять регистр

статуса линии, адрес порта которого на 5 больше базового адреса

используемого коммуникационного адаптера. Бит 0 этого регистра

будет равен нулю, до тех пор пока не будет получен символ в ре-

гистр данных приемника. Когда бит 0 становится равным 1, то надо

немедленно считать его из регистра, с тем чтобы на него не нало-

жился следующий принимаемый символ. После того как символ считан,

бит 0 опять становится равным 0 и остается таковым, пока не при-



будет новый символ.

Хотя здесь об этом не говорилось, но коммуникационные процеду-

ры обычно создают циклический буфер для сбора поступающих симво-

лов. Циклические буфера обсуждались в [3.1.1]. Вы должны также

знать, что если поступающие данные подавать на экран со скоростью

1200 бод, то процедура сдвига экрана BIOS [4.5.1] не будет успе-

вать и произойдет переполнение. Простое решение этих проблем

состоит в использовании коммуникационного прерывания, как объяс-

нено в [7.1.8].

Следующий пример частично дублирует содержимое предыдущего

раздела, относящегося к передаче символов. Как и в том случае код

начинается с бесконечного цикла. Объедините эти 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 Посылка/получение данных с помощью коммуникационного

прерывания.




Хорошая коммуникационная программа имеет слишком много работы,

чтобы посвятить себя целиком вводу/выводу. Поступающие данные

должны анализироваться, передаваемые данные должны собираться, а

большие блоки данных могут записываться на диск или считываться с

него. Коммуникационное прерывание позволяет программе не тратить

на ввод/вывод больше времени, чем он того требует. Например,

после установки прерывания, управление передается процедуре пере-

дачи данныз только в том случае, когда регистр хранения передат-

чика пуст и возвращается программе, как только послан байт дан-

ных, позволяя ей продолжать свою работу до тех пор, пока регистр



хранения передатчика не будет снова готов. Не забудьте ознако-

миться с обсуждением прерываний в [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


Когда одно из этих событий происходит, то инициируется аппаратное

прерывание, возникающее в микросхеме обработки прерываний 8259 по

каналу 3 для COM1 и по каналу 4 для COM2. Процедура обработки