Занимательная микроэлектроника — страница 60 из 117

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

Внутренние прерывания могут возникать от любого устройства, которое является дополнительным по отношению к ядру системы: от таймеров, от аналогового компаратора, от последовательного порта и т. д. Внутреннее прерывание— это событие, которое возникает в системе и прерывает выполнение основной программы. Система внутренних прерываний в AVR довольно раз ветвленная и представляет собой основной механизм взаимодействия устройств с ядром системы, и мы еще к этому вопросу будем неоднократно возвращаться.

На внешних прерываниях мы остановимся здесь подробнее. Внешних прерываний у МК типа AT90S8515 два, INTO и INT1 (а вот в ATmega128 — целых восемь!), естественно, они могут возникать независимо друг от друга. Внешнее прерывание — событие, которое возникает при появлении сигнала на одном из входов, специально предназначенных для этого (в данном случае контакт 12 или 13). Различаются три вида событий, вызывающих прерывание, и их можно устанавливать в программе: это может быть низкий уровень напряжения, а также положительный или отрицательный фронт на соответствующем выводе. Любопытно, что прерывания по всем этим событиям выполняются, даже если соответствующий вывод порта сконфигурирован на выход.

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

В отличие от этого, прерывания по фронту или спаду выполняются один раз на импульс. Конечно, от дребезга контактов там никакой защиты нет и быть не может, потому что МК не способен отличить дребезг от серии коротких импульсов. Если это критично, нужно либо принимать внешние меры по защите от дребезга, либо использовать тот же способ, что и для прерывания по уровню— внутри процедуры обработчика прерывания первой же командой запретить само прерывание, а через некоторое время в другой процедуре (по таймеру, например, или по иному событию) опять его разрешить (способ «антидребезга», фактически идентичный применению одновибратора, см. главу 9). Но если по нажатию кнопки просто что-то устанавливается в некое состояние, то ничего страшного не случится, если это произойдет несколько раз подряд, только следует учесть, что окончание этого процесса совпадет с отпусканием кнопки.

Подробности

У внимательного читателя возникает законный вопрос— а зачем вообще нужен режим внешнего прерывания по уровню? Дело в том, что оно во всех моделях выполняется асинхронно, т. е. в тот момент, когда низкий уровень появился на выводе МК. Конечно, обнаружение прерывания может произойти только по окончании текущей команды, так что очень короткие импульсы могут «пропасть». Но прерывания INT0 и INT1 в режиме управления по фронту у большинства моделей определяются наоборот, только синхронно, т. е. в момент перепада уровней тактового сигнала контроллера, поэтому их длительность не должна быть короче одного периода тактового сигнала. Но это не самое главное: по большому счету разницы в этих режимах никакой бы не было, если бы не то обстоятельство, что синхронный режим требует непременно наличия этого самого тактового сигнала. И асинхронное внешнее прерывание, соответственно, может «разбудить» контроллер, находящийся в одном из режимов глубокого энергосбережения, когда тактовый генератор не работает, а синхронное— нет. И обычные МК, вроде разбираемого AT90S8515 семейства Classic (но не его Меда-аналога!), выводиться из глубокого «сна» могут только внешним прерыванием по уровню, которое не всегда удобно использовать. У большинства же моделей семейства Меда (из младших моделей — кроме АТmega8), имеется еще одно прерывание INT2, которое происходит только по фронтам (а не по уровню), и, в отличие от INT0 и INT1, только асинхронно. Это значительно повышает удобство работы с семейством Меда в режиме энергосбережения (на эту тему см. главу 17).


Таймеры-счетчики

В МК 8515 два таймера-счетчика: один 8-разрядный (Timer 0), второй — 16-разрядный (Timer 1). Оба счетчика представляют собой счетчики с предзагрузкой (вроде 561ИЕ11/14) и могут работать от тактовой частоты процессора непосредственно, или поделенной на 8, 64, 256 или 1024, представляя в таком режиме собой именно таймеры, т. е. устройства для отсчета времени.

