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

Аппаратное обеспечение IBM PC

© Александр Фролов, Григорий Фролов
Том 2, книга 1, М.: Диалог-МИФИ, 1992.

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

5.2. Программирование таймера на уровне портов

Таймеру соответствуют четыре порта ввода/вывода со следующими адресами:

  • 40h - канал 0;
  • 41h - канал 1;
  • 42h - канал 2;
  • 43h - управляющий регистр.

Приведем формат управляющего регистра:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦   ¦   ¦     ¦ ¦
LT+T+T+T+T+-+T+T-
LT- LT- L=T=- L= BCD: 0 - двоичный счет;
  ¦   ¦    ¦           1 - двоично-десятичный счет.
  ¦   ¦    ¦
  ¦   ¦    L===== M:   000 - режим 0;
  ¦   ¦                001 - режим 1;
  ¦   ¦                X10 - режим 2;
  ¦   ¦                X11 - режим 3;
  ¦   ¦                100 - режим 4;
  ¦   ¦                101 - режим 5.
  ¦   ¦
  ¦   L========== RW:  00 - код команды CLC (запомнить CE);
  ¦                    01 - чтение/запись старшего байта;
  ¦                    10 - чтение/запись младшего байта;
  ¦                    11 - чтение/запись младшего, затем
  ¦                         старшего байта.
  ¦              
L============== SC:  00 - канал 0;
01 -    канал 1;
10 -    канал 2;
11 -    код команды RBC (чтение состояния канала).


Поле BCD определяет формат константы, использующейся для счета - двоичный или двоично-десятичный. В двоично-десятичном режиме константа задается в диапазоне 1-9999.

Поле M определяет режимы работы микросхемы 8254:

  • 0 - прерывание от таймера;
  • 1 - программируемый ждущий мультивибратор;
  • 2 - программируемый генератор импульсов;
  • 3 - генератор меандра;
  • 4 - программно-запускаемый одновибратор;
  • 5 - аппаратно-запускаемый одновибратор.

Мы будем рассматривать только режим 3, так как именно он используется в каналах 0 и 2.

Поле RW определяет способ загрузки констант через однобайтовый порт. Если в этом поле задано значение 00, это управляющее слово будет использоваться для фиксации текущего содержимого регистров счетчика CE в буферном регистре OL с целью чтения программой. Это код команды CLC - фиксация регистров. Код канала, для которого будет выполняться фиксация, должен быть указан в поле SC. Поля M и BCD при этом не используются.

Поле SC определяет номер канала, для которого предназначено управляющее слово. Если в этом поле задано значение 11, будет выполняться чтение состояния канала.

Приведем формат команды RBC чтения слова состояния канала:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦   ¦ ¦ ¦ ¦ ¦ ¦ ¦
LT+T+T+T+T+T+T+T-
LT- ¦ ¦ ¦ ¦ ¦ L= равно 0.
  ¦  ¦ ¦ ¦ ¦ ¦
  ¦  ¦ ¦ ¦ ¦ L=== 1 - выбор канала 0. 
  ¦  ¦ ¦ ¦ L===== 1 - выбор канала 1.
  ¦  ¦ ¦ L======= 1 - выбор канала 2.
  ¦  ¦ ¦
  ¦  ¦ L========= STAT: 0 - читать состояние каналов;
  ¦  ¦                  1 - не читать состояние каналов.
  ¦  ¦
  ¦  L=========== CNT:  0 - запомнить текущее содержимое CE;
  ¦                     1 - не запоминать содержимое CE.
  ¦
  L============== код команды RBC - 11.


С помощью этой команды вы можете выполнять операции чтения состояния каналов либо запоминание регистра счетчика CE каналов. Можно выполнять эти операции как для отдельных каналов, так и для всех каналов одновременно, если установить соответствующие биты (1, 2, 3) в 1.

Формат слова состояния канала напоминает формат регистра управляющего слова, за исключением двух старших разрядов 7 и 6:

