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

Инициализация асинхронного адаптера


Первое, что должна сделать программа, работающая с асинхронным адаптером, - установить формат и скорость передачи данных. После загрузки операционной системы для асинхронных адаптеров устанавливается скорость 2400 бод, не выполняется проверка на четность, используются один стоповый бит и восьмибитовая длина передаваемого символа. Вы можете изменить этот режим командой MS-DOS MODE.

Выполнив ввод из управляющего регистра, программа может получить текущий режим адаптера. Для установки нового режима измените нужные вам поля и запишите новый байт режима обратно в управляющий регистр.

Если вам надо задать новое значение скорости обмена данными, перед записью байта режима установите старший бит этого байта в 1, при этом регистр данных и управляющий регистр используются для задания скорости обмена. Затем последовательно двумя командами вывода загрузите делитель частоты тактового генератора. Младший байт запишите в регистр данных, а старший - в регистр управления прерываниями.

Перед началом работы необходимо также проинициализировать регистр управления прерываниями (порт 3F9h), даже если в вашей программе не используются прерывания от асинхронного адаптера. Для этого сначала надо перевести регистр данных и регистр управления прерываниями в обычный режим, записав ноль в старший бит управляющего регистра. Затем можно устанавливать регистр управления прерываниями. Если прерывания вам не нужны, запишите в этот порт нулевое значение.

На этом инициализацию можно считать законченной.

Для того чтобы узнать текущее состояние асинхронного адаптера, вы можете использовать следующую функцию:

/** *.Name aux_stat *.Title Определение режима асинхронного адаптера * *.Descr Эта функция считывает текущий режим * асинхронного порта и записывает его * в структуру с типом AUX_MODE. * *.Proto void aux_stat(AUX_MODE *mode, int port); * *.Params AUX_MODE mode - структура, описывающая * протокол и режим работы порта: * * typedef struct _AUX_MODE_ { * * union { * struct { * unsigned char len : 2, // длина символа * stop : 1, // число стоп-битов * parity : 2, // контроль четности * stuck_parity : 1, // фиксация четности * en_break_ctl : 1, // установка перерыва * dlab : 1; // загрузка регистра * // делителя * } ctl_word; * char ctl; * } ctl_aux; * * unsigned long baud; // скорость передачи данных * * } AUX_MODE; * * int port - номер асинхронного адаптера: * 0 - COM1, 1 - COM2 * *.Return Ничего * *.Sample aux_test.c **/


#include <stdio.h> #include <conio.h> #include "sysp_com.h"

void aux_stat(AUX_MODE *mode, int port) {

unsigned long b;

// Запоминаем режим адаптера

mode->ctl_aux.ctl = (char)inp(0x3fb - 0x100 * port);



// Устанавливаем старший бит режима // для считывания текущей скорости передачи

outp(0x3fb - 0x100 * port, mode->ctl_aux.ctl | 0x80);

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

b = inp(0x3f9 - 0x100 * port); b = b << 8; b += inp(0x3f8 - 0x100 * port);

// Преобразуем его в боды

switch (b) { case 1040: b = 110; break; case 768: b = 150; break; case 384: b = 300; break; case 192: b = 600; break; case 96: b = 1200; break; case 48: b = 2400; break; case 24: b = 4800; break; case 12: b = 9600; break; case 6: b = 19200; break; case 3: b = 38400; break; case 2: b = 57600; break; case 1: b = 115200; break; default: b=0; break; }

mode->baud = b;

// Восстанавливаем состояние адаптера

outp(0x3fb - 0x100 * port, mode->ctl_aux.ctl & 0x7f);

}

Прочитав состояние адаптера, вы можете изменить нужные вам поля в структуре AUX_MODE и вызвать функцию aux_init() для изменения параметров адаптера:

/** *.Name aux_init *.Title Инициализация асинхронного адаптера * *.Descr Эта функция инициализирует асинхронные * адаптеры, задавая протокол обмена данными * и скорость обмена данными. * *.Proto int aux_init(AUX_MODE *mode, int port, * int imask); * *.Params AUX_MODE *mode - указатель на структуру, * описывающую протокол и режим работы * порта; * * int port - номер асинхронного адаптера: * 0 - COM1, 1 - COM2 * * int imask - значение для регистра маски * прерываний * *.Return 0 - инициализация выполнена успешно; * 1 - ошибки в параметрах инициализации. * *.Sample aux_test.c **/

#include <stdio.h> #include <conio.h> #include "sysp_com.h"

int aux_init(AUX_MODE *mode, int port, int imask) {

unsigned div; char ctl;

// Вычисляем значение для делителя

switch (mode->baud) { case 110: div = 1040; break; case 150: div = 768; break; case 300: div = 384; break; case 600: div = 192; break; case 1200: div = 96; break; case 2400: div = 48; break; case 4800: div = 24; break; case 9600: div = 12; break; case 19200: div = 6; break; case 38400: div = 3; break; case 57600: div = 2; break; case 115200: div =1; break; default: return(-1); break; }

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

ctl = inp(0x3fb - 0x100 * port); outp(0x3fb - 0x100 * port, ctl | 0x80);

outp(0x3f9 - 0x100 * port, (div >> 8) & 0x00ff); outp(0x3f8 - 0x100 * port, div & 0x00ff);

// Записываем новое управляющее слово

outp(0x3fb - 0x100 * port, mode->ctl_aux.ctl & 0x7f);

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

outp(0x3f9 - 0x100 * port, imask);

return(0);

}


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