Модемы и факс-модемы. Программирование для MS-DOS и Windows.© Александр Фролов, Григорий ФроловТом 16, М.: Диалог-МИФИ, 1993. 5.3. Порты асинхронного адаптераНа этапе инициализации системы, модуль процедуры начальной загрузки BIOS тестирует имеющиеся асинхронные порты RS-232-C и инициализирует их. В зависимости от версии BIOS инициализирует первые два или четыре порта. Их базовые адреса записываются в области данных BIOS начиная с адреса 0040:0000h. Чтобы просмотреть значения, записанные в области данных BIOS вашего компьютера, можно воспользоваться программой Debug, поставляемой вместе с операционной системой MS-DOS. Таким образом, можно определить, какие COM-порты установлены на компьютере. Запустите программу Debug. Для этого введите в строке
системного приглашения MS-DOS команду DEBUG.EXE. Программа Debug выведет на
экран приглашение в виде черточки '-'. Чтобы просмотреть содержимое оперативной
памяти по адресу 0040:0000h введите команду d40:0 и нажмите клавишу -d40:0 0040:0000 F8 03 F8 02 E8 03 00 00-78 03 00 00 00 00 00 00 ........x....... 0040:0010 61 C6 00 80 02 80 00 20-00 00 38 00 38 00 E0 50 a...... ..8.8..P Нас будут интересовать только первые восемь байт из этого дампа. Первые два байта содержат базовый адрес порта COM1. Поменяв местами два этих байта, получаем адрес 3F8h. Следующие два байта содержат адрес порта COM2 - 2F8h, затем COM3 - 3E8h. Два байта, соответствующие порту COM4, содержат нулевые значения. Это означает, что асинхронный последовательный адаптер компьютера не имеет порта COM4 или BIOS компьютера не может или не пытается его обнаружить. Теперь вы можете завершить работу программы Debug. Для
этого введите команду q и нажмите клавишу Адреса COM-портов из нашего примера являются своего рода стандартом. Первый адаптер COM1 обычно имеет базовый адрес 3F8h и занимает диапазон адресов от 3F8h до 3FFh. Второй адаптер COM2 имеет базовый адрес 2F8h и занимает адреса 2F8h...2FFh. Третий адаптер COM3 имеет базовый адрес 3E8h и занимает диапазон адресов от 3E8h до 3EFh. Четвертый адаптер COM4 имеет базовый адрес 2E8h и занимает адреса 2E8h...2EFh. Тем не менее, для некоторых компьютеров, например, с шиной MCA - PS/2, адреса COM-портов могут иметь другие значения. Порты асинхронного адаптера могут вырабатывать прерывания: Порты COM1 и COM3 асинхронного последовательного адаптера используют линию IRQ4 и вырабатывают прерывание INT 0Ch, а порты COM2 и COM4 используют линию IRQ3 и вырабатывают прерывание INT 0Bh. Некоторые платы последовательного асинхронного адаптера позволяют присвоить COM-портам другие линии IRQ, например, IRQ5 или IRQ7. Как видно, порты COM1, COM3 и COM2, COM4 используют одинаковые прерывания. Поэтому, как правило, нельзя одновременно использовать порты COM1 и COM3, так же как порты COM2 и COM4. Например, если к порту COM1 подключен модем, то мышь можно подключить только к порту COM2 или COM4 Теперь перейдем к подробному рассмотрению портов, используемых COM-портами. 5.3.1. Регистр данных Регистр данных расположен непосредственно по базовому адресу COM-порта и используется для обмена данными и для задания скорости обмена. При передаче данных в этот регистр необходимо записать передаваемый байт данных. После приема данных от внешнего устройства принятый байт можно также прочитать из этого же регистра. В зависимости от состояния старшего бита управляющего регистра (расположенного по адресу base_adr + 3, где base_adr соответствует базовому адресу COM-порта) назначение этого регистра может изменяться. Если старший бит равен нулю, регистр используется для записи передаваемых данных. Если же старший бит равен единице, регистр используется для ввода значения младшего байта делителя частоты тактового генератора. Изменяя содержимое делителя, можно изменять скорость передачи данных. Старший байт делителя записывается в регистр управления прерываниями по адресу base_adr + 1. Зависимость скорости передачи данных от значения делителя частоты представлена в следующей таблице:
Как следует из этой таблицы, максимальная скорость обмена информацией, которую можно достичь при использовании асинхронного адаптера, достигает 115200 бит за секунду, что примерно соответствует 12 Кбайт в секунду. 5.3.2. Регистр управления прерываниями Этот регистр используется либо для управления прерываниями от асинхронного адаптера, либо (после вывода в управляющий регистр байта с установленным в 1 старшим битом) для вывода значения старшего байта делителя частоты тактового генератора. В режиме управления прерываниями регистр имеет следующий формат: D0 Разрешение прерывания при готовности принимаемых данных. Если бит содержит единицу, генерация прерывания при готовности принимаемых данных разрешена D1 Разрешение прерывания после передачи байта (когда выходной буфер передачи пуст). Если бит содержит единицу, генерация прерывания после передачи байта разрешена D2 Разрешение прерывания по обнаружению состояния BREAK или по ошибке. Если бит содержит единицу, то при обнаружении состояния BREAK или при возникновении ошибки происходит прерывание D3 Разрешение прерывания по изменению состояния входных линий на разъеме RS-232-C (CTS, DSR, RI, DCD). Если бит содержит единицу, то при изменении состояния линий CTS, DSR, RI, DCD COM-порт вырабатывает прерывание D7-D4 Не используются, должны быть равны 0 Для удобства доступа к регистрам UART мы определили для каждого регистра соответствующее объединение (см. файл UART_REG.H). Ниже мы приводим объединение, которое можно использовать для доступа к отдельным полям регистра управления прерываниями из программ на языке Си: // Смещение относительно базового адреса #define ICR_N 1 // Регистр управления прерываниями typedef union _ICR_ { struct { unsigned char in_ready : 1; unsigned char out_ready : 1; unsigned char err : 1; unsigned char change : 1; unsigned char reserv : 4; } bit_reg; unsigned char byte; } ICR; 5.3.3. Регистр идентификации прерывания После того как произошло прерывание от COM-порта, программа может прочитать значение регистра идентификации прерывания, чтобы определить причину его возникновения. Формат регистра представлен ниже: D0 Если бит равен единице, значит нет прерываний, ожидающих обслуживания D2-D1 Содержит идентификатор прерывания
В файле UART_REG.H регистр идентификации прерывания определен следующим образом: // Смещение относительно базового адреса #define IIDR_N 2 // Регистр идентификации прерывания typedef union _IIDR_ { struct { unsigned char no_inter : 1; unsigned char inter_id : 2; unsigned char reserv : 5; } bit_reg; unsigned char byte; } IIDR; 5.3.4. Управляющий регистр Управляющий регистр доступен для записи и чтения. Этот регистр управляет различными характеристиками UART: скоростью передачи данных, контролем четности, передачей сигнала BREAK, длиной передаваемых слов (символов). D1-D0 Данные биты определяют длину передаваемых слов в битах:
D2 Бит определяет количество стоповых бит:
D3-D4 Биты управляют проверкой на четность:
D5 Фиксация четности. При установке этого бита бит четности всегда принимает значение 0, если биты D3 D4 равны 11, или 1, если биты D3 D4 равны 01 D6 Установка перерыва. Вызывает вывод строки нулей в качестве сигнала BREAK для подключенного устройства D7 Бит используется для доступа к регистру установки скорости. Если бит D7 равен единице, то регистр данных и регистр управления прерываниями используются для загрузки делителя частоты тактового генератора. Если бит D7 равен нулю, то регистр данных и регистр управления прерываниями используются как обычно Для облегчения доступа к отдельным полям управляющего регистра можно воспользоваться следующим объединением: // Смещение относительно базового адреса #define LCR_N 3 // Управляющий регистр typedef union _LCR_ { struct { unsigned char len : 2; unsigned char stop : 1; unsigned char parity : 2; unsigned char stuck_parity : 1; unsigned char en_break_ctl : 1; unsigned char dlab : 1; } bit_reg; unsigned char byte; } LCR; 5.3.5. Регистр управления модемом Регистр управления модемом управляет состоянием выходных линий DTR, RTS и линий, специфических для модемов - OUT1 и OUT2. Формат регистра представлен ниже: D0 Линия DTR. Сигнал подтверждения связи. Используется модемами для разрешения передачи данных между компьютером и микросхемой UART D1 Линия RTS. Сигнал подтверждения связи. Используется модемами для разрешения передачи данных между компьютером и микросхемой UART D2 Линия OUT1. Для некоторых модемов при установке этого бита в единицу происходит его аппаратный сброс D3 Линия OUT2. Если бит D3 содержит единицу, то UART может вырабатывать прерывания, а если нулю - не может D4 Запуск диагностики при входе асинхронного адаптера, замкнутом на его выход (Digital Loopback test). Эта возможность реализована только для асинхронных портов, использующих микросхему UART 8250, или полностью совместимых с ней D7-D5 Должны быть равны 0 Регистр управления модемом определен нами в файле UART_REG.H следующим образом: // Смещение относительно базового адреса #define MCR_N 4 // Регистр управления модемом typedef union _MCR_ { struct { unsigned char dtr : 1; unsigned char rts : 1; unsigned char out1 : 1; unsigned char out2 : 1; unsigned char diag : 1; unsigned char reserv : 3; } bit_reg; unsigned char byte; } MCR; 5.3.6. Регистр состояния линии Регистр состояния линии позволяет программе определить причину ошибок, которые могут произойти при передаче данных между компьютером и COM-портом. Формат регистра представлен ниже: D0 Данные получены и готовы для чтения, при чтении данных бит сбрасывается D1 Ошибка переполнения. Принят новый байт данных, а предыдущий еще не был считан программой. В результате предыдущий байт потерян D2 Ошибка четности, сбрасывается после чтения состояния линии D3 Ошибка синхронизации. Возникает, например, при отсутствии стоп-битов в принятом байте D4 Обнаружен запрос на прерывание передачи BREAK - длинная строка нулей D5 Регистр хранения передатчика пуст, в него можно записывать новый байт для передачи D6 Регистр сдвига передатчика пуст. Этот регистр получает данные из регистра хранения и преобразует их в последовательный вид для передачи. Если этот бит равен единице, то UART может принять очередной символ от компьютера D7 Тайм-аут (устройство не связано с компьютером) Доступ к отдельным полям регистра состояния линии можно организовать с помощью следующего объединения: // Смещение относительно базового адреса #define LSR_N 5 // Регистр состояния линии typedef union _LSR_ { struct { unsigned char in_ready : 1; unsigned char overflow : 1; unsigned char parity : 1; unsigned char synxr : 1; unsigned char break_detect : 1; unsigned char out_ready : 1; unsigned char shift_ready : 1; unsigned char taimout : 1; } bit_reg; unsigned char byte; } LSR; 5.3.7. Регистр состояния модема Регистр состояния модема позволяет программе определить состояние управляющих сигналов, передаваемых модемом асинхронному порту компьютера. Формат регистра состояния модема представлен ниже: D0 Если бит D0 равен единице, линия CTS изменила состояние D1 Если бит равен единице, линия DSR изменила состояние D2 Если бит D2 равен единице, линия RI изменила состояние. Некоторые коммуникационные программы определяют по состоянию этого бита наличие звонка на телефонной линии D3 Если данный бит равен единице, значит линия DCD изменила свое состояние. Некоторые коммуникационные программы определяют по состоянию этого бита, установил ли модем соединение с удаленным модемом D4 Бит соответствует состоянию линии CTS. Эта линия используется совместно с линией RTS при реализации аппаратного управления потоком данных D5 Бит соответствует состоянию линии DSR. Эта линия используется совместно с линией DTR при аппаратной реализации подтверждения связи D6 Бит соответствует состоянию линии RI. Единица означает, что модем обнаружил звонок на телефонной линии D7 Состояние линии DCD. Единица означает, что модемом получена несущая частота. Заметим, что при выполнении аналогового теста (analog test) этот бит должен содержать единицу. Если это не так, то возможно, что модем исправен (для внешних модемов), но кабель, соединяющий модем и компьютер, не полностью соответствует стандарту RS-232 Доступ к отдельным полям регистра состояния модема можно организовать с помощью следующего объединения: // Смещение относительно базового адреса #define MSR_N 6 // Регистр состояния модема typedef union _MSR_ { struct { unsigned char change_cts : 1; unsigned char change_dsr : 1; unsigned char change_ri : 1; unsigned char change_dcd : 1; unsigned char cts : 1; unsigned char dsr : 1; unsigned char ri : 1; unsigned char dcd : 1; } bit_reg; unsigned char byte; } MSR; |