обработка нажатия кнопок attiny2313 (длительное нажатие)

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Всем привет!!!!! делаю устройство на attiny2313 описание:
внешний кварц 4мгц
кнопки подключены к portD pd1,pd2,pd4,pd5 ,через сопротивление 10ком
к +5в ,замыкаются на минус.

возникла следующая проблема:Для работы мне необходимо отслеживать длинное и короткое нажатие кнопки.

сейчас в основном цикле просто проверяю наличие 0

Код: Выделить всё


.equ	K1	=	PD1	; 
.equ	K2	=	PD2	; 
.equ	K3	=	PD4	;
.equ	K4	=	PD5	;

.def	zz0	=	r16
.def	zz1	=	r17
.def	zz2	=	r18

;основной цикл программы 
next: 
    sbis PIND,K1 ; если 0 то переход
    rcall K1 
    sbis PIND,K2
    rcall K2 
    sbis PIND,K3
    rcall K3 
    sbis PIND,K4
    rcall K4 
    ....
    ....   
    rjmp	next



K1:
    ldi zz2 ,$02	
    ldi zz1 ,$71
    ldi zz2 ,$00
    rcall delay 

    ...................
ret

delay:           
 subi zz0 , 1
 sbci zz1 , 0
 sbci zz2 , 0
 brcc delay
ret 

сначала сделал без задержки все очень быстро ,вставил задержку ,но даже с задержкой фигня какая то получается ,потом думал сделать цикл на отпускание.
не нравится то что ,приходится использовать задержку в основном цикле


Работаю над тем, как сделать опрос клавы с помощью таймера,
проверять там каким то образом длинное и короткое нажатии и только после этого проверять код нажатой клавиши в основном цикле?????


Может кто знает как это делается!!!!!!!
Реклама
Опытный кот
Аватара пользователя
Сообщения: 890
Зарегистрирован: Вт янв 20, 2009 14:49:08
Откуда: Гондурас, Мурманск

Сообщение DrWatson »

В прерывании по таймеру сканируешь кнопки, если нажата к.-л. кнопка, считаешь время до её отпускания, допустим: нажата меньше 100мс - дребезг, нажата больше 100мс, но меньше 1000мс - короткое нажатие, нажата дольше 1с - длинное.
- Если вы такие умные, то почему тогда строем не ходите?
ἓν οἶδα ὅτι οὐδὲν οἶδα (с) Σωκράτης
Реклама
Друг Кота
Сообщения: 4435
Зарегистрирован: Сб мар 07, 2009 20:44:36

Сообщение Arlleex »

помоему sbis - это пропустить. если бит установлен...
sbic - если очищен...
Не умеешь - не берись, но не взявшись не научишься...
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Вопрос???? как еще можно сканировать порт D

Код: Выделить всё

   in      KeyIN, pindD     
через IN не будет нормально работать ,у меня еще используются выводы порта D
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

через IN не будет нормально работать ,у меня еще используются выводы порта D
не понял.
Я делал так. Кнопка висела на внешнем прерывании, которое изначально настроил на спад (нажатие). Обработчик прерывания начинался с определения действия - нажалась или отжалась кнопка (проверка регистра настройки внешнего прерывания). Если нажалась, меняем настройку внешнего прерывания на нарастание (отжатие), включаем таймер и выходим из обработчика. Далее произошло снова прерывание (кнопка отжалась),снова меняемем настройку внешнего прерывания, соответственно проверяем таймер еще считает или нет, если да то тормозим его (чтоб не попасть в обработчик прерывания по таймеру) и выполняем то действие, которое должно выполнятся при коротком удержании кнопки. Ну а если таймер уже не считает, выходим из обработчика внешнего прерывания и попадаем в обрабочик прерывания по таймеру, где выполняем действие при длительном нажатии на кнопку. Вот эта постоянная настройка прерывания (регистр MCUCR) могла бы отсутствовать, если бы вы юзали другой МК, где есть настройка прерывания на любое изменение фронта. У тини2313 нету.[/quote]
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Реклама
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Не совсем понял у меня же 4 кнопки , или вы имеете ввиду использовать INT0 как общий провод для всех 4 кнопок????
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 119
Зарегистрирован: Ср ноя 07, 2007 15:17:20

