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