оказалась по нужному адресу, — например, можно поставить команду rjmp $0000. Есть и другие, более корректные способы размещения команд по конкретным адресам памяти (с помощью директивы .org), но не будем усложнять. Кстати, надо учесть, что данный способ относится, строго говоря, лишь к МК с памятью не более 8 Кбайт, уже для ATmega16 команды будут другими: вместо 2-байтовой rjmp там применяется 4-байтовая jmp (а вместо команды вызова подпрограммы rcall — call).

* * *

Особое место занимает вектор, расположенный по самому первому, нулевому адресу, у нас он именуется RESET. Вообще говоря, вектор по нулевому адресу — это даже не совсем прерывание, а так называемый вектор сброса — мы ведь неоднократно говорили, что МК начинает выполнение программы с нулевого адреса. Программа из предыдущего раздела с него прямо начиналась (т. е. при включении питания сразу выполнялся первый оператор, потом второй и т. д.), но если задействованы прерывания, мы не можем так поступить. Поэтому в самом первой строке программы обязательно должен стоять указатель на процедуру, которая осуществляется в самом начале работы, и обычно так и называется: RESET. Эта процедура должна начинаться со следующих обязательных строк:

Если указатель стека не установить, то прерывания не заработают. Установка указателя стека для ряда моделей Tiny (в которых отсутствует SRAM) не требуется, а вот для других, в том числе и всех Mega, где количество SRAM превышает 256 байтов, эта загрузка будет протекать иначе, т. к. константа RAMEND там размером больше байта:

* * *

Подробности

Как мы уже отмечали в главе 18, стек — область памяти, куда будут записываться адреса точек возврата при вызове подпрограмм по команде rcall или перехода к обработчикам прерываний. По окончании процедуры обработки прерывания (по команде reti) или обычной подпрограммы (по команде ret) этот адрес считывается в программный счетчик, и выполнение основной программы продолжается. Если во время выполнения обработчика данного прерывания происходит другое прерывание с большим приоритетом (это нужно специально разрешать, по умолчанию в AVR любое прерывание будет ожидать окончания обработки предыдущего), то в стек записывается также и этот текущий адрес команды, таким образом ошибиться при последовательном возврате невозможно. Стек устроен по принципу «последним вошел — первым вышел», т. е. извлекается всегда последнее записанное туда значение. Программист может использовать стек и для своих целей (командами push и pop — например, для сохранения текущего значения рабочих регистров), но неопытным программистам лучше активно этим способом не пользоваться — вероятность допустить трудно обнаруживаемую ошибку значительно возрастает. Тем более что в AVR и без того достаточно РОН (в отличие, например, от х51, где без стека обойтись практически невозможно), а при необходимости можно еще и хранить текущие значения в SRAM.

Прерывание таймера по переполнению

С учетом всего сказанного напишем программу, переключающую светодиод. В данном случае она будет это делать по событию переполнения таймера-счетчика Timer 1 (вектор у нас обозначен: TIM1_OVF). Так как счетчик 16-разрядный, то событие переполнения будет возникать при каждом 65 536-м импульсе входной частоты. Если мы зададим коэффициент деления тактовой частоты на входе Timer 1 равным 64, то при 4 МГц частоты генератора мы получим примерно 1 Гц: 4 000 000/64/65 536 = 0,953674 Гц.

Это не совсем то, что нам требуется, и к тому же частота неточно равна одному герцу. Для того чтобы светодиод переключался точно раз в полсекунды (т. е. период его был равен секунде), программу придется немного усложнить, загружая каждый раз в счетные регистры определенное значение, которое рассчитывается просто: если период одного тактового импульса таймера равен 16 мкс (частота 4 000 000/64), то для получения 500 000 микросекунд надо отсчитать таких импульсов 31 250. Так как счетчик суммирующий, а прерывание возникает при достижении числа 65 536, то нужно предварительно загружать в него необходимое число 65 536 — 31250 = 34 286.

Это не единственный способ, но наиболее универсальный, годящийся для всех таймеров. Кстати, именно таким способом реализован отсчет времени

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату