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

Регистр состояния модема



Регистр состояния модема

Регистр состояния модема определяет состояние управляющих сигналов, передаваемых модемом асинхронному порту компьютера.

7 6 5 4 3 2 1 0 --T-T-T-T-T-T-T-¬ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ LT+T+T+T+T+T+T+T- ¦ ¦ ¦ ¦ ¦ ¦ ¦ L= Линия CTS изменила состояние ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ L=== Линия DSR изменила состояние ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ L===== Линия RI изменила состояние. Некоторые ¦ ¦ ¦ ¦ ¦ коммуникационные программы определяют по ¦ ¦ ¦ ¦ ¦ состоянию этого бита наличие звонка на ¦ ¦ ¦ ¦ ¦ телефонной линии ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ ¦ L======= Если данный бит равен единице, значит ¦ ¦ ¦ ¦ линия DCD изменила свое состояние. ¦ ¦ ¦ ¦ Некоторые коммуникационные программы ¦ ¦ ¦ ¦ определяют по состоянию этого бита, ¦ ¦ ¦ ¦ детектировал ли модем несущую частоту на ¦ ¦ ¦ ¦ телефонной линии ¦ ¦ ¦ ¦ ¦ ¦ ¦ L========= Состояние линии CTS. Эта линия ¦ ¦ ¦ используется совместно с линией RTS при ¦ ¦ ¦ реализации аппаратного управления потоком ¦ ¦ ¦ данных ¦ ¦ ¦ ¦ ¦ L=========== Состояние линии DSR. Эта линия ¦ ¦ используется совместно с линией DTR при ¦ ¦ аппаратной реализации подтверждения связи ¦ ¦ ¦ L============= Состояние линии RI. Единица означает, что ¦ модем обнаружил звонок на телефонной ¦ линии ¦ L=============== Состояние линии 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;



В качестве примера рассмотрим программу, которая считывает и отображает на дисплее состояние некоторых регистров асинхронного адаптера. Сначала программа запрашивает номер COM-порта, состояние регистров которого вы хотите узнать. Затем она получает базовый адрес регистров этого асинхронного адаптера. Базовый адрес регистров данного асинхронного адаптера программа получает через область переменных BIOS. Вычисление базового адреса выполняется функцией com_address():

#include "sysp_com.h"

/** *.Name com_address * *.Title Определяет адрес заданного COM-порта. * *.Descr Эта функция определяет адрес базового регистра * COM-порта. Адрес берется из области переменных * BIOS. * *.Proto unsigned com_address( int port ); * *.Params int port - номер асинхронного адаптера: * 0 - COM1, 1 - COM2, 2 - COM3, 3 - COM4. * *.Return Адрес базового регистра асинхронного порта. * Если порт не установлен, возвращается 0, * если неправильно задан параметр, то -1. * *.Sample com_adr.c **/

unsigned com_address( int port ) {

unsigned base_address;

// возвращаем -1, если заданный асинхронный порт // не COM1, не COM2, не COM3 и не COM4

if(( port > 4 ) ( port < 0 )) return( -1 );

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

base_address = *(( unsigned _far * ) FP_MAKE( 0x40, port * 2 ));

return( base_address ); }

Старые версии BIOS могут самостоятельно определить наличие и адреса только первых двух COM-портов. Таким образом, если на вашем компьютере установлен асинхронный последовательный порт COM3 или COM4, то без дополнительной инициализации данная программа может просто "не увидеть" эти порты.

После определения базового адреса COM-порта, программа считывает состояние регистров данного порта и отображает их на дисплее.

Итак, приведем основной модуль программы:

// REGISTER.C

#include "uart_reg.h" #include "sysp_com.h" #include <graph.h>

unsigned com_address( int );



