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

         

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


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

Каждый раз, когда модем получает или передает символ, он сообщает об этом компьютеру сигналом по линии IRQ. Компьютер класса IBMPC имеет восемь таких линий, а компьютер класса 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
COM13F8h - 3FFhIRQ4
COM22F8h - 2FFhIRQ3
COM33E8h - 3EFhIRQ4
COM42E8h - 2EFhIRQ3
Теперь мы приведем небольшую программу, определяющую, какие последовательные адаптеры установлены на вашем компьютере. Данная программа сначала отображает на экране адреса 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 ); }


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