Программирование модемов© Александр Фролов, Григорий ФроловТом 4, М.: Диалог-МИФИ, 1993, 236 стр. 2.2. Инициализация асинхронного адаптераПервое, что должна сделать программа, работающая с асинхронным адаптером, - установить формат и скорость передачи данных. После загрузки операционной системы для асинхронных адаптеров устанавливается скорость 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);
}
|