Сообщение Dexa »

MTF писал(а):Не совсем понял у меня же 4 кнопки , или вы имеете ввиду использовать INT0 как общий провод для всех 4 кнопок????
Вообще я сказал как именно можно реализовать 2 действия на 1 кнопке. Вам на всех 4-х кнопках так надо или на одной? Если для всех 4 то надо подумать, ща в 2 ночи и не скажу)) И нет ничего удивительного в том что повесит 4 кнопки на INT. У меня 12 кнопок там весит.
......aлкоголь расширяет сосуды, курение их сужает, а сдают почему-то нервы......
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1116
Зарегистрирован: Чт окт 15, 2009 14:16:18
Откуда: Екб

Сообщение AI_Disable »

Я делал так: в основном цикле проверял, нажата ли кнопка, если да, то делаем ++ переменной. Если кнопка не нажата и переменная больше нуля, сравниваем её с неким значением(которое зависит от скорости выполнения основного цикла и подбирается экспериментально). Если переменная меньше - это кратковременно нажатие, если больше - длительное. После, сбрасываем переменную.
На мой взгляд, это самый рациональный и простой способ, т.к. не пожирает драгоценный таймер на такую ерунду и работает без задержек в цикле.
ЗЫ: единственный минус - если основной цикл повторяется очень быстро (тысячи раз в секунду), то тогда переменная начнёт жрать память, неподобающим образом.
Тут уж выбирайте, что вам важнее: таймер или 2-4 байта памяти.
Контактная информация:
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Возник вопрос?????

допустим

TmKey - счетчик времени нажатия кнопки

.............
inc TmKey
cpi TmKey , 50
brsh Long ; переход если больше или равно 1 секунде
.............
long:
.............
так я могу проверить только длительное нажатие

Кто нибудь знает, можно ли как нибудь при сравнении TmKey использовать выражение (больше 100мс но меньше 1000мс),
как это можно реализовать????
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

cpi TmKey, 50
brsh Long; переход если больше или равно 1 секунде
это означает "если больше ровно 1000 мс - переход".
Значит, если нет перехода, т.е. программа выполняется дальше, то проверяем TmKey> 100 мс? если да - переход, если нет - программа выполняет что-то другое. вот і все.

Код:
cpi TmKey, 50
brsh Long ; переход если больше или равно 1 секунде
cpi TmKey, 5
brsh Short ; переход если больше или равно 0.1 секунде - короткое нажатие
rjmp Drebezg ; иначе обрабативаем дребезг
.............

Long:
..........
Short:
..........
Drebezg:
..........
Последний раз редактировалось Петро Пт янв 08, 2010 16:04:27, всего редактировалось 1 раз.
Контактная информация:
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

не могу придумать как обработать нажатие и отпускание кнопки ,вот попробывал набросать!!!!!!!!
Чувствую что что то не так, может кто подскажет что я не так делаю и как надо обрабатывать кнопки????

Код: Выделить всё

T1OVF:
  in r16,portd   ; считываем порт d
  andi r16,0b00110110  ;обнуляем лишние pd
  cp r16,  keyold   ;срав со старым кодом кнопки
  mov keyold ,r16   ;записыв в keyold r16
  
  brne  A1  ; переход если не совпадает проверяем время кнопки 
  inc TmKey

????????
????????
????????
????????
A1:
  cpi TmKey, 50 
  brsh Long ; переход если больше или равно 1 секунде 
  cpi TmKey, 5 
  brsh Short ; переход если больше или равно 0.1 секунде -      короткое   нажатие 
  rjmp Drebezg ; иначе обрабативаем дребезг 
  ............. 

Long: 
.......... 
Short: 
.......... 
Drebezg: 
..........
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Код: Выделить всё

T1OVF: 
  in r16,portd   ; считываем порт d 
  andi r16,0b00110110  ;обнуляем лишние pd

  cpi r16,0  ;если r16=0, тоесть ни одна кнопка не нажата, то выход из обработчика
  brne _next_  ;иначе переход на сравнение со старым кодом кнопки
  mov keyold ,r16   ;запись в keyold r16 
  reti