Могут они работать и как обычные счетчики внешних импульсов с выводов Т0 (вывод 1) для Timer 0 и Т1 (вывод 2) для Timer 1 (по спаду или по фронту). Частота подсчитываемых импульсов не должна превышать половины частоты тактового генератора МК (причем при несимметричном меандре инструкция рекомендует и еще меньшее значение предельной частоты — 0,4 от тактовой), иначе счетчик вам посчитает «погоду на Марсе» — это сильное ограничение, поэтому, например, использовать МК для создания универсального частотомера неудобно. Поэтому все быстродействующие логические схемы конструируют не на микроконтроллерах, а на комбинационной логике — на ПЛИС.

При наступлении переполнения счетчика возникает событие, которое может вызывать соответствующее прерывание. Счетчик Timer 0 фактически этим и ограничивается. 16-разрядный счетчик Timer 1 — более «продвинутая» штука, и может вызывать прерывания по совпадению с определенным заранее заданным числом (точнее, даже два отдельных прерывания с двумя разными числами А и В), при этом счетчик может обнуляться или продолжать счет, и на специальных выводах OSC1A (вывод 15) или OSC1B (вывод 29) при этом могут генерироваться импульсы (аппаратно, без участия программы). Этот режим нам понадобится, чтобы задавать определенную частоту прерываний — например, в часах для отсчета секунд (см. главу 14).

Также возможно прерывание по внешнему событию на специальном выводе ICP (вывод 31), при этом содержимое счетчика помещается в некий регистр ICR1, а счетчик может обнуляться и начинать счет заново или просто продолжать счет (режим измерения периода внешнего сигнала). Источником таких событий может быть встроенный аналоговый компаратор— это удобно для того, чтобы построить на основе МК частотомер, но, как мы видели ранее— только низкочастотный, не более 5–7 МГц. Некоторые подробности о прерываниях и таймерах вы узнаете также из главы 17, когда мы будем разбирать режимы энергосбережения.

В AT90S8535 и во всех Mega (кроме Mega8515) есть как минимум еще один, третий таймер, который также будучи, как и Timer0, 8-разрядным, может выполнять более интересные вещи (например, работать автономно от остальной системы, когда весь процессор находится в режиме экономии, что позволяет этот таймер использовать в качестве часов реального времени, RTC). Но и это не все: описанные таймеры могут работать в т. н. PWM-режиме, специально предназначенном для их работы в качестве широтно-импульсных модуляторов (ШИМ). Этот режим мы кратко рассмотрим в главе 19 в связи с голосовой сигнализацией.

Кроме таймеров-счетчиков в любом AVR-контроллере есть сторожевой (Wathcdog) таймер. Он предназначен в основном для вывода МК из режима энергосбережения через определенный интервал времени, но может выполнять и простой перезапуск МК при включении питания, например, если работа программы зависит от прихода внешних сигналов, то при их потере (например, из-за сбоев на линии) МК может просто «повиснуть», а Wathcdog-таймер выведет его из этого состояния.

Остальные узлы МК семейства AVR мы рассмотрим по ходу изложения конкретных схем — так будет нагляднее. А тому, как состыковать последовательный интерфейс UART с компьютером, будет посвящена даже отдельная глава 18. Здесь же мы закончим краткое знакомство с микроконтроллером и перейдем к вопросу о том, как его программировать.

Глава 13Персональный компьютер вместо паяльника

Всегда имеются в продаже свежие программные продукты!

Объявление на рынке

Готовой работающей программой называют код, содержащий пока еще не обнаруженные ошибки.

Народное


Слово «программирование» в отношении МК имеет двоякий смысл. Во-первых, это собственно процесс написания программы, как и для любых других устройств, содержащих процессор, от холодильников до персональных компьютеров или узлов управления космическими аппаратами. Во-вторых, этим словом также называют процесс загрузки программы в память программ. Чтобы не путаться, мы будем подразумевать под «программированием» МК именно запись программ в память (ее еще называют «прошивкой»), а подготовительный этап будем называть «созданием программы».

Заметки на полях

Отмечу, что каждый, кто хочет всерьез научиться программировать (неважно для чего, хоть для Веба, хоть для микроконтроллеров), должен начинать с изучения фундаментального труда Д. Кнута [10]. К сожалению, Кнут не практикующий программист, а профессор Стэндфордского университета, и как все профессоры, начинает с анализа, доказательств теорем и тому подобной «чепухи», зачем-то очень нужной математикам. Читатель, конечно, понимает, что в этих высказываниях есть значительная доля шутки, но правда заключается в том, что математик потребует доказательства там, г