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





Процессу программирования, как показывает опыт, такое использование выводов не мешает — в крайнем случае можно установить по дополнительному диоду (обычному маломощному, например, КД521) последовательно с резисторами 510 Ом, анодом к выводу МК и контактам разъема. Единственное, чего нельзя делать с выводами программирования, — подсоединять их к выходным каскадам какой-то другой микросхемы (или, например, к выходу открытого транзистора) — тогда и программирования не получится, и вообще можно повредить и схему, и программатор. Кнопку Кн1 можно подсоединять в принципе к любому из контактов порта D (как видите, их в этой модели семь, восьмой пропал, т. к. не хватило выводов корпуса), но именно к выводу PD2 я подключил его с далеко идущими целями, о чем вы узнаете далее.
Резистор R8 в принципе также можно не устанавливать, если обойтись встроенным "подтягивающим" резистором, но, как мы уже говорили, без него помехоустойчивость схемы будет значительно ниже: например, у автора этих строк без такого резистора происходило ложное срабатывание кнопки как при внешних наводках, так и при бросках питания (к примеру, при переключении питания с сети на резервную батарею). Наличие внешнего резистора гарантированно решает такие проблемы, поэтому лучше его устанавливать всегда.

Проблема, которую нам придется преодолеть, заключается в том, что любая кнопка дребезжит, и потому при нажатии или отпускании генерируется множество импульсов, из которых придется выбрать один. Использование прерывания, как следовало бы сделать "по-правильному", не избавляет от необходимости учитывать дребезг, поэтому в принципе решения проблемы и там и здесь одинаковы: придется делать искусственную задержку реакции МК, для чего нам и понадобится имитатор таймера. Другой нюанс заключается в том, что в этом случае реагировать следует не на нажатие, а на отпускание кнопки, и это немного усложнит нашу программу.

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

Задержка
Давайте начнем с формирования временного интервала. Нам нужно сформировать задержку порядка долей секунды. Метод без таймера основан на том,что каждая команда в МК выполняется за строго определенное время. В AVR считать время вообще очень просто: большинство команд выполняется за один такт, и потому, например, для формирования интервала в одну секунду при тактовой частоте 4 МГц, нам требуется выполнить какую-нибудь (в принципе неважно, какую) последовательность из четырех миллионов команд.
Обычно программисты используют декрементирование (т. е. последовательное уменьшение на единицу) какой-либо величины. Предположим, что необходимое число займет три регистра-разряда (это даст максимальную величину 16 777 215). Схема действий такая: мы последовательно уменьшаем самый младший разряд (назовем его RazrO) на единицу, когда его величина достигает нуля, уменьшаем на единицу следующий (Razri) и переходим опять к уменьшению младшего, начиная со значения 255 (это значение загружать специально не требуется, т. к. при вычитании единицы из нуля результат получится равным 255 автоматически). Когда, в свою очередь, величина Razri достигает нуля, уменьшаем на единицу самый старший (Razr2) и так до тех пор, пока все разряды не станут нулями. Предварительно следует загрузить в переменные Razr0-Razr2 нужное число. Какое? Это зависит от конкретного алгоритма.

Следующая последовательность команд (листинг 5.8) реализует этот алгоритм "в лоб".
Delay:
dec RazrO
brne Delay
dec Razri
brne Delay
dec Razr2
brne Delay <все равны 0 — конец задержки>

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

Значительно более компактной-и предсказуемой будет реализация алгоритма на основе команды вычитания с учетом переноса (листинг 5.9).
I Листинг 5L$
Delay:
subi RazrO,l suci Razrl,0 suci Razr2,0 brcc Delay

Работает это так: команда suci вычитает сразу две величины — то, что записано в самой команде, плюс флаг переноса с. Если результат предыдущего вычитания устанавливает флаг переноса (что происходит при переходе через ноль, когда из нуля вычитается единица), то команда suci вычтет его значение, равное единице, если нет, то не вычтет ничего (точнее, вычтет ноль). В результате в каждой итерации выполняется строго определенное число команд и за строго определенное время: по одному такту на каждое вычитание плюс два такта на переход обратно к началу цикла (ведь для команды brcc условие перехода выполняется, если флаг переноса не установлен), всего пять тактов.
(Для особо въедливых отметим, что самый последний цикл будет на один такт короче.) Итак, для того чтобы получить ровно 4 ООО ООО тактов, нам нужно записать в регистры Razr2-Razr0 число 4 ООО 000/5 = 800 000 или $0С3500. Это даст интервал в 1 с при тактовой частоте 4 МГц. В общем случае число N, соответствующее нужному интервалу времени Т (с) при тактовой частоте F (Гц), можно получить по формуле 7775. Всего с тремя регистрами и тактовой частотой 4 МГц мы можем получить задержку до 4,19 с, если запишем в них число 16 777 215 = $FFFFFF.



     
 

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