_next_:
  cp r16,  keyold   ;сравнение со старым кодом кнопки 
  mov keyold ,r16   ;запись в keyold r16 

  brne  A1  ; переход если не совпадает, проверяем время кнопки 
  inc TmKey ;если же совпадает и r16 не 0, тоесть r16=1,то считаэм сколько миллисекунд кнопка уже нажата
Ну а если не совпадает, то значит кнопку отпустили
  reti 

A1:
  cpi TmKey, 50 
  brsh Long ; переход если больше или равно 1 секунде 
  cpi TmKey, 5 
  brsh Short ; переход если больше или равно 0.1 секунде -      короткое   нажатие 
  rjmp Drebezg ; иначе обрабативаем дребезг 
  ............. 
;Обрабатывать всякого рода нажатие нужно по этих метках:
Long: 
..........
reti
Short: 
.......... 
reti
Drebezg: 
..........
reti
Добавляэм reti, чтобы что-то одно выполнилось из трех,поскольку при переходе на Long после выполнения кода под ним еще и выполнится код под Short i Drebezg.
Контактная информация:
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Петро Огромное спасибо за помощь в написании кода :beer:

один маленький вопрос ???? TmKey надо , где то обнулять или нет ???
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Точно, я же забыл про обнуление TmKey.
Тогда часть кода, где ето нужно сделать, будет такова:

Код: Выделить всё

;Обрабатывать всякого рода нажатие нужно по этих метках: 
Long: 
.......... 
rjmp _return_ 
Short: 
.......... 
rjmp _return_ 
Drebezg: 
.......... 
rjmp _return_ 

_return_:
clr TmKey
reti
Ну что, заработало?
Контактная информация:
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Петро Все OK , заработало :)) спасибо за помощь :beer:
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Извиняюсь за назойливость ,вчера проверил только на короткое нажатие ,начал испытывать длинное нажатие ,выяснилось что (Long) работает как то не так ,если я держу ничего не происходит , только когда отпустишь.
возможно ли как то проверять Long не по отпусканию ?????
Это не хвост, это антенна
Аватара пользователя
Сообщения: 1306
Зарегистрирован: Вс янв 18, 2009 20:51:02

Сообщение ooogo »

а что будет если при нажатой кнопке еще и другую кнопку нажмут!? обработчик прерывания остановит счет начнет распознование нажатия на первую кнопку!?
может быть в основной программе проверять нажатие, и по нажатию запускать таймер(с тиканьем ~0.1c), в котором увеличивать переменную при переполнении(не обязательно от нуля) выставлять флаг длительного удержания, а в основной программе, пока нет отпускания этой кнопки(в цикле) проверять флаг длительного нажатия, а как только отпустили кнопку дребезг и короткое нажатие.
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

У меня все два таймера работает постоянно T0 СK/256 4Мгц,а второй не всегда поэтому и прилаживаю к T0 ,целую неделю бьюсь c этими кнопками (длительное нажатие), так и ничего не получается :cry:
Первый раз сказал Мяу!
Сообщения: 31
Зарегистрирован: Вс сен 13, 2009 15:42:50
Откуда: Львів

Сообщение Петро »

Чтобы длинное нажатие обрабатывалось во время самого нажатие(действия выполнялись каждие 1 сек соответственно), нужно поместить подпрограму Long сразу после смены TmKey. В обработчику Long заодно и отнимаем 50 от TmKey, чтоб после каждой 1-й секунди нажатия он мог снова дойти до 50 и мог выполниться обработчик.
Может быть еще случай, когда после длинного нажатия кнопку отпустили, а 0<TmKey<50. Поетому чтоб не выполнился лишний обработчик (Drebezg или Short), ми должны проверять в его начале было ли последнее нажатия длинным. Если было - флаг Т=1 (мы же устанавливаем его в 1 если нажатие длинное в обработчику), тогда пропускаем обработчик, переходим на _return_, очищаем флаг, выходим. Если же последнее нажатия не длинное, Т=0, тогда можно спокойно обрабатывать короткое или дребезг.

Код: Выделить всё

;запиши в начале страницы
.def temp=R25  ;или какой там регистр у тебя свободен

;...................
T1OVF: 
  in r16,portd   ; считываем порт d 
  andi r16,0b00110110  ;обнуляем лишние pd 

  cpi r16,0  ;если r16=0, тоесть ни одна кнопка не нажата, то выход из обработчика 
  brne _next_  ;иначе переход на сравнение со старым кодом кнопки 
  mov keyold ,r16   ;запись в keyold r16 
  reti 

