1. Работа с таймером мс68нс705с8.
Как уже было рассмотрено выше, таймер может генерировать прерывания по трем событиям:
· переполнение счетчика таймера (прерывание TOI);
· обнаружение на входе TCAP заданного сигнала (прерывание ICI);
· совпадение значения счетчика таймера с содержимым регистра OCR (прерывание OCI);
Проиллюстрируем использование прерываний простой программой, которая по переполнению таймера складывает содержимое портов А и В и выводит результат в порт В. Напомним, что информация в порт A поступает с переключателей, а при выводе в порт B информация отображается на светодиодах.
Основная программа:
300 LDA #$FF Программируем
302 STA $05 порт В на вывод.
304 CLR $01 Очищаем порт В.
306 LDA #$20 Разрешаем прерывания
308 STA $12 по переполнению таймера.
30А WAIT Разрешаем прерывания и
30В BRA 30A ждем переполнения таймера.
Подпрограмма обработки прерывания:
800 LDA $01 Складываем содержимое
802 ADD $0 портов А и В.
804 STA $01 Сохраняем результат в порте В.
806 LDA $13 Сбрасываем флаг
808 LDA $19 переполнения таймера.
80А RTI Возврат из подпрограммы.
В ячейку памяти $1FF8, где располагается вектор прерывания TOI, запишем адрес подпрограммы обработки прерывания по преполнению таймера ($0800) и предусмотрим возможность по нажатию кнопки USER RESET начинать счет сначала, для чего по адресу $1FFE (вектор RESET) занесем число $0300. Ниже приводятся некоторые пояснения к программе.
В ячейке $12 располагается регистр управления таймером (TCR), пятый бит которого является флагом разрешения прерываний по переполнению таймера. Записывая туда единицу командами с адресами $306 и $308, мы разрешаем соответствующее прерывание.
При переполнении таймера устанавливается флаг TOF в регистре статуса таймера (TSR), расположенном по адресу $13. Этот флаг необходимо сбросить в подпрограмме обработки прерывания, так как в противном случае, после выхода из нее по команде RTI, прерывания будут разрешены, а установленный флаг TOF приведет к генерации нового прерывания. Чтобы его сбросить, необходимо обратиться сначала к TSR, а затем к младшему байту регистра счетчика таймера (адрес $19). Это делают команды, находящиеся по адресам $806 и $808.
Поскольку по адресу $0 находится регистр данных порта А, к которому подключены переключатели, то команда сложения по адресу $802 использует в качестве своих аргументов содержимое порта В, скопированное в аккумулятор, и значение, считанное с переключателей в порт А.
Запустите программу с адреса $300. На светодиодах начнут отображаться постоянно увеличивающиеся числа (если, конечно, на переключателях установлен не 0). Изменяя положение переключателей, убедитесь в правильной работе программы.
При нажатии на USER RESET программа начнет считать сначала, так как управление при этом переходит по адресу $300.
Выйти из программы можно, нажав кнопку MASTER RESET.
Теперь рассмотрим следующий тип прерываний от таймера - прерывание ICI, генерируемое функцией Input Capture. Работа функции основана на обработке сигнала, поступающего на вход TCAP микроконтроллера. Фиксация срабатывает при обнаружении на входе фронта или спада сигнала, в зависимости от состояния бита IEDG в управляющем регистре таймера TCR. При IЕDG=0 прерывания происходят по переднему фронту сигнала (переход с уровня логического "0" на уровень логической "1" ). При IEDG=1, прерывания обнаруживаются по заднему фронту сигнала на входе TCAP микроконтроллера. В момент срабатывания Input Capture устанавливается флаг ICF, содержимое счетчика таймера переписывается в регистр ICR и, кроме того, если установлен флаг ICIE в регистре TCR, то генерируется прерывание ICI, Такой механизм позволяет измерять временные параметры сигнала на входе TCAP. Для формирования этого сигнала к входу TCAP подключена кнопка IC, установленная на дополнительной плате.
В качестве иллюстрации вышесказанного, приведем пример программы, измеряющей длительность нажатия на кнопку IC. Время нажатия определяется путем подсчета переполнений таймера.
Основная программа :
300 LDA #$FF Переключаем порт В
302 STA $05 на вывод.
304 CLR $01 Гасим светодиоды.
306 LDA #$80 Разрешаем прерывания IC по
308 STA $12 переднему фронту сигнала.
30A WAIT Ожидание нажатия на кнопку IC.
30B LDA #$A2 Разрешаем прерывания TOI и IC
30D STA $12 по заднему фронту сигнала.
30F CLRA Очистка счетчика переполнений.
310 WAIT Ожидание переполнения или нажатия на IC.
311 BRCLR 7,$1,$317 Если светодиоды не горят (поступило прерывание IC), то переход,
314 INCA иначе увеличение счетчика переполнений.
315 BRA $310 Возврат к ожиданию.
317 STA $1 Вывод результата на светодиоды.
319 BRA $319 Бесконечный цикл.
Подпрограмма обработки прерывания :
800 BRCLR 7,$13,$805 Если прерывание по переполнению, то переход
803 COM $01 иначе инвертирование светодиодов.
805 LDA $15 Очистка флагов
807 LDA $19 TOF и ICF.
809 RTI Возврат из подпрограммы.
По адресам $300-$308 находятся команды, производящии начальную установку, после чего программа переходит в режим ожидания нажатия на IC. После нажатия на кнопку IC, запускается счетчик переполнения таймера (команды по адресам $30F-$315) Работа счетчика прекращается в момент отпускания кнопки IC ( команда $311 ), после чего значение счетчика (регистр А) выводится на светодиоды. При любом из двух прерываний от таймера ( по IC и по переполнению ), вызывается подпрограмма обработки прерывания по адресу $800, которая очищает флаги прерываний в регистре статуса таймера и, в случае обработки прерывания IC, инвертирует содержимое светодиодов.
Поставте точку останова по адресу $319, запишите адрес подпрограммы обработки прерывания ( $0800 ) по адресу $1FF8 и запустите программу. Светодиоды должны погаснуть . После этого нажмите на кнопку IC и удерживайте ее несколько секунд. При этом светодиоды должны гореть. После отпускания кнопки на светодиодах появится результат-содержимое регистра А.
Как уже было сказано выше, время нажатия на кнопку IC измеряется в переполнениях таймера. Так как период тактовых импульсов таймера 2 мкс. (частота тактирования 500 кГц), то переполнения таймера происходят каждые 2*65536=131072 мкс., то есть, чтобы полученный вами результат перевести в реальное время, нужно содержимое регистра А умножить на 0,131 с. Однако при таком методе измерения длительности возникает погрешность измерения, не превышающая ±0,131 с., что вполне приемлемо для измерения интервалов времени порядка нескольких секунд. Если же измеряемое время невелико (сравнимо с 0,1 с.), то требуется более точный метод измерения времени, в котором необходимо учитывать не только количество переполнений, но и содержимое таймера в момент начала и окончания измерения временного интервала. При этом удобно использовать то, что при нажатии на кнопку IC содержимое счетчика таймера переписывается в регистр ICR. В качестве примера приведена программа, которая позволяет измерить быстроту реакции человека.
Правила работы с программой следующие: после запуска программы необходимо дождаться зажигания светодиодов и затем, как можно быстрее нажать на кнопку IC. После этого на светодиодах и в регистре А появится время реакции примерно в сотых долях секунды.
Основная программа :
300 LDA #$FF Переключаем порт В
302 STA $05 на вывод.
304 CLR $01 Гасим светодиоды.
306 LDA #$A0 Разрешаем прерывания по переполнению
308 STA $12 таймера и нажатию на кнопку IC.
39A LDA $13 Сбрасываем
30C LDA $19 флаг TOF.
30E AND #$1F Формируем случайное число
310 ADD #$10 в диапазоне $10..$2F.
312 WAIT Случайная задержка на время от 2 до 3 секунд
313 BRSET 7,$1,$326 с проверкой на фальшстарт.
316 DECA
317 BNE $312
319 COM $01 Зажигаем светодиоды.
31B CLRA Очищаем счетчик количества переполнений.
31C WAIT Ждем прерывания от таймера.
31D SEI Запрещаем прерывания.
31E BRCLR 7,$1,$32A Если светодиоды не горят, то переходим к
преобразованию результатов.
321 INCA Иначе увеличиваем счетчик переполнений таймера.
322 CMP #$F Если этот счетчик не переполнился,
324 BNE $31C то возврат на WAIT.
326 LDA #$FF Иначе выход по
328 BRA $338 переполнению счетчика.
32A LSLA Сдвиг
32B LSLA аккумулятора
32C LSLA на четыре
32D LSLA разряда влево.
32E LDX $14 Загрузка старшего байта регистра ICR
в регистр X для обработки.
330 LSRX Сдвиг содержимого
331 LSRX регистра X
332 LSRX на четыре
333 LSRX разряда вправо.
334 STX $01 Сложение содержимого
336 ADD $01 регистров A и X и запись
338 STA $01 результата в порт B.
33A BRA $33A Бесконечный цикл.
Подпрограмма обработки прерывания :
800 BRCLR 7,$13,$805 Если поступило прерывание от кнопки IC,
803 COM $01 то инвертировать состояние светодиодов.
805 LDA $19 Сбрасываем флаги
807 LDA $15 TOF и ICF.
809 RTI Возврат из подпрограммы.
Пояснения к программе:
1. Случайное число, которое было сформировано командами, стоящими по адресам $30C-$310, используется далее для организации случайной задержки командами с адресам $312-$317
2. В программе предусмотрена обработка ситуации, когда кнопку IC нажали раньше времени (команда по адресу $314). В этом случае в аккумулятор командами с адресами $326 и $328 заносится число #$FF, что символизирует фальшстарт.
3. Частота тактирования таймера 500 кГц (тактовая частота ОЭВМ, деленная на 4), то есть период тактовых импульсов таймера 2 мкс. Так как мы подаем сигнал к старту (зажигаем светодиоды) сразу после переполнения таймера, то при нажатии на кнопку IC в регистрах $14 и $15 будет содержаться время реакции. Однако, такой способ пригоден лишь для измерения интервалов времени, не превышающих время переполнения таймера (0,131 с.). Для измерения более длинных интервалов времени в программе предусмотрен счетчик переполнений таймера в регистре А, от которого используется только младшая тетрада. Это дает возможность увеличить максимальное время ожидания до 0,131*16=2,097 с. Таким образом, младшая тетрада регистра А и два байта регистра данных IC образуют 20-ти битный счетчик. Мы от него используем только старшие 8 бит.
4. Задачей команд, расположенных по адресам $32А-$336, является преобразование двухбайтного кода, хранящегося в регистрах А и Х, в однобайтовый так, чтобы старшая тетрада регистра Х стала младшей тетрадой результата, а младшая тетрада регистра А стала старшей тетрадой результата.
5. Подпрограмма обработки прерывания, расположенная с адреса $800, проверяет тип вызвавшего ее прерывания. Если была нажата кнопка IC, то информация на светодиодах инвертируется. Помимо этого сбрасываются флаги TOF и ICF.
Установите точку останова по адресу $33A и запишите адрес подпрограммы обработки прерывания в ячейки $1FF8 и $1FF9. Запустите программу с адреса $300 и убедитесь в правильности ее работы.
Теперь рассмотрим последний тип прерываний от таймера - прерывание OCI, генерируемое функцией Output Compare. Напомним, что эта функция срабатывает при совпадении содержимого счетчика таймера со значением в регистре OCR. При этом устанавливается флаг OCF, значение бита OLVL регистра TCR выводится на выход TCMP и, кроме того, если установлен флаг OCIE в регистре TCR, то генерируется прерывание OCI. Для отображения состояния вывода TCMP на дополнительной плате установлен светодиод OC.
В качестве примера использования прерывания OC рассмотрим программу, которая управляет яркостью светодиода OC в зависимости от состояния переключателей порта A. Изменение яркости основано на регулировании скважности сигнала, подаваемого на светодиод. Напомним, что скважностью называется отношение периода сигнала к длительности импульса. Регулирование скважности производится с переключателей.
Основная программа :
300 CLR $04 Программируем порт А на ввод.
302 LDA #$40 Разрешаем прерывания
304 STA $12 по ОС.
306 WAIT Ожидаем
307 BRA $306 прерывания.
Подпрограмма обработки прерывания :
800 LDA $0 Читаем информацию с переключателей.
802 AND #$1F Маскируем три старших бита.
804 BRCLR 0,$12,$80A Если OLVL=0, то переход на $80A.
807 NEGA Вычисляем дополнение
808 ADD #$1F содержимого порта А до $1F.
80A INCA
80B ADD $16 Добавляем
80D STA $16 приращение в
80F LDA $13 регистр ОСR
811 LDA $17 и сбрасываем
813 STA $17 флаг OCF.
815 LDA $12 Инвертируем
817 EOR #$01 OLVL
819 STA $12 в TCR.
81B RTI Возврат из подпрограммы.
Как видно, действия по регулированию яркости сосредоточены, в основном, в подпрограмме обработки прерывания OC. Разберем их более подробно.
- из порта А читается число N<32 (выполняется командами по адресам $800 и $802);
- светодиод зажигается на (N+1)*256 и гасится на (32-N)*256 тактов таймера (командами с адресами $804-$813).
Чтобы отличить, какое из двух чисел N*256 или (32-N)*256 использовать в качестве приращения в регистре ОС предусмотрены команды с адресами $804-$808.
Команды по адресам $815-$819 инвертируют состояние бита OLVL и, тем самым, задают состояние светодиода (горит или не горит ) при следующем вызове подпрограммы.
Следует отметить необходимость команды INCA по адресу $80A. Если бы ее не было, то для вычисления приращение OCR использовалось бы число в диапазоне 0-31 ( а не 1-32 ). В случае, когда на переключателях установлен 0, приращение OCR также равно 0, и за время выполнения команд $80F-$81B таймер успеет превысить значение, хранящееся в регистре данных ОС. Это приведет к тому, что следующее прерывание наступит более, чем через 60000 тактов, что составляет около 0,1 с., в то время, как нам необходимо было получить задержку, близкую к 0.
Теперь запишите адрес подпрограммы обработки прерывания ($0800) по адресу $1FF8 и запустите программу с адреса $300.
Убедитесь в том, что программа работает правильно. Затем замените команду $80A INCA на NOP и проверьте справедливость сказанного выше об этой команде.
2. COP-таймер.
СОР-таймер обычно используется в ситуациях, когда необходима защита от сбоев в работе микроконтроллера, возникающих по каким-либо причинам. Назначение СОР-таймера - генерировать сигнал сброса микроконтроллера через определенный промежуток времени (он задается в регисре $1E). В случае правильной работы, программа должна периодически сбрасывать СОР-таймер, тогда отсчет времени начинается сначала. Если же в работе программы возник сбой, то через некоторое время COP-таймер сработает, и после сброса управление снова будет передано программе пользователя. Для сброса СОР-таймера необходимо записать в рагистр $1D сначала $55, затем $AA.
В качестве примера рассмотрим программу, которая мигает светодиодами и каждые 0,5с посылает в регистр $1D два числа: то, что записано в порте А (то есть выставлено на переключателях), и дополнительное к нему. Таким образом, если на переключателях поставить число $55, то программа будет автоматически сбрасывать СОР-таймер. В любом другом случае произойдет сброс микроконтроллера.
Основной блок :
300 LDA #$FF Программируем
STA $5 порт B на вывод.
CLR $4 Программируем
порт A на ввод.
CLR $1 Гасим светодиоды.
LDA $7 Устанавливаем время
STA $1E сброса в 1с.
30C CLRA Организуем
30D CLRX задержку
30E DECX примерно
30F BNE $30E на
311 DECA 0,5с.
312 BNE $30D
314 LDA $1 Инвертируем
316 EOR #$C0 состояние
318 STA $1 светодиодов.
31А JSR $400 Вызываем подпрограмму сброса СОР-таймера.
31D BRA $30C Возврат на задержку.
Подпрограмма сброса СОР-таймера :
400 LDA $0 Читаем порт А.
STA $1D Посылаем данные в $1D.
COMA Вычисляем дополнение.
STA $1D Снова посылаем данные в $1D.
RTS Возврат из подпрограммы.
Подпрограмма обработки прерывания RESET :
800 LDA $1E
802 LDX $1E
804 NOP
По адресам $30C..$31D находится программа мигания светодиодами. С адреса $400 расположена подпрограмма сброса СОР-таймера.
Поставьте точку останова по адресу $804, запишите $800 по адресу $1FFE (вектор прерывания RESET) и запустите программу.
Если на переключателях установлено не $55, то примерно через секунду программа закончит свою работу. При этом пятый бит регистра $1E установится в 1, что говорит о инициировании сброса аппаратурой СОР-таймера.
Установите на переключателях $55 и снова запустите программу. Должны замигать светодиоды. Если изменить положение переключателей на короткое время (менее 1с), то все останется по прежнему, и программа продолжит свою работу. Но стоит задержать переключатель в другом положении на более длительный промежуток времени (более 1с), как произойдет вызов подпрограммы по адресу $800. Значит, СОР-таймером было инициировано прерывание RESET. Содержимое регистра А, скопированное из $1E командой $800 LDA $1E, подтверждает это.
Контрольные вопросы и задания.