7 6 5 4 3 2 1 0
T-T-T-T-T-T-T-¬
¦ ¦ ¦   ¦     ¦ ¦
LT+T+T+T+T+-+T+T-
¦ ¦ LT- L=T=- L= BCD: 0 - двоичный счет;
 ¦ ¦  ¦    ¦           1 - двоично-десятичный счет.
 ¦ ¦  ¦    ¦
 ¦ ¦  ¦    L===== M:   000 - режим 0;
 ¦ ¦  ¦                001 - режим 1;
 ¦ ¦  ¦                X10 - режим 2;
 ¦ ¦  ¦                X11 - режим 3;
 ¦ ¦  ¦                100 - режим 4;
 ¦ ¦  ¦                101 - режим 5.
 ¦ ¦  ¦
 ¦ ¦  L========== RW:  00 - код команды CLC (запомнить CE);
 ¦ ¦                   01 - чтение/запись старшего байта;
 ¦ ¦                   10 - чтение/запись младшего байта;
 ¦ ¦                   11 - чтение/запись младшего, затем
 ¦ ¦                        старшего байта.
 ¦ ¦             
 ¦ L============= FN:  флаг перезагрузки констант;
 L=============== OUT: состояние выхода OUT.



Разряд FN используется, в основном, в режимах 1 и 5 для определения, произошла ли загрузка константы из регистра CR в регистр счетчика CE.

Разряд OUT позволяет определить состояние выходной линии канала OUT в момент выполнения команды RBC.

Для программирования канала таймера необходимо выполнить следующую последовательность действий:

  • вывести в порт управляющего регистра с адресом 43h управляющее слово;
  • требуемое значение счетчика посылается в порт канала (адреса 40h...42h), причем вначале выводится младший, а затем старший байты значения счетчика.

Сразу после этого канал таймера начнет выполнять требуемую функцию.

Для чтения текущего содержимого счетчика CE необходимо выполнить следующее:

  • вывести в порт управляющего регистра код команды CLC (команда запоминания содержимого регистра CE);
  • вывести в порт управляющего регистра код команды запроса на чтение/запись в регистры канала (поле RW должно содержать 11);
  • двумя последовательными командами ввода из порта нужного канала ввести младший и старший байты текущего сосотояния счетчика CE.

Для чего вам может понадобиться перепрограммирование каналов таймера?

Если вам надо повысить точность измерения времени, выполняемого с помощью канала 0 таймера, вы можете увеличить частоту генерируемых этим каналом импульсов (стандартно 18,2 Гц). По окончании измерений режим работы канала необходимо восстановить для правильного функционирования системы.

Канал 2, подключенный к громкоговорителю, вы можете использовать для генерации различных звуков или музыки, о чем мы расскажем немного позже. Этот же канал может быть использован для генерации случайных чисел.

Приведем пример программы, отображающей слово состояния и содержимое счетчика для всех трех каналов таймера:

#include <stdio.h>
#include <conio.h>

main() {

        unsigned i;

        printf("\n\nКанал 0"
                     "\n-------"
                      "\n");

// Читаем слово состояния канала,
// команда 0xe2 = 11100010B

        outp(0x43, 0xe2);

        printf("\nСлово состояния канала: %02.2X",
                inp(0x40));

// Читаем текущее состояние регистра счетчика
// канала. Для этого вначале выдаем команду CLC
// для канала 0. Код этой команды - 0x00

        outp(0x43, 0x00);

// Вводим младший и старший байты счетчика
// и отображаем его.

        i = inp(0x40);
        i = (inp(0x40) << 8) + i;

        printf("\nРегистр счетчика:       %04.4X",i);

// Повторяем те же действия для 1 и 2 каналов.

        printf("\n\nКанал 1"
                    "\n-------"
                         "\n");

        outp(0x43, 0xe4);
        printf("\nСлово состояния канала: %02.2X",inp(0x41));

        outp(0x43, 0x40);


        i = inp(0x41);
        i = (inp(0x41) << 8) + i;

        printf("\nРегистр счетчика:       %04.4X",i);

        printf("\n\nКанал 2"
                    "\n-------");

        outp(0x43, 0xe8);
        printf("\nСлово состояния канала: %02.2X",inp(0x42));

        outp(0x43, 0x80);

        i = inp(0x42);
        i = (inp(0x42) << 8) + i;

        printf("\nРегистр счетчика:       %04.4X",i);

        exit(0);

}


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