Модемы и факс-модемы. Программирование для MS-DOS и Windows

       

Коммуникационная программа


Теперь мы приступим к самому интересному - приведем подробный алгоритм коммуникационной программы, а затем - исходный текст такой программы.

Сначала мы рассмотрим вариант коммуникационной программы без использования прерываний от асинхронного порта. Этот вариант несколько проще, так как нам не надо создавать довольно нетривиальный обработчик для этого прерывания, а также программировать контроллер прерываний.

Итак, приступим. Как мы сказали ранее, первым шагом при программировании модема надо считать инициализацию 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);

}


Содержание раздела