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

Сигнальные лампы для внутреннего модема


Как мы говорили ранее, одним из преимуществ внешнего модема над внутренним является наличие на его лицевой панели световых индикаторов, по которым можно определить состояние модема.

Мы приведем маленькую резидентную программу, которая отображает на экране дисплея состояние модема. Наша программа компенсирует недостаток внутреннего модема, связанный с отсутствием индикации.

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

Как работает эта программа? Она перехватывает прерывание от таймера (с номером 1Сh) и таким образом получает управление несколько раз в секунду. Затем она считывает значения регистров состояния линии, состояния модема и регистра управления модемом.

По состоянию регистра управления модемом программа определяет состояние линий DTR и RTS, управляющих процессом подтверждения связи. Регистр состояния модема отражает состояние сигналов CTS, DSR, используемых для управления потоком, а также линий RI и DCD. Сигнал RI означает, что пришел вызов от удаленного модема, а сигнал DCD - что модемы установили и поддерживают связь.

После того как программа считает состояние регистров асинхронного порта, она отображает их состояние на экране дисплея. Вывод данных на экран наша программа выполняет путем непосредственного доступа к видеопамяти. При этом данные выводятся, начиная с адреса B800:0000. Если вы собираетесь использовать программу в графических режимах видеоадаптера или отображать данные о сотоянии регистров в другом месте экрана, то вам надо самим изменить процедуру вывода.

После запуска программы в левом верхнем углу экрана появится небольшое окно, в котором будет отображаться состояние линий TD, RD, RTS, CTS, RI, CDC, DTR, DSR:

--T-T-T-T-T-T-T-¬ ¦t¦r¦r¦c¦r¦d¦d¦d¦ ¦d¦d¦t¦t¦i¦c¦t¦s¦ ¦ ¦ ¦s¦s¦ ¦d¦r¦r¦ LT+T+T+T+T+T+T+T- ¦ ¦ ¦ ¦ ¦ ¦ ¦ L---- сигнал DSR ¦ ¦ ¦ ¦ ¦ ¦ L------ сигнал DTR ¦ ¦ ¦ ¦ ¦ L-------- сигнал DCD ¦ ¦ ¦ ¦ L---------- сигнал RI ¦ ¦ ¦ L------------ сигнал CTS ¦ ¦ L-------------- сигнал RTS ¦ L---------------- данные принимаются L------------------ данные передаются


Если какой- нибудь из этих сигналов примет значение логической единицы, то первый символ в названии этого сигнала будет отображаться с заглавной буквы. Например, если модем установил связь и передает данные, будут активными линии TD, RTS, CTS, DCD, DTR и DSR:

T r R C r D D D d d t t i c t s     s s   d r r

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

// LIGHT.C // сигнальные лампы модема



#include <stdlib.h> #include <string.h> #include <dos.h>

// включаемый файл uart_reg.h можно найти в приложении

#include "uart_reg.h"

// отключаем проверку стека и указателей

#pragma check_stack( off ) #pragma check_pointer( off )

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

#define TICKPERMIN 1092L

char _huge *tsrstack; char _huge *appstack; char _huge *tsrbottom;

// объявления функций

void (_interrupt _far *oldtimer)( void ); void _interrupt _far newtimer( void );

void test_com_port( void ); void hello( void ); void help( void );

// определяем указатель на счетчик таймера

long _far *pcurtick = (long _far *)0x0000046cL; long goaltick;

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

