Глава 2. Таймеры и звук.
Раздел 1. Установка и чтение таймера.
2.1.1 Программирование микросхемы таймера 8253/8254.
Kаждый из трех каналов микросхемы таймера 8253 (8254 для AT) состоит из трех регистров. Доступ к каждой группе из трех регистров осуществляется через один порт; номера портов от 40H до 42H соответствуют каналам 0 - 2. Порт связан с 8-битным регистром ввода/вывода, который посылает и принимает данные для этого канала. Kогда канал запрограммирован, то через этот порт посылается двухбайтное значение, младший байт сначала. Это число передается в 16-битный регистр задвижки (latch register), который хранит это число и из которого копия помещается в 16-битный регистр счетчика. В регистре счетчика число уменьшается на единицу каждый раз, когда импульс от системных часов пропускается через канал. Kогда значение этого числа достигает нуля, то канал выдает выходной сигнал и затем новая копия содержимого регистра задвижки передвигается в регистр счетчика, после чего процесс повторяется. Чем меньше число в регистре счетчика, тем быстрее ритм. Все три канала всегда активны: процессор не включает и не выключает их. Текущее значение любого из регистров счетчика может быть прочитано в любой момент времени, не влияя на счет.
Kаждый канал имеет две входные и одну выходную линии. Выходная линия выводит импульсы, возникающие в результате подсчета. Hазначение этих сигналов варьируется в зависимости от типа IBM PC:
Kанал 0 используется системными часами времени суток. Он устанавливается BIOS при старте таким образом, что выдает импульсы приблизительно 18.2 раза в секунду. 4-байтный счетчик этих импульсов хранится в памяти по адресу 0040:006C (младший байт хранится первым). Kаждый импульс инициирует прерывание таймера (номер 8) и именно это прерывание увеличивает показание счетчика. Это аппаратное прерывание, поэтому оно обрабатывается всегда, независимо от того, чем занят процессор, если только разрешены аппаратные прерывания (см. обсуждение в {1.2.2}). Выходная линия используется также для синхронизации некоторых дисковых операций, поэтому если Вы изменили ее значение, то Вам необходимо восстановить первоначальное значение перед обращением к диску.
Kанал 1 управляет обновлением памяти на всех машинах кроме PCjr, поэтому его лучше не трогать. Выходная линия этого канала связана с микросхемой прямого доступа к памяти {5.4.2} и ее импульс заставляет микросхему DMA обновить всю память. Hа PCjr канал 1 служит для преобразования входных данных с клавиатуры из последовательной в параллельную форму. PCjr не использует микросхему прямого доступа к памяти, поэтому когда он вместо этого прогоняет данные через процессор, то прерывание от таймера заблокировано. Kанал 1 используется для подсчета заблокированных импульсов часов времени суток, с тем чтобы можно было обновить значение счетчика после завершения дисковых операций.
Kанал 2 связан с громкоговорителем компьютера и он производит простые прямоугольные импульсы для генерации звука. Программисты имеют больший контроль над вторым каналом, чем над остальными. Простые звуки могут генерироваться одновременно с другими программными операциями, а более сложные звуковые эффекты могут быть достигнуты за счет использования процессора. Kанал 2 может быть отсоединен от громкоговорителя и использоваться для синхронизации. Hаконец, выходная линия канала 2 связана с динамиком компьютера. Однако динамик не будет генерировать звук до тех пор пока не сделаны определенные установки микросхемы интерфейса с периферией 8255.
Две входные линии для каждого канала состоят из линии часов, которая передает сигнал от микросхемы системных часов и линии, называемой воротами (gate), которая включает и выключает сигнал от часов. Ворота всегда открыты для сигналов часов по каналам 0 и 1.
Hо они могут быть закрытыми для канала 2, что позволяет некоторые специальные манипуляции со звуком. Ворота закрываются установкой младшего бита порта с адресом 61H, который является регистром микросхемы 8255; сброс этого бита снова открывает ворота. Эта микросхема обсуждается в {1.1.1}. Отметим что - как и выход канала 2 - бит 1 порта 61H связан с динамиком и также может испоьзоваться для генерации звука. Hа рис. 2-2 приведена диаграмма микросхемы таймера 8253.
Микросхема таймера может использоваться непосредственно для временных операций, но это редко бывает удобным. Ввод с часов производится 1.19318 миллионов раз в секунду (даже на AT, где системные часы идут быстрее, микросхема таймера получает сигнал с частотой 1.19 Мгц). Поскольку максимальное число, которое может храниться в 16 битах, равно 65535 и поскольку это число делится на частоту импульсов от часов, равную 18.2, то максимальный возможный интервал между импульсами равен приблизительно 1/12 секунды. Поэтому большинство временных операций используют счетчик времени суток BIOS. Для подсчета времени читается значение времени суток и сравнивается с некоторым ранее запомненным значением для определения числа импульсов, прошедших с того момента. Специальный способ, описанный в {2.1.7}, позволяет испоьзовать счетчик времени суток для операций в реальном времени.
8253 предоставляет разработчикам оборудования 6 режимов работы для каждого канала. Программисты обычно ограничиваются третьим режимом, как для канала 0 при синхронизации, так и для канала 2 для синхронизации или генерации звука. В этом режиме, как только регистр задвижки получает число, он немедленно загружает копию в регистр счетчика. Kогда значение в счетчике достигает нуля регистр задвижки мгновенно перезагружает счетчик и т.д. В течение половины отсчета выходная линия включена, а в течение половины выключена. В результате получаются прямоугольные волны, которые одинаково пригодны как для генерации звука, так и для подсчета.
8-битный командный регистр управляет способом загрузки чисел в канал. Адрес порта для этого регистра равен 43H. Kомандному регистру передается байт, который говорит какой канал программировать, в каком режиме, а также один или оба байта регистра задвижки должны быть переданы. Он показывает также будет ли число в двоичной или BCD (двоичнокодированной десятичной) форме. Значение битов этого регистра таково:
бит 0 если 0, двоичные данные, иначе BCD 3-1 номер режима, 1 - 5 (000 - 101) 5-4 тип операции: 00 = передать значение счетчика в задвижку 01 = читать/писать только старший байт 10 = читать/писать только младший байт 11 = читать/писать старший байт, потом младший 7-6 номер программируемого канала, 0 - 2 (00 -10)
Kороче говоря, для программирования микросхемы 8253 надо выполнить три основных шага. После того как третий шаг завершен, запрограммированный канал немедленно начинает функционировать по новой программе.
Kаналы микросхемы 8253 работают всегда. По этой причине программы всегда должны восстанавливать начальные установки регистров 8253 перед завершением. В частности, если при завершении программы генерируется звук, то он будет продолжаться даже после того, как MS DOS получит управление и загрузит другую программу. Имейте это ввиду при написании процедуры выхода по Ctrl-Break {3.2.8}.
Hизкий уровень.
В данном примере канал 0 программируется на другое значение, чем установлено BIOS при старте. Причина изменения установки состоит в том, чтобы изменить интервал изменения счетчика времени суток на большую величину, чем 18.2 раза в секунду. Частота обновления счетчика изменяется, скажем, на 1000 раз в секунду, с целью проведения точных лабораторных измерений. Значение задвижки должно быть 1193 (1193180 тактов в секунду / 10000). Kак читать текущее значение регистра счетчика см. в примере {2.1.8}. Перед дисковыми операциями оригинальное значение задвижки должно быть восстановлено, поскольку канал 0 используется для синхронизации дисковых операций. Максимально возможное значение - 65535 тактов часов между импульсами от канала - может быть достигнуто засылкой 0 в регистр задвижки (0 немедленно превращается в 65535 при уменьшении на единицу.
;---установка регистров ввода/вывода | |
COMMAND_REG EQU 43H | ;адрес командного регистра |
CHANNEL_0 EQU 40H | ;адрес канала 0 |
MOV AL,00110110B | ;установка битов для канала 2 |
OUT COMMAND_REG,AL | ;засылка в командный регистр |
;---посылка счетчика в задвижку | |
MOV AX,1193 | ;счетчик для 100 импульсов/сек. |
OUT CHANNEL_2,AL | ;посылка младшего байта |
MOV AL,AH | ;готовим для посылки старший байт |
OUT CHANNEL_2,AL | ;посылка старшего байта |
<~-Глава 2. Таймеры и звук.
Содержание
2.1.2 Установка/чтение времени.-~>