
Лабораторная работа №4. Структура таймера. Управление таймером
Цель: Изучение особенностей работы системного таймера.
Задача: Создать программу, работающую с системным таймером через порты ввода-вывода. Теоретические сведения:
Современный компьютер содержит устройство, называемое программируемым системным таймером. Таймер позволяет вычислительной системе решать задачи реального времени, а именно:
измерять моменты наступления программно-аппаратных событий;
самостоятельно генерировать такие события в требуемые моменты времени.
Таймер включает в себя целых три устройства — три канала таймера, каждый из которых можно запрограммировать для работы в двоичной или двоично-десятичной системе в одном из шести режимов. Работа каждого из каналов синхронизирована с тактовыми импульсами, поступающими с кварцевого генератора с частотой 1,193 МГц (точнее, 1 193 180 Гц). На большинстве современных материнских плат располагаются два таймера, т.е. число каналов равно шести.
Рис.1 Схема системного таймера
П
о
умолчанию
для всех каналов установлен режим №3.
В этом режиме каналы работают следующим
образом:
в счетчик таймера загружается некоторая константа пересчета в диапазоне 1..65535 (по умолчанию она имеет максимально возможное значение);
по фронту каждого приходящего тактового импульса из счетчика вычитается двойка;
при достижении счетчиком значения 0 на выходе у канала таймера инвертируется значение сигнала "OUT", кроме того в счетчик вновь загружается исходная константа и работа счетчика продолжается;
по фронту сигнала "OUT" (т.е. при каждом втором обнулении счетчика) генерируется некоторое "событие".
Рис. 2 Режим №3 работы таймера
"События" канала 0 заключаются в том, что на контроллер прерываний подаются запросы с приоритетом IRQ0 и, соответственно, в системе возникают прерывания с номером 8 (int 8).
"События" канала 1 заключаются в генерации тактовых импульсов, синхронизирующих системные процессы на материнской плате ПЭВМ.
"События" канала 2 представляют собой прямоугольные импульсы, подающиеся на вход встроенного компьютерного динамика.
Управление таймером через порты ввода-вывода
Для своих нужд программы могут использовать канал 2 (если им не нужен динамик) и канал 4 (если присутствует второй таймер). При необходимости можно перепрограммировать и канал 0, но затем надо будет вернуть его в исходное состояние, чтобы BIOS и DOS могли продолжать работу.
В пространстве портов ввода-вывода для таймера выделена область от 40h до 5Fh:
порт 40h — канал 0 (генерирует IRQ0)
порт 41h — канал 1 (поддерживает обновление памяти)
порт 42h — канал 2 (управляет динамиком)
порт 43h — управляющий регистр первого таймера
порты 44h – 47h — второй таймер компьютеров с шиной MicroChannel
порты 48h – 4Bh — второй таймер компьютеров с шиной EISA
Управление таймером осуществляется путем вывода байта в управляющий порт (43h для первого таймера).
Назначение бит в этом байте:
-
7-6
5-4
3-1
0
Бит 0: формат счетчика
0 — двоичное 16-битное число (0000 – FFFFh)
1 — двоично-десятичное число (0000 – 9999)
Биты 3-1: режим работы канала
000: прерывание IRQ0 при достижении нуля
001: ждущий мультивибратор
010: генератор импульсов
011: генератор прямоугольных импульсов (основной режим)
100: программно запускаемый одновибратор
101: аппаратно запускаемый одновибратор
Биты 5 – 4:
00 — зафиксировать текущее значение счетчика для чтения (в этом случае биты 3 – 0 не используются)
01 — чтение/запись только младшего байта
10 — чтение/запись только старшего байта
11 — чтение/запись сначала младшего, а потом старшего байта
Биты 7 – 6: если не 11 — это номер канала, который будет программироваться: 00,01,10 = канал 0,1,2
Для того чтобы запрограммировать таймер в режиме 3, в котором работают каналы 0 и 2 по умолчанию и который чаще всего применяют в программах, требуется выполнить следующие действия:
Вывести в регистр 43h команду (для канала 2) 10110110h, то есть установить режим 3 для канала 2, и при чтении/записи будет пересылаться сначала младшее слово, а потом старшее.
Послать младший байт начального значения счетчика в порт выбранного канала (42h для канала 2).
Послать старший байт начального значения счетчика в этот же порт.
Например:
mov al, 0B6h ; B6h = 10110110b (10 11 011 0 – канал 2, запись 2 байт, режим 3, двоичное число)
out 43h, al ; Вывести команду в порт 43h
mov al, 0FFh ; Задать в al значение FFh (впрочем, можно задать любое другое)
out 42h, al ; Вывести в порт 42h (канал 2) младший байт, равный FFh
out 42h, al ; Вывести в порт 42h (канал 2) старший байт, равный FFh (итого FFFFh)
После этого таймер немедленно начнет уменьшать введенное число от начального значения к нулю со скоростью 1 193 180 раз в секунду (четверть скорости процессора 8088). Каждый раз, когда это число достигает нуля, оно снова возвращается к начальному значению. Кроме того, при достижении счетчиком нуля канал 0 вызывает прерывание IRQO, а канал 2, если включен динамик, посылает ему начало следующей прямоугольной волны, заставляя его работать на установленной частоте. Начальное значение счетчика для канала 0 по умолчанию составляет 0FFFFh (65 535), то есть максимально возможное. Поэтому точная частота вызова прерывания IRQ0 равна 1 193 180/65 536 = 18,20648 раза в секунду.
Если биты 7 – 6 равны 11, считается, что байт, посылаемый в порт 43h, — команда чтения счетчиков. Её формат отличается от команды программирования канала:
-
7-6
5-4
3-1
0
Бит 0: резерв (должен быть 0)
Биты 3-1: команда относится к каналам 3–1 (001 – 0-й канал, 010 – 1-й, 011 – 0-й + 1-й и т.п.)
Биты 5 – 4: режим чтения
00: сначала состояние канала/потом значение счетчика
01: значение счетчика
10: состояние канала
Биты 7 – 6: 11 (код команды чтения счетчиков)
Если этой командой запрашивается состояние каналов, новые команды будут игнорироваться, пока не прочтется состояние из всех каналов, которые были заказаны битами 3 – 1.
Состояние и значение счетчика данного канала получают чтением из порта, соответствующего требуемому каналу.
Формат байта состояния имеет следующий вид:
бит 7: состояние входа OUTx на момент выполнения команды чтения счетчиков. Так как в режиме 3 счетчик уменьшается на 2 за каждый цикл, состояние этого бита, замороженное командой фиксации текущего значения счетчика, укажет, в каком полуцикле находился таймер
бит 6: 1/0 — состояние счетчика не загружено/загружено (используется в режимах 1 и 5, а также после команды фиксации текущего значения)
биты 5 – 0: совпадают с битами 5 – 0 последней команды, посланной в порт 43h
Чтобы прочитать текущее значение счетчика, надо:
Послать в порт 43h команду фиксации значения счетчика для выбранного канала (биты 5 – 4 равны 00h).
Послать в порт 43h команду перепрограммирования канала без изменения режима его работы, если нужно изменить способ чтения/записи (обычно не требуется).
Прочитать из порта, соответствующего выбранному каналу, младший байт фиксированного значения счетчика.
Прочитать из того же порта старший байт.