Главная страница
Библиотека (скачать книги)
Скачать софт
Введение в программирование
Стандарты для C++
Уроки по C#
Уроки по Python
HTML
Веб-дизайн
Ассемблер в среде Windows
ActiveX
Javascript
Общее о Линукс
Линукс - подробно
Линукс - новое
Delphi
Паскаль для начинающих
Турбопаскаль
Новости
Партнеры
Наши предложения
Архив новостей





Обратите внимание на то, что при смене модели здесь не требуется что-либо исправлять (при условии, конечно, что новая модель будет поддерживать такие же прерывания), за исключением строки .org $OD. В модели 8515 всего 12 прерываний + сброс, а объем памяти 8 кбайт, поэтому таблица прерываний занимает 13 двухбайтовых ячеек, и программа может начинаться с ячейки номер $0D. В других моделях это обязательно будет другое число, т. к. количество прерываний отличается, причем для моделей с объемом памяти программ меньше или равной 8 кбайт к адресу последнего прерывания нужно добавить единицу, а в моделях с объемом памяти более 8 кбайт — двойку.
Если вы боитесь ошибиться, то более-менее универсальный метод заключается в том, чтобы пренебречь потерями пространства памятц и всегда начинать программу с адреса, заведомо большего следующего за вектором последнего прерывания, например, так: .org $40. В данном случае мы потеряем первые 64 ячейки памяти минус занятые под реально действующие векторы. Обратите внимание, что в старших моделях Mega таблица прерываний может занимать и больше места, чем 64 ячейки (так, в ATmegal28 программа может начинаться лишь с ячейки $46), но для них, за небольшим исключением, и названия прерываний будут иными, так что все равно программу придется править (или использовать условную компиляцию).

RESET
Теперь обратимся к процедуре RESET, Т. е. к истинному началу программы — что там должно быть? Когда контроллер доходит до команды вызова подпрограммы (call или rcaii), или в нем происходит прерывание (хотя в векторе и стоит обычное rjmp или jmp, но по сути это тоже вызов подпрограммы), он должен сохранить состояние программного счетчика с тем, чтобы потом знать, куда вернуться. Это происходит в специальной области памяти, которая называется стек (stack). Потому в любой программе на AVR-ассемблере, допускающей прерывания или просто подпрограммы, как мы уже обсуждали в главе 4, первыми после метки RESET ДОЛЖНЫ идти следующие строки:
RESET:
ldi temp,low(RAMEND) ;загрузка указателя стека out SPL,temp
ldi temp,high(RAMEND) ;загрузка указателя стека out SPH,temp

Этими операторами вы указываете, где компилятору расположить программный стек— а именно, в конце SRAM (что обозначается константой RAMEND, объявленной в соответствующем inc-файле). Для моделей Tiny с аппаратным стеком (ATtinyljc, ATtiny28) эти строки следует опустить (подробнее см. главу,4). Для тех моделей, у которых стек программный, но объем SRAM не превышает 256 байт (модель ,2313 во всех ее инкарнациях, ATtiny26 и др.), запись сокращается:
RESET:
ldi temp,RAMEND ;загрузка указателя стека out SPL,temp

После задания стека желательно поставить следующие строки:
ldi temp, 1«ACD out ACSR,temp ;выкл. аналог, компаратор

Почему желательно, а не обязательно? Потому что по умолчанию аналоговый компаратор всегда включен, и, соответственно, расходует питание. Если вы его не используете, то зачем лишнее потребление? Правда, это практически не скажется на потреблении в нормальном режиме работы — доля компаратора очень мала. Потому критичной вставка этих строк становится только в случае, если задействованы режимы энергосбережения, а в обычных режимах эти команды просто ни на что не повлияют. С другой стороны, если компаратор необходим (см. главу 10), то, конечно, эти строки нужно исключить.
После всего этого в процедуре RESET обычно идет секция инициализации, где разрешаются прерывания, устанавливаются состояния выводов портов, инициализируются начальные значения переменных и т. п. Примеры мы еще встретим в тексте этой книги неоднократно. Эта секция, как мы говорили ранее, обязательно должна заканчиваться командой sei — общим разрешением прерываний, т. к. по умолчанию они запрещены.

