Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Программирование модемов

© Александр Фролов, Григорий Фролов
Том 4, М.: Диалог-МИФИ, 1993, 236 стр.

[Назад] [Содеожание] [Дальше]

4.2. COM-порт и номера IRQ

COM-порт это своеобразные "электронные двери" через которые компьютер может обмениваться информацией с внешним миром. Все внутрение модемы уже имеют COM-порт на своей плате. Внешние модемы должны подключаться к отдельному COM-порту (асинхронному последовательному адаптеру), расположенному на плате внутри компьютера. Как мы уже говорили, каждый COM-порт имеет свой номер. Номер COM-порта - это просто соглашение, по которому коммуникационные программы узнают, какие адреса регистров используются для передачи и получения данных.

Каждый раз, когда модем получает или передает символ, он сообщает об этом компьютеру сигналом по линии IRQ. Компьютер класса IBM PC имеет восемь таких линий, а компьютер класса IBM AT - шестнадцать. Как правило, COM1 и COM3 используют IRQ4, а COM2 и COM4 - IRQ3. Однако некоторые внутренние модемы позволяют отдельно установить номер COM-порта и номер IRQ. Например, вы можете использовать COM3 и IRQ5.

Вы можете использовать COM1 и COM2 или COM3 и COM4 одновременно, так как они имеют различные линии IRQ. Если вам надо одновременно иметь три или больше COM-портов, то вам необходимо использовать другие IRQ (не только IRQ3 и IRQ4). Лучше всего использовать для этих целей IRQ5 и IRQ7. Линия IRQ7 предназначена для принтера и используется только программами фоновой печати, а IRQ5 - для жесткого диска.

Если вам не надо использовать одновременно три или больше COM-портов, то лучше использовать IRQ3 и IRQ4 для всех ваших COM-портов. Таким образом вы избавите себя от неприятностей с коммуникационными программами, которые не позволяют отдельно задавать номер линии IRQ и используют только IRQ3 и IRQ4.

Кроме определенного IRQ за каждым COM-портом закреплен адрес порта, через который программы могут взаимодействовать с ним. Существует четыре зарезервированных адреса - 3F8H, 2F8H, 3E8h и 2E8h, используемых для COM-портов на машинах всех фирм-производителей. В большинстве внутренних модемов специальные перемычки задают одновременно номер COM-порта, на который устанавливается модем и используемый им номер IRQ.

Существует некое несоответствие в том, как BIOS определяет адреса регистров данного COM-порта. Если во время операции начальной загрузки (POST) BIOS не обнаружит регистров асинхронного адаптера с базовым адресом 3F8h (обычно являющегося портом COM1), но обнаружит их по адресу 2F8h (обычно являющегося портом COM2), то он определит его как порт COM1. В добавление к этому для порта COM1 зарезервирована линия IRQ4, а для COM2 - IRQ3. Так что если вы используете для работы с данным COM-портом функции Basic, Pascal или DOS, то может возникать несоответствие между номером COM-порта, номером линии IRQ и базовым адресом регистров. Таким образом, используйте следующее правило - "не устанавливайте COM2 без COM1".

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

Номер COM порта Используемые адреса Номер IRQ
COM1 3F8h - 3FFh IRQ4
COM2 2F8h - 2FFh IRQ3
COM3 3E8h - 3EFh IRQ4
COM4 2E8h - 2EFh IRQ3

Теперь мы приведем небольшую программу, определяющую, какие последовательные адаптеры установлены на вашем компьютере. Данная программа сначала отображает на экране адреса COM-портов, определенные в переменных BIOS, а затем проверяет наличие последовательных портов по адресам 3F8h, 2F8h, 3E8h, 2E8h. Для этого производится запись с последующим считыванием в управляющий регистр для каждого предполагаемого порта. Если записанное и считанное значения совпадают, значит, COM-порт по данному адресу существует.

Итак, текст программы:

// COM_PORT.C

#include "sysp_com.h"

void main(void) {

   unsigned adr;
   int port;

   printf(" Программа определения адресов асинхронных портов.\n\n");

   printf(" Определяем адреса портов по области переменных BIOS:\n\n");

   // смотрим адрес каждого из четырех COM-портов в области
   // переменных BIOS

   for( port = 0; port < 4; port++ ) {

      // определяем адрес порта port

      adr = com_address( port ); 

      if( adr != 0 )
         printf("\n    COM%d - базовый адрес %Xh", port + 1, adr );

      // если соответствующая переменная BIOS содержит
      // нулевое значение считаем, что порт отсутствует

      else
         printf("\n    COM%d - отсутствует", port + 1);
   }


   // проверяем все зарезервированные базовые адреса
   // последовательных портов - 3F8h, 2F8h, 3E8h, 2E8h.

   printf("\n\n Тестируем зарезервированные адреса для регистров COM портов:\n\n");

   for( port = 0; port < 4; port++ ) {

      int port_address[] = { 0x3F8, 0x2F8, 0x3E8, 0x2E8 };

      // определяем адрес порта port

      adr = port_address[port];

      printf("    COM-порт с базовым адресом %Xh %s\n", adr,
            ( test_com( adr ) == 0 )? "отсутствует": "обнаружен");
   }
}
// TEST_COM.C

#include "sysp_com.h"

/**
*.Name         test_com
*
*.Title        Определяет наличие последовательного порта.
*
*.Descr        Эта функция определяет наличие последовательного
*              асинхронного порта по заданному базовому адресу.
*
*.Proto        int  test_com( unsigned base_adr );
*
*.Params       unsigned base_adr - базовый адрес предполагаемого
*              асинхронного адаптера.
*
*.Return       Если порт не установлен, возвращается 1,
*              если порт отсутствует, то возвращается 0.
*
*.Sample       test_com.c
**/

int test_com( unsigned base_adr ) {

   unsigned  save_reg;

   // определяем наличие асинхронного порта по заданному базовому
   // адресу путем записи с последующим чтением и сравнением
   // содержимого управляющего регистра

   // сохраняем содержимое управляющего регистра

   save_reg = inp( base_adr + LCR_N );

   // производим запись с последующим сравнением числа 0xA5
   // в управляющий регистр

   outp( base_adr + LCR_N, 0xA5 );
   if( 0xA5 != inp( base_adr + LCR_N ) )
      return( 0 );

   // производим запись с последующим сравнением числа 0x5A
   // в управляющий регистр

   outp( base_adr +  LCR_N, 0x5A );
   if( 0x5A != inp( base_adr + LCR_N ) )
      return( 0 );

   // восстанавливаем содержимое управляющего регистра

   outp( base_adr + LCR_N, save_reg );

   return( 1 );
}

Предупреждение!

Несколько COM-портов с различными номерами могут использовать одну и ту же линию IRQ. Если у вас есть несколько устройств, использующих одну линию IRQ, то вам надо соблюдать осторожность.

Обычно модем не может разделять IRQ с устройствами, программное обеспечение которых остается резидентным. Например, вы не должны устанавливать модем на линию IRQ, которая используется мышью. Если на вашем компьютере наблюдается конфликт по линии IRQ, советуем вам переустановить IRQ одного из конфликтующих устройств.

Для внутреннего модема базовый адрес асинхронного порта и номер линии IRQ, который он использует, задаются внутренними переключателями (DIP переключатели) в соответствии с документацией на модем.

[Назад] [Содеожание] [Дальше]