Коммуникационная программа
Теперь мы приступим к самому интересному - приведем подробный алгоритм коммуникационной программы, а затем - исходный текст такой программы.
Сначала мы рассмотрим вариант коммуникационной программы без использования прерываний от асинхронного порта. Этот вариант несколько проще, так как нам не надо создавать довольно нетривиальный обработчик для этого прерывания, а также программировать контроллер прерываний.
Итак, приступим. Как мы сказали ранее, первым шагом при программировании модема надо считать инициализацию COM-порта (микросхемы UART), к которому подключен модем.
Программа, представленная в предыдущей главе, имеет один большой недостаток: она должна постоянно выполнять опрос регистра состояния линии с тем, чтобы определить момент, когда от модема поступит очередной символ. В результате становится трудной, а иногда невозможной, обработка поступающих символов. Например, если вы сразу отображаете символы, получаемые от COM-порта, на экране, то при использовании для этого функции putch отдельные символы могут быть потеряны. Дело в том, что функция putch работает слишком медленно и на скоростях 2400 бит/с и выше модем может успеть передать в COM-порт несколько новых символов, в то время как функция putch еще не вывела на экран ни одного символа. В этом случае происходит ошибка переполнения входного буфера микросхемы UART (см. бит D2 регистра состояния линии).
Таким образом, имеет смысл организовать прием и передачу символов модему в фоновом режиме, используя прерывания по окончании приема и передачи символа.
printf("\nFOSSIL-драйвер неустановлен\n");
exit(-1);
}
// Определяем возможность эмуляции FOSSIL-драйвером
// протокола MNP
_asm {
mov ah,0E0h
mov al,6h
xor bx,bx
int 14h
mov signatura,bx
}
mnp = ( signatura != 0x4D58 ) ? 0 : 1;
printf("Эмуляция MNP %s.\n\n", (mnp) ? "поддерживается"
: "не поддерживается");
if(mnp)
printf("PageUp - режим вызова, "
"PageDown - режим ответа\n\n");
_asm {
// Устанавливаем скорость обмена и формат данных
xor ah,ah
mov al,0A3h
mov dx,com_port_num
int 14h
// Устанавливаем сигнал DTR в активное состояние
mov ah,6
mov al,1
mov dx,com_port_num
int 14h
// Запрещаем использование режима управления потоком
mov ah,0Fh
xor al,al
mov dx,com_port_num
int 14h
}
// Начинаем обмен данными между компьютером и модемом
do_chat();
}
//********************************************************
// Функция do_chat
//********************************************************
void do_chat( void ) {
while(1) {
unsigned char key,stey;
unsigned i,j;
// Если пользователь нажал на клавиатуру, получаем код
// нажатого символа и передаем его модему
if( kbhit() ) {
key = getch();
if(( key == 0 ) && mnp) {
key = getch();
if( key == 73 ) origin();
else if( key == 81 ) answer();
continue;
}
// По нажатию клавиши Esc выходим из программы
if( key == 27 ) {
_asm {
// Сбрасываем сигнал DTR
mov ah,06h
xor al,al
mov dx,com_port_num
int 14h
// Отключаем FOSSIL-драйвер
mov ah,05h
mov dx,com_port_num
int 14h
}
return;
}
// Если нажата клавиша Enter переводим строку
if( key == '\r' ) {
key = 13;
putch('\n');
}
// Выводим ASCII код нажатого на клавиатуре символа
// на экран
putch(key);
// Передаем ASCII код нажатого на клавиатуре символа
// FOSSIL-драйверу, для дальнейшей передачи его модему
_asm {
mov dx,com_port_num
mov ah,1
mov al,key
int 14h
}
}
// Определяем состояние приемного буфера FOSSIL-драйвера
_asm {
mov dx,com_port_num
mov ah,3
int 14h
and ah,01h
mov stey,ah
}
// Если приемный буфер содержит данные, выводим их
// на экран дисплея
if( stey > 0 ) {
_asm {
mov dx,com_port_num
mov ah,2
int 14h
mov stey,al
}
putch(stey);
}
}
}
//********************************************************
// Функция help
//********************************************************
void help( void ) {
printf(" Неправильно задан параметр программы \n"
"FOSSILEX n, где n - номер порта от 0 до 3\n");
exit(0);
}
//********************************************************
// Функция origin
//********************************************************
void origin(void) {
// Переключаем эмулятор MNP в режим вызова удаленного модема
_asm {
mov ah,0E0h
mov al, 2
mov bl,0
mov bh,1
mov dx,com_port_num
int 14h
}
putch(7);
}
//********************************************************
// Функция answer
//********************************************************
void answer(void){
// Переключаем эмулятор MNP в режим ответа на
// вызов удаленного модема
_asm {
mov ah,0E0h
mov al,2
mov bl,1
mov bh,1
mov dx,com_port_num
int 14h
}
putch(7);
putch(7);
}