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

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

© Александр Фролов, Григорий Фролов
Том 33, М.: Диалог-МИФИ, 1997, 304 стр.

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

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

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

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

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

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

·       40h - канал 0;

·       41h - канал 1;

·       42h - канал 2;

·       43h - управляющий регистр

Формат управляющего регистра

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

Поля регистра

Описание

0

Поле BCD:

0 - двоичный режим;

1 - двоично-десятичный режим

1-3

Поле M:

000 - режим 0;

001 - режим 1;

X10 - режим 2;

X11 - режим 3;

100 - режим 4;

101 - режим 5

4-5

Поле RW:

00 - код команды CLC (запомнить CE);

01 - чтение/запись старшего байта;

10 - чтение/запись младшего байта;

11 - чтение/запись младшего, затем старшего байта

6-7

Поле SC:

00 - канал 0;

01 - канал 1;

10 - канал 2;

11 - код команды RBC (чтение состояния канала)

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

Поле M определяет режимы работы таймера:

·       0 - прерывание от таймера;

·       1 - программируемый ждущий мультивибратор;

·       2 - программируемый генератор импульсов;

·       3 - генератор меандра;

·       4 - программно-запускаемый одновибратор;

·       5 - аппаратно-запускаемый одновибратор

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

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

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

Формат команды чтения слова состояния канала

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

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

Поле

Описание

0

Всегда равно 0

1

1 - выбор канала 0

2

1 - выбор канала 1

3

1 - выбор канала 2

4

Поле STAT:

0 - читать состояние каналов;

1 - не читать состояние каналов

5

Поле CNT:

0 - запомнить текущее содержимое CE;

1 - не запоминать содержимое CE

6-7

код команды RBC - 11

Формат слова состояния канала

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

Поля регистра

Описание

0

Поле BCD:

0 - двоичный режим;

1 - двоично-десятичный режим

1-3

Поле M:

000 - режим 0;

001 - режим 1;

X10 - режим 2;

X11 - режим 3;

100 - режим 4;

101 - режим 5

4-5

Поле RW:

00 - код команды CLC (запомнить CE);

01 - чтение/запись старшего байта;

10 - чтение/запись младшего байта;

11 - чтение/запись младшего, затем старшего байта

6

FN: флаг перезагрузки констант

7

OUT: состояние выхода OUT

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

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

Последовательность действий

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

·       вывести в порт управляющего регистра с адресом 43h управляющее слово;

·       требуемое значение счетчика посылается в порт канала (адреса 40h-42h), причем вначале выводится младший, а затем старший байты значения счетчика.

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

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

·       вывести в порт управляющего регистра код команды CLC (команда запоминания содержимого регистра CE);

·       вывести в порт управляющего регистра код команды запроса на чтение/запись в регистры канала (поле RW должно содержать 11);

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

Программа TIMERST

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

Листинг 5.1. Файл timerst\timerst.с


	// =====================================================
	// Просмотр слова состояния и содержимого
	// счетчиков таймера
	//
	// (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>
	
	int 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-------\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);
	  return 0;
	}
[Назад] [Содеожание] [Дальше]