unsigned uart_reg[] = { 0, 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; unsigned com_port;

// главная процедура

void main( int argc, char *argv[] ) {

unsigned tsrsize;

// параметр программы должен содержать номер // используемого COM-порта

if( argc < 2 ) help();

hello();

_asm mov WORD PTR tsrstack[0], sp _asm mov WORD PTR tsrstack[2], ss

FP_SEG( tsrbottom ) = _psp; FP_OFF( tsrbottom ) = 0;

com_port = ( unsigned ) uart_reg[atoi( argv[1] )];

printf( "\nпорт %x\n", com_port );

// определяем момент первой проверки регистров // асинхронного адаптера

goaltick += TICKPERMIN / 10L;

// переустанавливаем вектор прерывания от таймера

oldtimer = _dos_getvect( 0x1c ); _dos_setvect( 0x1c, newtimer );

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



tsrsize = ((tsrstack - tsrbottom) >> 4) + 1; _dos_freemem( _psp );

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

_dos_keep( 0, tsrsize ); }

void hello( void ) {

printf("\n(c) Frolov G.V. Сигнальные лампы\n \n" " trrcrddd \n" " ddtticts \n" "   ss drr \n" " ¦¦¦¦¦¦¦¦ \n" " ¦¦¦¦¦¦¦L---- сигнал DSR \n" " ¦¦¦¦¦¦L----- сигнал DTR \n" " ¦¦¦¦¦L------ сигнал DCD \n" " ¦¦¦¦L------- сигнал RI \n" " ¦¦¦L-------- сигнал CTS \n" " ¦¦L--------- сигнал RTS \n" " ¦L---------- данные принимаются \n" " L----------- данные передаются \n" ); }

void help( void ) {

printf(" Неправильно задан параметр программы - \n" " пример: LIGHT [1|2|3|4] \n"); exit(0); }

// обработчик прерываний от таймера

void _interrupt _far newtimer() {

// если пришло время, проверяем регистры COM-порта

if(*pcurtick >= goaltick) {

(*oldtimer)();

// вычисляем время следующей проверки

goaltick += TICKPERMIN / 10L;

// проверяем регистры COM-порта и отображаем их на экране

test_com_port(); }

else _chain_intr( oldtimer ); }

void test_com_port( void ) {

char data[] = "trrcrddd"; char data2[] = "ddtticts"; char data3[] = " ss drr";

char attr[9];

_asm {

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

mov dx,com_port add dx,LSR_N in al,dx

// проверяем, пуст ли регистр сдвига передатчика

test al,40h jz next_1

mov ah,'t' mov data[0],ah mov attr[0],0x71 jmp short next_2

next_1:

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

mov ah,'T' mov data[0],ah mov attr[0],0x79

next_2:

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

test al,1 jnz next_3 mov ah,'r' mov data[1],ah mov attr[1],0x71 jmp short next_4

next_3:

// если есть данные для чтения, отображаем на экране // символ 'R'

mov ah,'R' mov data[1],ah mov attr[1],0x79

next_4:

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

mov dx,com_port add dx,MSR_N in al,dx



// определяем состояние линии CTS

test al,10h jnz next_5

// линия CTS неактивна

mov ah,'c' mov data[3],ah mov attr[3],0x72 jmp short next_6

next_5:

// линия CTS активна

mov ah,'C' mov data[3],ah mov attr[3],0x7a

next_6:

// определяем состояние линии DSR

test al,20h jnz next_7

// линия DSR неактивна

mov ah,'d' mov data[7],ah mov attr[7],0x72 jmp short next_8

next_7:

// линия DSR активна

mov ah,'D' mov data[7],ah mov attr[7],0x7a

next_8:

// определяем состояние линии RI

test al,40h jnz next_9

// линия RI находится в неактивном состоянии

mov ah,'r' mov data[4],ah mov attr[4],0x76 jmp short next_10

next_9:

// линия RI находится в активном состоянии

mov ah,'R' mov data[4],ah mov attr[4],0x7e

next_10:

// определяем состояние линии DCD

test al,80h jnz next_11

// линия DCD неактивна

mov ah,'d' mov data[5],ah mov attr[5],0x76 jmp short next_12

next_11:

// линия DCD активна

mov ah,'D' mov data[5],ah mov attr[5],0x7e

next_12:

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

mov dx,MCR_N add dx,com_port in al,dx

// проверяем линию RTS

test al,2 jnz next_13

// линия RTS находится в неактивном состоянии

mov ah,'r' mov data[2],ah mov attr[2],0x74 jmp short next_14

next_13:

// линия RTS находится в активном состоянии

mov ah,'R' mov data[2],ah mov attr[2],0x7c

next_14:

// проверяем линию DTR

test al,1 jnz next_15

// линия DTR неактивна

mov ah,'d' mov data[6],ah mov attr[6],0x74 jmp short next_16

next_15:

// линия DTR активна

mov ah,'D' mov data[6],ah mov attr[6],0x7c

next_16:

// отображаем на экране состояние регистров // вывод на экран происходит непосредственно // через видеопамять

// сегмент видеопамяти

mov ax,0B800h mov es,ax

xor si,si mov di,0 mov cx,8

next_char:

// отображаем на экране очередной символ // из массива data

mov ah,data[si] mov es:[di],ah

inc di

// устанавливаем атрибуты этого символа

mov ah,attr[si] mov es:[di],ah sti

inc di inc si

loop next_char

xor si,si mov di,160 mov cx,8

next_str2: mov ah,data2[si] mov es:[di],ah inc di mov ah,attr[si] mov es:[di],ah sti inc di inc si loop next_str2

xor si,si mov di,320 mov cx,8

next_str3: mov ah,data3[si] mov es:[di],ah inc di mov ah,attr[si] mov es:[di],ah sti inc di inc si loop next_str3

} }


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