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





Программа счетчика
Сначала разберемся с нажатием-отпусканием кнопки. Отслеживать состояние вывода удобно командами sbic или sbis (Skip if Bit in I/O register Clear/Set — пропустить следующую команду, если бит в РВВ очищен/установлен) применительно к второму биту массива PinD. Листинг 5.10 иллюстрирует простейший цикл слежения за состоянием кнопки (когда кнопка нажимается, состояние вывода меняется с единицы на ноль). Листинг 5.10
Pincykle: /цикл отслеживания кнопки
sbic PinD,2 /пропустить, если нажата
rjmp Pincykle /вернуться обратно, если не нажата <кнопка нажата — что-то делаем>
rjmp Pincykle /вернуться обратно к отслеживанию

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

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

Тогда вся программа, включая секцию определений, будет такой, как в листинге 5.11.
Листинг 5.11
Программа счета нажатий в двоичном коде .device AT90S2313 .include "-2313def. inc"
;частота 4 МГц
.def temp = г16 /рабочая переменная
.def RazrO = г17 /разряды задержки
.def Razrl = rl8
.def Razr2 = rl9
.def Counter = r20 ;счетчик
.org 0 /необязательно, просто для ориентировки
============ Программа ============
ldi temp,ObOOOOOlOO ;для второго разряда порта D
out PORTD,temp /подтягивающий резистор на всякий случай
ldi temp,Obllllllll /порт В все контакты на выход
out DDRB,temp
clr Counter /очищаем счетчик Pincykle: /цикл отслеживания кнопки
sbic PinD,2 /пропустить, если нажата
rjmp Pincykle /вернуться обратно, если не нажата
/кнопка нажата — пауза 0,2 с, N = $027100
ldi Razr2,$02
ldi Razrl,$71
ldi RazrO,$00
rcall Delay
Pin_release: /отслеживаем отпускание
sbis PinD,2 /пропустить, если отпущена
rjmp Pincykle /вернуться обратно, если нажата
inc Counter /если отпущена, увеличиваем счетчик
out PORTB,Counter /выводим счетчик в порт В
/пауза 0,5 с, N = $061А80п
ldi Razr2,$06
ldi Razrl,$1A
ldi RazrO,$80
rcall Delay
rjmp Pincykle /вернуться обратно к отслеживанию
Delay: /процедура задержки
subi RazrO,1
suci Razrl, 0
suci Razr2,0
brcc Delay ret /возврат из процедуры

Как видите, программа совсем небольшая. Счетчик counter будет считать "вкруговую" — при переполнении он опять начнет с нуля. Программа выводит состояние счетчика в порт В целиком, таким образом работа ее не зависит от того, сколько именно светодиодов вы подключите к выводам этого порта, все восемь, или только три, как на схеме.
Пояснений здесь требует момент, связанный с определением переменных — почему мы начали сразу с регистра г1б, а не, например, с гО? Одно из самых больших неудобств AVR заключается в том, что команды, оперирующие с константами (ldi и subi в данном случае, а также команды cpi, andi и др.), не работают с первыми шестнадцатью РОН (от гО до г15), их можно использовать только для регистров ri6 - г31 (заметим сразу про еще одно аналогичное ограничение: команды поразрядного доступа к РВВ sbi, cbi, sbis и sbic работают только для первых тридцати двух РВВ, до номера $1F включительно).
Для сокращения программы рабочие переменные (temp, счетчики) всегда желательно выбирать из этой половины регистрового файла. Положение осложняется тем, что регистры из старшей половины наиболее дефицитны — последние шесть из них объединены в пары х, Y и z для работы с памятью (см. далее) и некоторых других операций, г24 и г25 задействованы в команде adiw, и т. п. Если переменных не хватает, то, чтобы не путаться с локальными переменными, загрузку регистра из первой половины регистрового файла (допустим, это г15) непосредственным значением приходится осуществлять парой команд:
ldi temp,10 mov г15,temp



     
 

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