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