Аппаратное обеспечение персонального компьютера

       

Программа COMTEST


В листинге 6.1 приведен исходный текст программы COMTEST, использующей описанные выше способы работы с асинхроннымо адаптером.

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

Листинг 6.1. Файл comtest\comtest.с

// =====================================================

// Работа с асинхронным адаптером COM1.

// Перед запуском программы необходимо замкнуть

// контакты 2 и 3 разъема COM1

//

// (C) Фролов А.В, 1997

//

// E-mail: frolov@glas.apc.org

// WWW:    http://www.glasnet.ru/~frolov

//            или



//         http://www.dials.ccas.ru/frolov

// =====================================================

#include <stdio.h>

#include <conio.h>

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;

void aux_stat(AUX_MODE *mode, int port);

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

void aux_outp(char chr, int port);

char aux_inp(int port);

int main(void)

{

  AUX_MODE amd;

  aux_stat(&amd, 0);

  printf("\nСостояние порта COM1:"

    "\nКод длины символа:    %d"

    "\nКод числа стоп-битов: %d"

    "\nКонтроль четности:    %d"

    "\nСкорость передачи:    %lu",

    amd.ctl_aux.ctl_word.len,

    amd.ctl_aux.ctl_word.stop,

    amd.ctl_aux.ctl_word.parity,

    (unsigned long)amd.baud);

  amd.baud = 115200;

  aux_init(&amd, 0, 0);


  aux_stat(&amd, 0);

  printf("\nСостояние порта COM1:"

    "\nКод длины символа:    %d"

    "\nКод числа стоп-битов: %d"

    "\nКонтроль четности:    %d"

    "\nСкорость передачи:    %lu",

    amd.ctl_aux.ctl_word.len,

    amd.ctl_aux.ctl_word.stop,

    amd.ctl_aux.ctl_word.parity,

    (unsigned long)amd.baud);

  printf("\n\nТестирование асинхронного адаптера."

    "\nНажимайте клавиши!"

    "\nДля завершения работы нажмите <Contril+C>\n");

  for(;;)

  {

    // Вводим символ с клавиатуры и передаем его

    // в асинхронный адаптер

    aux_outp((char)getch(), 0);

    // Вводим символ из асинхронного адаптера и

    // отображаем его на экране

    putchar(aux_inp(0));

  }

  return 0;

}

/**

*.Name         aux_stat

*.Title        Определение режима асинхронного адаптера

*

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

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

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

*

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

*

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

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

*

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

*                 0 - COM1, 1 - COM2

**/

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

}

/**

*.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 - ошибки в параметрах инициализации.

**/

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;

}

/**

*.Name         aux_outp

*.Title        Вывод символа в асинхронный адаптер

*

*.Descr        Эта функция дожидается готовности

*              передатчика и посылает символ

*

*.Proto        void aux_outp(char chr, int port);

*

*.Params       char chr - посылаемый символ;

*

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

*                 0 - COM1, 1 - COM2

**/

void aux_outp( char chr, int port)

{

  unsigned status_reg, out_reg;

  status_reg = 0x3fd - 0x100 * port;

  out_reg = status_reg - 5;

  while( (inp(status_reg) & 0x20) == 0 );

  outp(out_reg, chr);

}

/**

*.Name         aux_inp

*.Title        Ввод символа из асинхронного адаптера

*

*.Descr        Эта функция дожидается готовности

*              приемника и вводит символ из асинхронного

*              адаптера

*

*.Proto        char aux_inp(int port);

*

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

*                 0 - COM1, 1 - COM2

*

*.Return       Принятый символ

**/

char aux_inp(int port)

{

  unsigned status_reg, inp_reg;

  status_reg = 0x3fd - 0x100 * port;

  inp_reg = status_reg - 5;

  while( (inp(status_reg) & 1) == 0 );

  return(inp(inp_reg));

}


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