- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Занимательная электроника - Юрий Ревич
Шрифт:
Интервал:
Закладка:
1. Конфигурирует нужные выводы порта D (PD5 и PD6) на выход.
2. Устанавливает на выводе PD6 логическую единицу (логический ноль на выводе PD5 устанавливается по умолчанию).
И что, программа будет состоять всего из двух команд? Увы, не все так просто.
В регистры портов записывать непосредственное значение нельзя, можно только командой out переносить информацию из какого-нибудь рабочего регистра. Поэтому добавится третья команда — сначала мы установим нужные биты в некоем рабочем регистре, специально выбранном для этих целей из числа регистров общего назначения (РОН), затем загрузим весь полученный байт в регистр порта. Причем установить непосредственное значение можно также не в любом из РОН, а только в регистрах с номерами с 16 по 31, поэтому выберем себе регистр r16 в качестве рабочего. Тогда последовательность команд будет выглядеть так:
ldi r16, 0Ь0Н00000 ; устанавливаем биты номер 5 и 6 в регистре r16
out DDRD,r16 ; выводим это значение в регистр направления порта D
sbi PortD,6 ; устанавливаем в единицу бит 6 регистра данных порта D
Здесь ldi — команда загрузки непосредственного значения (load immediate), out — команда вывода в какой-либо регистр ввода/вывода (РВВ), sbi (set bit input/output) — команда установки бита с выбранным номером в РВВ. А что означает запись 0Ь0Н00000? Это хорошо знакомое нам двоичное представление числа — 0b впереди как раз и означает, что это именно двоичная запись. Таким образом в данном случае удобнее отсчитывать биты, но если мы запишем это же число в hex-форме 0х60 (или $60), или даже просто десятичное 96, ничего не изменится.
Заметим, что способ установки значений РВВ через команду out — не единственный, можно было бы установить биты 5 и 6 регистра DDRD двумя командами sbi (есть и другие способы).
* * *
Подробности
Обратите внимание на синтаксис команд — сначала пишется, куда писать, а потом, через запятую, откуда или что. Это справедливо для всех команд и для всех ассемблеров. Каждая команда пишется в отдельной строке. Весь текст после точки с запятой ассемблером игнорируется и представляет собой комментарии, которые нужно писать обязательно, иначе вы через пару месяцев и сами в своей программе не разберетесь. Если комментарий переходит на другую строку, то точку с запятой нужно ставить заново, в начале строки. В отличие от знака перевода строки, все пробелы и табуляции игнорируются (а там, где есть другой разделительный знак, в данном случае запятая, как видите, пробелов вообще может не быть), так что украшать текст отступами можно, а для удобства чтения и нужно. Строчные и прописные буквы не различаются: записи LDI, Ldi и ldi означают одно и то же — и это отличие AVR-ассемблера от программных сред, основанных на C/C++. Вопреки распространяемым в Интернете сведениям (заимствованным из [22]), это правило соблюдается и для обновленных версий компилятора Avrasm2.
* * *
Ну, а теперь все? Можно скопировать это в Блокнот, сохранить с расширением asm и компилировать в hex-файл? Ишь разбежались — нет, не все. Во-первых, никаких таких DDRD и PortD AVR-ассемблер не понимает. Если соответствия кодов команд и их мнемонических обозначений (ldi), а также обозначений рабочих регистров (r16) и их адресов зашиты в ассемблере, то адреса РВВ могут меняться от модели к модели, а их названия и вообще могут быть выбраны совершенно произвольным образом. Сам ассемблер понимает только конкретные числа, представляющие собой адреса этих регистров. Но писать программу без мнемонических обозначений было бы крайне неудобно, т. к. она оказалась бы совершенно нечитаемой (вторая команда, к примеру, тогда выглядела бы так: out $11, r16). Поэтому к нашей программе надо «пристегнуть» файл с мнемоническими обозначениями, который поставляется Atmel и в данном случае называется tn2313def.inc (при компиляции он должен находиться в одном каталоге с файлом программы). Это делается почти в точности, как в языке С, строкой:
.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, тогда она запишется так:
Здесь Razr0-Razr2 — рабочие регистры. Отведем для них регистры r17, r18 и r19. В начало программы тогда следует внести их определения через команду def (по образцу .def Razr0 = r17). Delay с двоеточием — метка, в данном случае обозначающая начало процедуры, команда ret — выход из процедуры (зачем она нужна, пояснено далее). Команда subi вычитает из регистра константу, в данном случае единицу. А команды sbci работают хитрее — они также вычитают константу, но с учетом переноса. Если переноса нет, то они просто ничего не делают (ибо вычитаемое значение равно нулю). Перенос же возникает тогда, когда в результате предыдущей команды вычиталась единица из нуля. Тогда значение регистра меняется с нулевого на все единицы (255), а перенос записывается в специальный бит переноса и учитывается следующей командой sbci. В этой схеме легко узнать принцип работы соединенных между собой двоичных счетчиков из главы 16, в которых выход старшего разряда предыдущего счетчика соединен со входом переноса следующего. В данном случае счетчик состоит из трех отдельных байтовых регистров, т. е. всего имеет 24 двоичных разряда.

