123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- Для кнопки надо выбраную ножку I/O подключить через кнопку на землю. Сам же
- вывод надо сконфигурировать как вход с подтяжкой (DDRxy=0 PORTxy=1). Тогда,
- когда кнопка не нажата, через подтягивающий резистор, на входе будет высокий
- уровень напряжения, а из бит PINху будет при чтении отдавать 1. Если кнопку
- нажать, то вход будет положен на землю, а напряжение на нем упадет до нуля, а
- значит из PINxy будет читаться 0. По нулям в битах регистра PINх мы узнаем
- что кнопки нажаты.
- Пунктиром показан дополнительный подтягивающий резистор. Несмотря на то, что
- внутри AVR на порт можно подключить подтяжку, она слабоватая — 100кОм. А
- значит ее легко придавить к земле помехой или наводкой, что вызовет ложное
- срабатывание. А еще эти внутренние подтягивающие резисторы очень любят гореть
- от наводок. У меня уже с десяток микроконтроллеров с убитыми PullUp
- резисторами. Все работает, но только нет подтяжки — сгорела. Вешаешь снаружи
- резистор и работает как ни в чем ни бывало. Поэтому, для ответственных схем я
- настоятельно рекомендую добавить внешнюю подтяжку на 10кОм — даже если
- внутреннюю накроет, внешняя послужит. В процессе обучения на это можно
- забить.
- ===============================================================================
- если кнопка нажата и флага1 нет - ставим флаг и выход.
- если кнопка нажата и есть флаг1 - увеличиваем счётчик. если счётчик переполнился - фиксируем удержание.
- если есть флаг удержания, счётчик не переполнен но достиг порога - можно фикисровать срабатывани атовповтора (при необходимости)
- если кнопка отпущена но есть флаг1 и при этом счётчик >= порога и нет флага удержания - фиксируем нажатие.
- сьросим флаг1, счётчик времени.
- флаги 2 и 3 сбросят п/п обработки
- кнопка нажата
- флаг1 есть?
- нет: установим и дальше
- да: считаем время нажатия
- переполнилось время нажатия?
- да: удержание. ставим флаг3,
- кнопка отпущена
- время нажатия >= 0.5сек?
- да: есть флаг 3?
- нет: ставим флаг2
- сбросим флаг1, сбросим время нажатия
- ; *** начало бработки кнопки ***
- sbic ButPort,BTN1 ; кнопка 1 нажата?
- rjmp T0L2 ; нет, на обработку ненажатой кнопки
- sbrs flagb,BTN1P ; была нажата раньше?
- rjmp T0L4 ; нет, вкл флаг и дальше...
- inc TIKB ; да, увеличим счётчик
- brne T0L3 ; переполнения нет - на выход
- mov temp,flagb ; переполнение...
- sbi temp,1<<BTN1H
- mov flagb,temp ; установили флаг удержания
- rjmp T0L3 ; дальше...
- T0L2: sbrs flagb,BTN1P ; кнопка не нажата
- rjmp T0L5
- ldi temp,64 ; ~0.5 сек
- cp TIKB,temp ; тики достигли порога срабатывания?
- brlo T0L5 ; нет, на очистку
- mov temp,flagb ; да, ставим флаг
- cbi temp,1<<BTN1R
- mov flagb,temp ; установили флаг отпускания
- T0L5: clr TIKB ; очистим тики кнопок
- mov temp,flagb
- cbi temp,1<<BTN1P
- mov flagb,temp ; сбросили флаг нажатия
- rjmp T0L3 ; дальше...
- T0L4: sbi temp,1<<BTN1P
- mov flagb,temp ; установили флаг нажатия
- ; *** закончили обратоку кнопки ***
- T0L3:
- ===============================================
- каждый раз -- всё с начала, нихера не помню, нихера не выходит...
- ещё раз:
- предположим, опрос кнопки идёт в таймере с периодичнойстью 1-10 мс.
- пороги -- антидребезг = 50 мс, срабатывания = 100 мс, длинное нажатие =
- 500 мс, удержание = 2 с.
- опрос кнопок:
- кнопка нажата (
- если флага нет (
- если счётчик достиг порога срабатывания (
- ставим флага нажатия
- очищаем счётчик // можно не делать.
- ) если не достиг (
- увеличиваем счётчик
- )
- ) если флаг есть (
- если счётчик меньше времени удержания (
- увеличиваем счётчик
- )
- )
- ) если кнопка не нажата (
- если флаг есть (
- сбросить флаг
- если счётчик меньше времени срабатывания (
- очистить счётчик
- )
- ) если флага нет (
- очистить счётчик
- )
- )
- // 10 проверок, 7(6) действий
- обработка кнопок:
- тут просто проверяем время нажатия/удержания.
- сначала двойные комбинации, потом одиночные.
- непонятно как обрабатывать удержание, если должна быть реакция и на
- нажатие...
- кроме того -- ещё нужен обратный счётчик.
- после фиксации факта срабатывания или отпускания -- заводим счётчик паузы,
- и пока он не дотикает до 0 -- кнопку не обрабатываем.
- по факту, из Печки, обработка текущеё кнопки:
- if(BTN[i].Pause == 0) { // текущая кнопка на паузе?
- // нет, продолжаем
- if (bit_is_clear(BTN_PIN,BTN[i].bit)) { // кнопка нажата
- if (bit_is_clear(BTN[i].flg,PRESSED)) { // флага нет
- if (BTN[i].Count >= BTN_Treshold) { // счётчик достиг антидребезга?
- SetBit(BTN[i].flg,PRESSED); // да. ставим флаг
- } else {
- BTN[i].Count ++; // не достиг. увеличим счётчик
- }
- } else { // флаг уже есть -- антидребезг отработали
- if (BTN[i].Count < BTN_Holded) { // счётчик меньше времени удержания?
- BTN[i].Count ++; // увеличиваем счётчик
- }
- }
- } else { // кнопка не нажата
- if (bit_is_set(BTN[i].flg,PRESSED)) { // флаг есть
- ResBit(BTN[i].flg,PRESSED); // и сбросим флаг
- if (BTN[i].Count < BTN_Pressed) { // счётчик
- BTN[i].Count = 0; // очистим счётчик
- }
- } else {
- BTN[i].Count = 0; // очистим счётчик
- }
- }
- } else { // на паузе. уменьшаем счётчик
- BTN[i].Pause --;
- }
- в обработчике кнопка обрабатывается если есть флаг и счётчик, сбрасывается
- счётчик кнопки и устанавливается счётчик паузы.
|