Модемы и факс-модемы. Программирование для MS-DOS и Windows

       

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


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

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

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

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

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

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

Листинг 5.4. Файл AUX_STAT.C

/**

*.Name         aux_stat

*

*.Descr        Функция считывает текущий режим

*              асинхронного порта и записывает его

*              в структуру с типом AUX_MODE.



*

*.Proto        void aux_stat(AUX_MODE *mode, int port);

*

*.Params       AUX_MODE mode - структура, описывающая


*              протокол и режим работы порта

*

*              int port - номер асинхронного адаптера:

*                 0 - COM1, 1 - COM2

*

*.Return       Ничего

**/

#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 для изменения текущего режима COM-порта. Исходный текст этой функции можно найти в листинге 5.5.

Листинг 5.5. Файл AUX_INIT.C

/**

*.Name         aux_init

*

*.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);

}


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