Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

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

© Александр Фролов, Григорий Фролов
Том 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);

}

[Назад] [Содеожание] [Дальше]