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 |
COM1 | 3F8h - 3FFh | IRQ4 |
COM2 | 2F8h - 2FFh | IRQ3 |
COM3 | 3E8h - 3EFh | IRQ4 |
COM4 | 2E8h - 2EFh | IRQ3 |
Итак, текст программы:
// 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 ); }