Для чего нужны прерывания?

Прерывание - это остановка извне выполнения текущей программы на время выполнения некоторой подпрограммы (которая называется "обработчик прерывания").
Что это значит?
Прерывание возникает по некоторому внешнему сигналу, поступающему в процессор. При этом, основная программа останавливается в совершенно произвольном месте (где ее застанет прерывание), и начинается выполнение подпрограммы-обработчика. По окончании работы обработчика, выполнение основной программы возобновляется с места останова. Это бывает очень полезно, если необходимо оперативно среагировать на какое-то внешнее событие. Например, на нажатие кнопочки, на начало передачи данных… И т.д. и т.п.
В AT90s2313 существует 11 событий, по которым можно установить прерывания (прерывание - дело добровольное, хочешь - ставишь, хочешь - не ставишь). Что это за события? Открываем даташит по микросхеме на стр.19 и смотрим табличку "Reset and interrupt vectors".
Для ленивых привожу ее здесь:

Английский знаем? Ну ладно, переведу :)
Reset - прерывание по сбросу (подача 0 на вывод микросхемы "Reset"; или включение питания; или по переполнению сторожевого таймера) INT_0 - первое внешнее прерывание (сигнал на вывод микросхемы "INT0") INT_1 - второе внешнее прерывание (сигнал на "INT1") Timer1_capt1 - прерывание защелки 1-го таймера Timer1_comp1 - прерывание компаратора 1-го таймера Timer1_OVF1 - по переполнению 1-го таймера Timer0_OVF0 - по переполнению 0-го таймера UART_RX - по окончанию приема пакета по протоколу UART UART_UDRE - по опустошению регистра данных UART UART_TX - по окончанию передачи пакета по UART ANA_COMP - прерывание аналогового компаратора Если некоторые слова вам еще не знакомы - не отчаивайтесь, так и должно быть. Давайте лучше разбираться, что такое - Interrupt Vectors - Вектора Прерываний? А это ни что иное, как указатели на адрес ПЗУ, на который мы переходим в результате прерывания. Все векторы расположены в самом начале адресного пространства, и занимают первые 11 адресов ПЗУ (с $000 по $00A). Это прекрасно видно из таблицы. То есть, если мы, скажем, хотим активизировать прерывание Timer1_comp1, то мы должны по адресу $004 поставить ссылку на подпрограмму - обработчик этого прерывания. А вообще, лучше расставить в начале программы ссылки на все прерывания. Давайте так и сделаем.
.cseg .org 0 rjmp Reset rjmp INT_0 rjmp INT_1 rjmp Timer1_capt1 rjmp Timer1_comp1 rjmp Timer1_OVF1 rjmp Timer0_OVF0 rjmp UART_RX rjmp UART_UDRE rjmp UART_TX rjmp ANA_COMP Так как эти команды стоят в самом начале программы, значит они как раз таки будут расположены в ПЗУ по первым 11-ти адресам. Таким образом, при каждом прерывании, будет вызываться соответствующий обработчик.
Например: по прерыванию компаратора таймера 1 (Timer1_comp1), мы перескакиваем на адрес $004, то есть - на 5-ю строчку программы. В пятой строчке стоит безусловный переход на метку Timer1_comp1. Где-то ниже в программе, мы пишем обработчик этого прерывания и в его начале ставим эту метку. Вот так все несложно…
Ну а что делать с остальными прерываниями, которые не используются? Надо все равно прописать на них метки (иначе компилятор страшно выругается), но по этим меткам ничего не делать, а тут же выходить.
Кстати, чуть не забыл:
reti - Interrupt return - выход из обработчика прерывания
Итак, пишем:
Reset: INT_0: INT_1: Timer1_capt1: Timer1_comp1: Timer1_OVF1: Timer0_OVF0: UART_RX: UART_UDRE: UART_TX: ANA_COMP: reti Пусть вас не смущает, что столько меток стоят на одну команду: это не страшно, так можно делать. Нельзя ставить несколько ОДИНАКОВЫХ меток…
Теперь в этой куче остается только закомментировать те прерывания, которые мы используем. В частности, в любой программе используется прерывание по сбросу (Reset). Поэтому его комментируем сразу же, а уже непосредственно текст основной программы начинаем с метки Reset.
Ну вот. Теперь возвращаемся к нашим баранам. То есть - бегущим огонечкам.






Рекомендуемый контент




Copyright © 2010-2017 housea.ru. Контакты: info@housea.ru При использовании материалов веб-сайта Домашнее Радио, гиперссылка на источник обязательна.