.include "tn2313def.inc";точка впереди обязательна!

* * *

Замечание

Файлы макроопределений (с расширением inc), к сожалению, нельзя скачать с сайта Atmel в отдельности. Как и файл компилятора Avrasm2, эти файлы для каждого контроллера в отдельности проще всего добыть из пакета AVR Studio, где они находятся в папке avrassembler/include. Лучше, если это будет одна из последних версий AVR Studio, пятая или более поздняя, иначе при компилировании совместно с Avrasm2 возможны ошибки.

* * *

Если вы заглянете внутрь файла tn2313def.inc, то увидите, что он состоит из строк, начинающихся с директивы .equ. Мы могли бы не включать его в программу (хотя в память процессора он все равно не записывается, ибо не содержит команд, а только определения переменных), а лишь дописать к программе в начале текста строки:

.equ DDRD = $11

.equ PortD = $12

Мы часто будем применять директиву .equ, которая устанавливает соответствие между числами и их обозначениями, наряду с другой полезной директивой — .def.

Если провести аналогии с языком Turbo Pascal или Turbo С, то директива .equ (от англ. equal — равно) полностью аналогична определению констант, а директива .def (от англ. define — определить) аналогична определению переменных, с единственным отличием: тип переменной здесь не указывается, ибо он один-единственный — число размером один байт. А вот в директиве .equ может быть указано число любого размера, а также и отрицательное, но, естественно, только целое.

Неудобно каждый раз писать r16 и помнить, что это у нас рабочая переменная для всяких текущих надобностей, потому лучше дописать еще такую строку:

.def temp = r16;рабочая переменная, от слова temporary (временный)

Окончательно исходный текст программы будет выглядеть так:

;программа зажигания светодиода

;процессор Tiny2313, частота 4 МГц

.include "tn2313def.inc"

.def temp = r16;рабочая переменная

ldi temp,0b01100000;устанавливаем биты номер 5 и 6 в temp

out DDRD,temp;выводим это значение в регистр направления порта D

sbi PortD,6;устанавливаем в единицу бит 6 регистра данных порта D

sleep

.exit

Программа займет в памяти программ контроллера ровно 8 байтов. Последняя команда sleep означает остановку процессора и выход в режим экономии — ведь должен процессор что-то делать по окончании программы? Директива .exit предназначена для ассемблера и означает конец программы, указывать ее необязательно.

А зачем мы в заголовочном комментарии указали тактовую частоту процессора?

В данном случае она не имеет значения (лишь бы контроллер работал), но при использовании любых процедур, связанных со временем, это критично. И поскольку можно забыть, на какую частоту вы рассчитывали при написании программы, следует ее на всякий случай указывать в комментариях.

Таймер без прерываний

Давайте теперь заставим наш МК управлять этим светодиодом так, чтобы он мигал с частотой примерно один раз в секунду из красного в зеленый. И сначала сделаем это самым простым способом — так, как это делали в те времена, когда микропроцессоры еще не были микроконтроллерами и не содержали никаких дополнительных узлов вроде таймеров. Для отсчета времени тогда пользовались тем фактом, что команды выполняются строго определенное время. Причем в AVR этот способ применять особенно удобно, поскольку большинство команд занимают один такт, за исключением команд передачи управления. Этим способом часто пользуются и по сей день для отсчета программных задержек (не станешь же заводить таймер по каждому случаю), потому урок окажется не совсем бесполезным. Заодно познакомимся с понятием процедур (подпрограмм) и с самими командами передачи управления.

Не вникая в подробности, сразу напишем «правильную» процедуру, позволяющую формировать заданные задержки без таймера. Назовем ее Delay, тогда она запишется так:

Перейти на страницу:

Поиск

Похожие книги