_next_: 
  cp r16,  keyold   ;сравнение со старым кодом кнопки 
  mov keyold ,r16   ;запись в keyold r16 

  brne  A1  ; переход если не совпадает, проверяем время кнопки 
  inc TmKey ;если же совпадает и r16 не 0, тоесть r16=1,то считаэм сколько миллисекунд кнопка уже нажата 
;Ну а если не совпадает, то значит кнопку отпустили 
Long:
  set
  subi TmKey,50 
  .......... 
  rjmp _return_ 
  reti 

A1: 
  cpi TmKey, 50 
  brsh Long ; переход если больше или равно 1 секунде 
  cpi TmKey, 5 
  brsh Short ; переход если больше или равно 0.1 секунде -      короткое   нажатие 
  rjmp Drebezg ; иначе обрабативаем дребезг 
  .............

;Обрабатывать всякого рода нажатие нужно по этих метках: 
Short:
bld temp,0
sbic temp,0
rjmp _return_
.......... 
rjmp _return_
 
Drebezg:
bld temp,0
sbic temp,0
rjmp _return_ 
.......... 
rjmp _return_ 

_return_:
clt
clr TmKey 
reti
Контактная информация:
MTF
Нашел транзистор. Понюхал.
Аватара пользователя
Сообщения: 179
Зарегистрирован: Чт янв 07, 2010 11:25:12
Откуда: Москва

Сообщение MTF »

Петро походу что то не так !!!

а правильно ли мы делаем что считываем 0 (нажатие кнопки) с помощью PORTD ????

Код: Выделить всё

  in r16,portd   ; считываем порт d 
  andi r16,0b00110110  ;обнуляем лишние pd
может надо читать из pind ,

Код: Выделить всё

  in r16,portd


а то вообше перестала работать
нажимаешь вообще ничего не происходит

сначала при включении начались проблемы с таймером T0

оказалось ему не нравилось в T1 , выход по reti в начале

Код: Выделить всё

  in r16,portd   ; считываем порт d 
  andi r16,0b00110110  ;обнуляем лишние pd 

  cpi r16,0  ;если r16=0, тоесть ни одна кнопка не нажата, то выход из обработчика 
  brne _next_  ;иначе переход на сравнение со старым кодом кнопки 
  mov keyold ,r16   ;запись в keyold r16 
  rjmp keyend 

_next_: 
  cp r16,  keyold   ;сравнение со старым кодом кнопки 
  mov keyold ,r16   ;запись в keyold r16 

  brne  A1  ; переход если не совпадает, проверяем время кнопки 
  inc TmKey ;если же совпадает и r16 не 0, тоесть r16=1,то считаэм сколько миллисекунд кнопка уже нажата 
;Ну а если не совпадает, то значит кнопку отпустили 
Long: 
  set 
  subi TmKey,50 
  .......... 
  rjmp _return_ 
  reti

  ........
  ..
keyend:
  reti 

после переделки таймер T1 заработал нормально ,а вот реакции о клавы нет вообще!!!

попробывал в основном цикле такой вариант чтобы просто от нажатия пикало ,то же херь какая то получилась ,после нажатия таймер T1 опять заглючило ,спустя 2-3 сек опять раздался пик и T1 начинает работать нормально ,ума не приложу в чем дело ????

Код: Выделить всё

;основной цикл 
next: 
 
;   в таком варианте работает   
;   sbis PIND,plus
;   rcall beep 
;   sbis PIND,minus
;   rcall beep 
    
    in    tmp, pind
    andi  tmp, 0b00110000   ;
    cpi   tmp ,0b00010000   
    rjmp  beep            
    cpi   tmp ,0b00100000   
    rjmp  beep

rjmp next

Beep:
    sbi	OutPort,(0<<OutPin)  ; устанавливаем управ имп
    ldi     Razz2,0x06
    ldi     Razz1,0x1A
    ldi     Razz0,0x80
    rcall   delay ; 0,5 c
    cbi	  OutPort,(0<<OutPin)  ; устанавливаем управ имп
ret

Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»