void main(void) {

unsigned adr; int port; unsigned char data;

LCR reg_lcr; LSR reg_lsr; MCR reg_mcr; MSR reg_msr; ICR reg_icr; IIDR reg_iidr;

printf(" Программа отображает состояние регистров UART.\n\n");

printf(" Введите номер асинхронного порта (1-4): "); scanf("%d", &port );

// определяем базовый адрес адаптера port

adr = com_address( --port );

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

printf("\n Управляющий регистр = %Xh\n\n", data = (unsigned char ) inp( adr + LCR_N ) );

reg_lcr.byte = data;

printf(" Длина слова в байтах %d\n" " Количество стоповых битов %d\n" " Контроль %s\n" " Фиксация четности %s\n" " Установка перерыва: %s\n" " Порты %Xh, %Xh используются %s\n",

reg_lcr.bit_reg.len + 5, reg_lcr.bit_reg.stop + 1, (reg_lcr.bit_reg.parity == 3) ? "на четность" : ((reg_lcr.bit_reg.parity == 1 ) ? "на нечетность" : "четности не выполняется"),

(reg_lcr.bit_reg.stuck_parity == 1) ? "производится" : "не производится",

(reg_lcr.bit_reg.en_break_ctl == 1) ? "есть" : "нет",

adr, adr + 1, (reg_lcr.bit_reg.dlab == 1) ? "для загрузки делителя частоты" : "как обычно"

);

// считываем значение регистра состояния линии

printf("\n Регистр состояния линии = %Xh\n\n", data = (unsigned char ) inp( adr + LSR_N ) );

reg_lsr.byte = data;

printf(" Данные готовы для чтения: %d\n" " Ошибка переполнения: %d\n" " Ошибка четности: %d\n" " Ошибка синхронизации: %d\n" " Обнаружен запрос на прерывание \"BREAK\": %d\n" " Регистр хранения передатчика пуст: %d\n" " Регистр сдвига передатчика пуст: %d\n" " Тайм-аут: %d\n",

reg_lsr.bit_reg.in_ready, reg_lsr.bit_reg.overflow, reg_lsr.bit_reg.parity, reg_lsr.bit_reg.synxr, reg_lsr.bit_reg.break_detect, reg_lsr.bit_reg.out_ready, reg_lsr.bit_reg.shift_ready, reg_lsr.bit_reg.taimout );



printf("\n\ n Нажмите любую клавишу для продолжения "); getch();

// считываем значение регистра управления модемом

printf("\n Регистр управления модемом = %Xh\n\n", data = ( unsigned char ) inp( adr + MCR_N )); reg_mcr.byte = data;

printf(" Линия dtr: %d\n" " Линия rts: %d\n" " Линия out1: %d\n" " Линия out2: %d\n" " Запуск диагностики: %d\n",

reg_mcr.bit_reg.dtr, reg_mcr.bit_reg.rts, reg_mcr.bit_reg.out1, reg_mcr.bit_reg.out2, reg_mcr.bit_reg.diag );

// считываем значение регистра состояния модема

printf("\n Регистр состояния модема = %Xh\n\n", data = ( unsigned char ) inp( adr + MSR_N ) ); reg_msr.byte = data;

printf(" Линия изменила cts состояние: %d\n" " Линия изменила dsr состояние: %d\n" " Линия изменила ri состояние: %d\n" " Линия изменила dcd состояние: %d\n" " Линия cts: %d\n" " Линия dsr: %d\n" " Линия ri: %d\n" " Линия dcd: %d\n",

reg_msr.bit_reg.change_cts, reg_msr.bit_reg.change_dsr, reg_msr.bit_reg.change_ri, reg_msr.bit_reg.change_dcd, reg_msr.bit_reg.cts, reg_msr.bit_reg.dsr, reg_msr.bit_reg.ri, reg_msr.bit_reg.dcd );

printf("\n\n Нажмите любую клавишу для продолжения "); getch();

// считываем значение регистра управления прерываниями

printf("\n\n Регистр управления прерываниями = %Xh\n\n", data = ( unsigned char ) inp( adr + ICR_N ));

reg_icr.byte = data;

printf(" Разрешение прерывания при готовности принимаемых данных: %d\n" " Разрешение прерываний после передачи данных: %d\n"

" Разрешение прерывания при обнаружении" " состояния \"BREAK\": %d\n"

" Разрешение прерыывания при изменении состояния линий" " cts, dsr, ri, dcd: %d\n",

reg_icr.bit_reg.in_ready, reg_icr.bit_reg.out_ready, reg_icr.bit_reg.err, reg_icr.bit_reg.change );

// считываем значение регистра идентификации прерываний

printf("\n\n Регистр идентификации прерываний = %Xh\n\n", data = ( unsigned char ) inp( adr + IIDR_N ));

reg_iidr.byte = data;

printf(" Нет прерываний, ожидающих обслуживания: %d\n" " Идентификатор прерывания: %d\n",

reg_iidr.bit_reg.no_inter, reg_iidr.bit_reg.inter_id ); }


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