Теперь вроде бы все готово к работе, но что будет делать контроллер в ожидании прерываний? Ведь основная функциональность большинства микропрограмм сосредоточена именно в их обработчиках, и в простейшем случае контроллер попросту ничего не должен делать, пока не придет сигнал очередного прерывания. Поэтому простейшая программа должна заканчиваться пустым циклом: sei ;разрешаем прерывания STOP:
rjmp STOP
На самом деле в этом цикле можно и делать что-то полезное— например, войти в один из режимов энергосбережения, или отслеживать изменение состояния какого-то вывода, или, например, прихода байта через UART и т. п. — в дальнейшем мы увидим примеры подобных действий. Именно внутри такого цикла работают немногочисленные программы, вообще не использующие прерываний.

Простейшая программа
Для примера мы сейчас напишем очень простую тренировочную программу, в которой не нужны прерывания. В этой программе мы покажем, как можно формировать интервалы времени без использования таймеров (а когда-то ведь именно так и делали!) и отслеживать события без привязки к внешним прерываниям.
Программа будет считать нажатия кнопки и демонстрировать их в двоичном коде на светодиодах (LED). В схеме для простоты мы ограничимся тремя светодиодами, т. е. будем считать до 8 нажатий (хотя без каких-то переделок программы можно увеличить число светодиодов до 8 и, соответственно, считать до 256). Опять же для простоты выберем модель семейства Classic AT90S2313 (напомним, что в ATtiny2313 можно реализовать режим Classic, если запрограммировать соответствующий конфигурационный бит, см. далее в этой главе). Схема, для которой мы будем писать программу, представлена на рис. 5.7.

Заметки на полях
Отметим, что такую последовательность лучше соблюдать всегда: сначала разработать схему, затем писать программу под нее, иначе вы можете легко наделать ошибок, когда окажется, что для удобства разводки нужно поменять контакты корпуса. Но при разработке схемы, в свою очередь, необходимо продумать структуру будущей программы, чтобы не влипнуть в ситуацию с созданием себе лишних сложностей (здесь они возникли, если бы мы выбрали выводы для подключения LED произвольно, а не по порядку выходов порта В). Обычно вначале рисуют блок-схемы алгоритмов, но мы этим заниматься не будем, ограничившись словесным описанием.
В схеме на рис. 5.7 показаны "подтягивающие" резисторы по выводам программирования (R2-R4), о необходимости установки которых "так долго говорили большевики" (см. главу 1). В такой схеме их устанавливать вообще-то необязательно (источников больших помех не ожидается), но для унификации я их показал — в дальнейшем рисовать узел программирования на схемах мы не будем, для всех остальных моделей он выглядит точно так же, меняются только контакты корпуса. При желании увеличить число индикаторов до 8 можно задействовать в том числе и контакты РВ5-РВ7 (они же выводы программирования), подсоединив к ним, а также к выводам РВЗ-РВ4, светодиоды аналогично тому, как это сделано для РВ0-РВ2. В этом случае "подтягивающие" резисторы, естественно, устанавливать нельзя (через них будет подсвечиваться выключенный светодиод), а помехи будут эффективно "садиться" и на светодиодах.

С1
R1
0,1
+s в —Г^Тч JL-jj
5,1 к
Reset Опит
PD0 (РВ7) SLK
PD1 (РВ6) MISO
XTAL2 (РВ5) MOSI
XTAL1 РВ4
PD2 РВЗ
PD3 РВ2
PD4 РВ1
PD5 РВО
GNO PD6
AT90S2313

Reset
GNO
+5 В
SLK
MISO
MOSI
Х1



     
 

Библиотека программиста. 2009.
Администратор: admin@programmer-lib.ru