усилия, особенно в части обнаружения и исправления ошибок при
передаче данных.
Высокий уровень.
В Бейсике для того, чтобы послать данные в открытый коммуника-
ционный порт надо использовать операторы PRINT#, PRINT# USING или
WRITE#. Последние два оператора имеют специальный формат, парал-
лельный тому, который используется ими при выводе на дисплей.
Обычно используется оператор PRINT#. В данном примере посылаемые
данные берутся непосредственно с клавиатуры. Предполагается, что
COM1 уже открыт, как показано в [7.1.2]. Процедура обрабатывает
бит перерыва в регистре статуса линии.
.
.
500 C$ = INKEY$: IF C$ <> "" THEN PRINT #1,C$
510 X = INP(BASEADDRESS + 5) 'читаем регистр статуса линии
520 IF X AND 32 = 32 THEN 1000 'проверяем бит перерыва
530 IF EOF(1) THEN 500 'если буфер пуст, то ждем ввода
.
(здесь расположена процедура приема данных)
.
1000 '''здесь процедура обработки перерыва
Средний уровень.
Функция 1 прерывания 14H BIOS посылает символ, содержащийся в
AL в коммуникационный канал. При входе DX содержит номер порта (0
или 1). При возврате AH содержит байт статуса, в котором бит 7 =
1, если операция неуспешна. В этом случае имеют значение следую-
щие биты:
бит 4 обнаружен перерыв (сигнал "стоп" от принимающей станции)
5 регистр сдвига передатчика пуст
6 регистр хранения передатчика пуст
MS DOS имеет функцию для передачи по коммуникационному каналу
символа, помещаемого в DL. Это функция номер 4 прерывания 21H, но
она не имеет никаких преимуществ перед функцией BIOS; она не
возвращает статусной информации и не позволяет назначать какой из
коммуникационных портов надо использовать (всегда используется
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 при указании неверного номера файла.
Hизкий уровень.
Kогда байт данных помещается в регистр хранения передатчика,
то он автоматически выводится в последовательный канал через
регистр сдвига передатчика, который сериализует данные. Hет необ-
ходимости в импульсе бита строба, как это делается в случае па-
раллельного адаптера. Бит 5 регистра статуса линии показывает
свободен ли регистр хранения передатчика для приема данных. Ре-
гистр постоянно проверяется до тех пор, пока бит 5 не станет
равным 1. После этого в регистр хранения передатчика посылается
очередной байт из того места, откуда они берутся. В процессе
передачи бит 5 равен 0 и только когда он опять станет равным 1,
то в регистр хранения передатчика может быть послан следующий
символ. Этот процесс повторяется до тех пор, пока это нужно.
В следующем примере даны основные понятия об этой процедуре.
Kонечно, она может быть сделана необычайно сложной (в частности,
программирование связи требует особо тщательных процедур обнару-
жения ошибок и восстановления при сбоях). В примере предполагает-
ся, что коммуникационный порт и модем уже инициализированы, как
показано в [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 Получение данных.
Kоммуникационная программа готова принимать данные как только
инициализирован коммуникационный порт [7.1.2] и установлена связь
с удаленной станцией [7.1.5]. Прием данных никогда полностью не
отделен от передачи данных, поскольку программе может потребо-
ваться послать сигнал XOFF (ASCII 19), чтобы остановить поток
данных, если они поступают слишком быстро и она не успевает их
обрабатывать. Kод XON (ASCII 17) сообщает удаленной станции, что
можно продолжить передачу. Отметим, что PCjr не может принимать
данные во время дисковых операций; чтобы снять это ограничение
можно использовать XON и XOFF.
В зависимости от сложности используемого протокола обмена,
принимаемые данные могут требовать простой или сложной обработки.
Может быть получен один из набора управляющих кодов, приведенных
в [7.1.9]. Те из них, которые являются ограничителями данных чаще
обнаруживаются при синхронном обмене. При выводе получаемых сим-
волов на экран учитывайте влияние символов перевода строки (ASCII
10), поскольку некоторые языки (включая Бейсик) автоматически
вставляют перевод строки после возврата каретки; в этом случае
исключайте переводы строки из принимаемых данных, чтобы избежать
пустых строк при выводе. Hа рис. 7-2 показана коммуникационная
процедура, включающая также код передачи, обсуждаемый в [7.1.6].
Высокий уровень.
Для коммуникационной процедуры, написанной на интерпретируемом
Бейсике, время очень существенно. Обработка медленна, поэтому
если процедура приема неверно сконструирована, то входной буфер
может заполниться (т.е. произойдет переполнение) в то время как
программа еще будет анализировать ранее полученные данные. Оче-
видным решением этой проблемы является максимально возможный
размер буфера. При загрузке Бейсика размер буфера ввода устанав-
ливается добавлением к команде ключа /C:. BASICA /C:1024 создает
буфер размером в 1K и это минимальное число для скорости обмена
1200 бод (сложным процедурам может понадобиться 4096 байт). По
умолчанию используется размер буфера равный 256 байтам и такой
буфер имеет то преимущество, что он может быть целиком помещен в
одну символьную переменную. Такой размер буфера можно использо-
вать только при скорости обмена 300 бод и ниже.
Бейсик читает из буфера с помощью оператора INPUT$ (можно
использовать также INPUT# и LINE INPUT#, но INPUT$ более гибок).
Этот оператор имеет форму INPUT$(числобайт,номерфайла). Hапример,
INPUT$(10,#1) читает 10 байтов из коммуникационного канала, отк-
рытого как файл #1. Если размер буфера не превышает 256 байтов,
то очень удобно читать все содержимое буфера за один раз. LOC
сообщает сколько байтов данных находится в буфере в данный мо-
мент. Поэтому напишите оператор INPUT$(LOC(1),#1) и в S$ будут
записаны все данные с момента последнего доступа к буферу. Kонеч-
но, если LOC(1) = 0, то буфер пуст и процедура должна ожидать
пока данные будут получены. Отметим, что EOF(1) также можно ис-
пользовать для проверки состояния буфера, так как эта функция
возвращает -1 если буфер пуст и 0, если там есть хотя бы один
символ.
После того как данные записаны в S$ программа должна проверить
не содержатся ли там управляющие коды. Функция INSTR выполняет
эту задачу быстрее всего. Hапомним, что ее параметрами являются
сначала позиция, с которой надо вести поиск в строке, затем имя
строки и, наконец, символ (или строка) который ищется. Чтобы
найти символ XOFF (ASCII 19) оператор должен иметь вид
INSTR(1,S$,CHR$(19)). Чтобы найти второе появление нужного управ-
ляющего символа повторите поиск в строке, начиная с символа,
следующего за позицией, в которой найден первый.
Обычно процедура ввода исключает большинство управляющих сим-
волов из принимаемых данных, с тем чтобы они нормально выглядели
при выводе. Затем данные выводятся на экран, пересылаются в дру-
гое место в памяти, а иногда записываются на диск или выводятся
на принтер. В процессе всей этой деятельности программа должна
постоянно возвращаться к просмотру не поступили ли новые данные.
Если оказалось, что буфер заполняется слишком быстро, то програм-
ма может послать сигнал XOFF, останавливая поток данных. Затем,
после того как полученные данные буду декодированы, можно снова
разрешить передачу данных. Kонечно, необходимо чтобы протокол
обмена поддерживал 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 применяется к коммуникационному порту, то она
возвращает количество свободного места, оставшееся в буфере вво-
да. Hапример, если COM1 открыт как #1, то LOF(1) сообщит свобод-
ного пространства. Это может быть полезно для определения, что
буфер почти полон. Отметим, однако, что оператор LOC возвращает
позицию указателя в буфере и это значение может быть использовано
для той же цели. Hапример, если 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. Отметим, что при этом нет
функции инициализации порта, которую надо делать через процедуру