Микроконтроллеры, АЦП, память и т.д Темы касающиеся микроконтроллеров разных производителей, памяти, АЦП/ЦАП, периферийных модулей... |
14.04.2011, 14:15
|
|
Заблокирован
Регистрация: 26.12.2009
Сообщений: 3,124
Сказал спасибо: 116
Сказали Спасибо 867 раз(а) в 614 сообщении(ях)
|
Re: Отследить короткое и продолжительное нажатие кнопки в фонаре. Как???
В такой задаче прерывания и нафиг не впёрлись, разве что только выходить из сна... Всё остальное в цикле по флагам...
|
|
|
|
14.04.2011, 16:15
|
|
Временная регистрация
Регистрация: 11.04.2011
Сообщений: 54
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Отследить короткое и продолжительное нажатие кнопки в фонаре. Как???
Спасибо, за ответы, но я всё таки хочу понять что именно я делаю не так???? Описываю каждый шаг.
Итак, кратко нажали - запустили таймер на генерацию ШИМа, ещё раз нажали - выключини таймер. Удерживаем › 1 сек - флаг долгого нажатия.
Код:
|
#define button PINB.0
volatile bit long_push = 0;
volatile unsigned int cnt = 0;
volatile bit state = 0;
...
// Clock value: 7812,5 Hz
TCCR0=0x05;
TCNT0=0xB2;
...
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
// Reinitialize Timer 0 value
TCNT0=0xB2; // срабатывание каждые ~10 мс
if (!button) { // если нажата кнопка т.е. PINB.0 не равен 1
cnt++; // прибавляем счетчик
if (cnt›65534) { // если кому то вздумается очень долго удерживать кнопку
cnt=101; // чтобы не перевалили за значение 65535
}
}
else if (button) { // если на PINB.0 стал 1
cnt=0; // то сбрасываем счетчик
long_push=0; // сбрасываем бит долгого нажатия
}
if ((cnt › 3) && (cnt ‹ 100)) { // проверяем условие короткого нажатия (держали › 40 мс и ‹ 1 сек; 10мс * 100 срабатываний)
// заодно и подавляем дребезг 40 мс (10 мс * 4 срабатывания)
if (!state) { // если фонарь выключен, то
OCR2=0x7D; // установили 50% ШИМ
TCCR2=0x6A; // запустили таймер (вкл)
state = 1; // флаг что фонарь включен
}
else if (state) { // если фонарь включен, то
OCR2=0x00; // выключили ШИМ
TCCR2=0x00; // остановили таймер (выкл)
state = 0; // флаг что фонарь выключен
}
}
if (cnt › 100) { // если держим › 1 сек - это длинное нажатие
long_push = 1; // потом проверяем long_push в основном цикле
}
} |
Что не правильно то??? Не понимаю
Последний раз редактировалось poligon_85; 14.04.2011 в 16:49.
|
|
|
|
14.04.2011, 16:39
|
|
Прописка
Регистрация: 25.08.2007
Сообщений: 193
Сказал спасибо: 11
Сказали Спасибо 57 раз(а) в 33 сообщении(ях)
|
Re: Отследить короткое и продолжительное нажатие кнопки в фонаре. Как???
Сообщение от poligon_85
|
что именно я делаю не так????
|
Да вот сразу не так. Если нажата кнопка, прибавляете счетчик. Так уже на следующем срабатывании таймера (через 10mS) у вас придет 1 из за дребезга кнопки и Ваш счетчик сбрасывается. Дальше смотреть даже нет смысла. Вы вложение в посте №25 скачайте, там точно выполнено то что Вы хотите и посмотрите как.
|
|
|
|
14.04.2011, 16:54
|
|
Временная регистрация
Регистрация: 11.04.2011
Сообщений: 54
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Да скачивал я. Там в #defineах запутаться можно. Хотя в протеусе всё работает с вашей прошивкой.
Но хочу разобраться в своем варианте. Что подправить то????
Код:
|
volatile int cnt = 0;
...
else if (button) { // если на PINB.0 стал 1
cnt--; // то вычитаем счетчик
long_push=0; // сбрасываем бит долгого нажатия
} |
Т.е. как накопилось в cnt нужное значение, то выполняем действие. Тем самым компенсируем случайный дребезг. Так?
Последний раз редактировалось poligon_85; 14.04.2011 в 17:00.
|
|
|
|
14.04.2011, 17:18
|
|
Прописка
Регистрация: 25.08.2007
Сообщений: 193
Сказал спасибо: 11
Сказали Спасибо 57 раз(а) в 33 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Чтобы компенсировать дребезг нужно сделать задержку 40-100mS, после этого нужно убедится, что состояние пина то же, что и до задержки. Значит сработала кнопка. Или нажата или отжата. Ведь, в Вашем случае важно и то и другое. Причем и нажатие и отжатие кнопки обрабатывается каждый раз по разному, в зависимости от того в каком режиме находится устройство (сами такие условия задали управлением одной кнопкой). Поэтому, представьте сначала на бумаге (или в голове, если умещается ) алгоритм работы. Пока, судя по коду, Вы его не представляете. А вот если в #definах моих разберетесь, а это кстати все состояния автомата вашей задачи, тогда и код напишете.
|
|
|
|
14.04.2011, 17:18
|
|
Гуру портала
Регистрация: 27.10.2008
Адрес: ЕС
Сообщений: 10,835
Сказал спасибо: 919
Сказали Спасибо 4,308 раз(а) в 2,573 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Запускаем два таймера, один быстрый, другой медленный. Лучше все сделать на одном, но для начала можно использовать и два.
Быстрый таймер опрашивает кнопку. Если кнопка нажата, инкременирует одну переменную и сбрасывает на ноль второй таймер.
Если сработал второй таймер, значит кнопку уже отпустили. Значение инкременнированной переменной - длинна нажатия кнопки.
Элементарная работа для двух прерываний. Но опять же - это простой и не корректный способ.
Зато дребезг мы победили.
|
|
|
|
14.04.2011, 18:43
|
|
Временная регистрация
Регистрация: 11.04.2011
Сообщений: 54
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Не понимаю я ваш код oleg_harp, точнее отчасти понимаю, но считаю что он избыточен.
Зачем так писать?
Код:
|
PIN_State = PINB.0; // считать состояние пина кнопки
if (PIN_State ==!Prev_PIN_State) // если состояние пина кнопки изменилось
{
Button_State = PIN_State; // запомнить состояние пина кнопки
PIN_Change = Changed; // установить флаг изменения
Time = 0; // запустить отсчет времени для антидребезга
}; |
Если можно: "считать состояние пина кнопки; если состояние пина кнопки изменилось"
"запустить отсчет времени для антидребезга"
Дальше:
Код:
|
if (Time == 5) // если через 8ms x 5 = 40mS
// состояние пина не изменилось |
мой код:
Код:
|
if ((cnt › 3) && (cnt ‹ 100)) { // проверяем условие короткого нажатия (держали › 40 мс и ‹ 1 сек; 10мс * 100 срабатываний)
// заодно и подавляем дребезг 40 мс |
Зачем писать так сложно как вы? Я наверное слишком тупой, но я хоть убейте не понимаю
Последний раз редактировалось poligon_85; 14.04.2011 в 18:49.
|
|
|
|
14.04.2011, 21:56
|
|
Прописка
Регистрация: 25.08.2007
Сообщений: 193
Сказал спасибо: 11
Сказали Спасибо 57 раз(а) в 33 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Цитата:
|
Не понимаю я ваш код oleg_harp, точнее отчасти понимаю, но считаю что он избыточен.
|
Не спорю. Я его не оптимизировал. Просто написал по быстрому решение Вашей задачи. Я не профессионал. Но Вы можете проверить, он будет надёжно работать не только в Proteus, но и в реале.
Цитата:
|
Если можно: "считать состояние пина кнопки; если состояние пина кнопки изменилось"
Код:
|
Код:
if (PINB.0 == 0) |
|
А где здесь проверяется изменение состояния пина? Я вижу, что проверяется состояние пина на равенство нулю (нажатие кнопки). А если кнопку отпустили? По Вашему когда её отпускают ничего не должно происходить?
|
|
|
|
14.04.2011, 23:42
|
|
Временная регистрация
Регистрация: 11.04.2011
Сообщений: 54
Сказал спасибо: 0
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Когда отпускают:
Код:
|
else if (button) { // если на PINB.0 стал 1
cnt=0; // то сбрасываем счетчик
long_push=0; // сбрасываем бит долгого нажатия
} |
Не понимаю почему не работает у меня, и не понимаю почему работает у вас
|
|
|
|
15.04.2011, 00:29
|
|
Прописка
Регистрация: 25.08.2007
Сообщений: 193
Сказал спасибо: 11
Сказали Спасибо 57 раз(а) в 33 сообщении(ях)
|
Re: Как отследить короткое и продолжительное нажатие кнопки в фонаре?
Сообщение от poligon_85
|
Когда отпускают:
Код:
|
else if (button) { // если на PINB.0 стал 1
cnt=0; // то сбрасываем счетчик
long_push=0; // сбрасываем бит долгого нажатия
} |
Не понимаю почему не работает у меня, и не понимаю почему работает у вас
|
Этот кусок кода как раз в Proteus у Вас будет работать. В реальной схеме через раз, потому что вы не отрабатываете дребезг контактов. Я об этом написал в посте #33.
А вот этот кусок нерабочий. Пока у Вас нажата кнопка каждые 10mS переменная state будет инвертироваться (cnt же будет проходить значения от 4 до скольких-нибудь), и из этого If state будет выходить каждый раз с неопределенным значением.
Код:
|
if ((cnt › 3) && (cnt ‹ 100)) { // проверяем условие короткого нажатия (держали › 40 мс и ‹ 1 сек; 10мс * 100 срабатываний)
// заодно и подавляем дребезг 40 мс (10 мс * 4 срабатывания)
if (!state) { // если фонарь выключен, то
OCR2=0x7D; // установили 50% ШИМ
TCCR2=0x6A; // запустили таймер (вкл)
state = 1; // флаг что фонарь включен
}
else if (state) { // если фонарь включен, то
OCR2=0x00; // выключили ШИМ
TCCR2=0x00; // остановили таймер (выкл)
state = 0; // флаг что фонарь выключен
}
}
if (cnt › 100) { // если держим › 1 сек - это длинное нажатие
long_push = 1; // потом проверяем long_push в основном цикле
}
} |
А я, кстати, понял почему мой код показался Вам сложным. Я действительно немного усложнил Ваш алгоритм, потому что мне показалось это удобным для пользователя. У меня при включении фонарика сразу можно удержать кнопку и регулировать яркость. Если это выкинуть и сделать как Вы написали изначально, т.е. включение - короткое нажатие-отпускание, а затем опять нажатие и удержание для регулировки яркости, то можно будет выкинуть пару состояний и код сократится.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 20:12.
|
|