Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите с кнопками
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > MCS51, AVR, PIC, STM8, 8bit
Maxi_Man
Помогите пожалуйста реализовать.
1)Необходимо, чтоб некая функция начинала выполняться после кратковременного нажатия кнопки и прерывалась после повторного нажатия.
2)Эта же функция начинала выполняться во время длительного нажатия кнопки (на протяжении всего нажатия) и прекращала выполняться после отпускания.
Кнопка одна и та же.
Контроллер: AtMega8;
Язык программирования:Си.
TSerg
Начните с чего-нибудь, уж.
alexeyv
1. Начните с обработчика нажатия кнопки и распознавания короткого и длительного нажатия
demiurg1978
Конечный автомат. Автоматное программирование. Цикл статей Татарчевского.
Есть нюанс. Так как кнопка одна, вам нужно тщательно продумать интерфейс, чтобы не было проблем. Нужно четко отличать, в каком состоянии какое нажатие. Иначе вы будете ожидать одной реакции на нажатия, а будет совершенно другая, так как не продуман интерфейс.

К примеру, исходное состояние девайса. Он должен ждать только короткое нажатие или только длинное. Или два коротких, к примеру. Два длинных.
В принципе, в одном состоянии можно ожидать короткое либо длинное нажатие. Но, повторяю, тщательно продумывайте. И без использования конечных автоматов не обойтись, если параллельно нужно выполнять какие-либо еще действия.

Программа будет примерно такая:

Опрос кнопки:
CODE

//========================================================================
#include "kbd_drv.h"
//========================================================================

//========================================================================
u08 _kbd_drv;

static u08 keys_buf;
//========================================================================

//========================================================================
void kbd_drv (void)
{
switch (_kbd_drv)
{
case KBD_DRV_NONE: // Состояние ожидания нажатия кнопки.
if (!(KNOPKA_PIN & (1<<KNOPKA))) // Если кнопка нажата,
{
set_timer (ST_KBD_1, DEBOUNCE_DELAY); // то установка таймера на подавление дребезга.
_kbd_drv = KBD_DRV_DOWN;
}
break;

case KBD_DRV_DOWN: // Подавление дребезга нажатия кнопки.
if (KNOPKA_PIN & (1<<KNOPKA))
{
_kbd_drv = KBD_DRV_NONE;
}
else
{
if (wait (ST_KBD_1)) // Если время подавления дребезга вышло,
{
Set_Event (EV_ID_KEY_PRESSED, SET_CLR_EVENT);
keys_buf = KEY_COD;

set_timer (ST_KBD_1, HOLD_DELAY); // то установка таймера на проверку удержания кнопки.
_kbd_drv = KBD_DRV_HOLD;
}
}
break;

case KBD_DRV_HOLD:
if (KNOPKA_PIN & (1<<KNOPKA))
{
_kbd_drv = KBD_DRV_WAIT_UP; // Установка состояния ожидания отжатия кнопки.
}
else
{
if (wait (ST_KBD_1)) // Если время удержания кнопки вышло,
{
Set_Event (EV_ID_KEY_PRESSED, SET_CLR_EVENT);
keys_buf = KEY_COD_HOLD;

set_timer (ST_KBD_1, HOLD_DELAY);
}
}
break;

case KBD_DRV_WAIT_UP: // Состояние ожидания отжатия кнопки.
if (KNOPKA_PIN & (1<<KNOPKA)) // Если кнопка отжата,
{
set_timer (ST_KBD_1, DEBOUNCE_DELAY); // то установка таймера на подавление дребезга.
_kbd_drv = KBD_DRV_UP;
}
break;

case KBD_DRV_UP: // Подавление дребезга отжатия кнопки.
if (!(KNOPKA_PIN & (1<<KNOPKA))) // Если кнопка нажата,
{
_kbd_drv = KBD_DRV_WAIT_UP;
}
else
{
if (wait (ST_KBD_1)) // Если время подавления дребезга вышло,
{
Set_Event (EV_ID_KEY_UNPRESSED, SET_CLR_EVENT);
_kbd_drv = KBD_DRV_NONE; // Установка состояния ожидания нажатия кнопки.
}
}
break;

default:
break;
}
}
//========================================================================

//========================================================================
u08 GetKeyCod (void)
{
return keys_buf;
}
//========================================================================


Выбор режима в зависимости от нажатий кнопки:
CODE

//========================================================================
#include "proc_fsm.h"
//========================================================================

//========================================================================
void proc_fsm (void)
{
static u08 _proc_fsm;

switch (_proc_fsm)
{
case PROC_FSM_INIT:
// Инициализация ввода-вывода
_proc_fsm = PROC_FSM_WAIT_KEYS_PRESSED;
break;

case PROC_FSM_WAIT_KEYS_PRESSED:
if (Get_Event (EV_ID_KEY_PRESSED)) // Если событие нажатия кнопки,
{
_proc_fsm = PROC_FSM_WAIT_SELECT_MODE; // то установка состояния выбора нажатия.
}
break;

case PROC_FSM_WAIT_SELECT_MODE:
if (Get_Event (EV_ID_KEY_UNPRESSED)) // Если событие отжатия кнопки, то это в любом случае было короткое нажатие.
{
set_led_1_blink_on (); // Включаем мигание светодиодом.
_proc_fsm = PROC_FSM_MODE_1;
return;
}

if (Get_Event (EV_ID_KEY_PRESSED)) // Если повторное событие нажатия кнопки, то это длинное нажатие кнопки.
{
led_1_on (); // Включаем светодиод.
_proc_fsm = PROC_FSM_MODE_2;
return;
}
break;

case PROC_FSM_MODE_1:
if (Get_Event (EV_ID_KEY_PRESSED)) // Если событие нажатия кнопки,
{
set_led_1_blink_off (); // то выключаем мигание светодиодом.
_proc_fsm = PROC_FSM_WAIT_KEYS_PRESSED;
return;
}

led_1_blink (); // Мигание светодиодом.
break;

case PROC_FSM_MODE_2:
if (Get_Event (EV_ID_KEY_UNPRESSED)) // Если событие отжатия кнопки,
{
led_1_off (); // то выключаем светодиод.
_proc_fsm = PROC_FSM_WAIT_KEYS_PRESSED;
}
break;

default:
break;
}
}
//========================================================================

//========================================================================
static u08 _led_blink;

#pragma inline
void set_led_1_blink_on (void)
{
led_1_on ();
set_timer (ST_LED_1_BLINK, LED_1_TIME);
_led_blink = 1;
}

#pragma inline
void set_led_1_blink_off (void)
{
led_1_off ();
_led_blink = 0;
}

#pragma inline
void led_1_blink (void)
{
switch (_led_blink)
{
case 0:
break;

case 1:
if (wait (ST_LED_1_BLINK))
{
led_1_switch ();
set_timer (ST_LED_1_BLINK, LED_1_TIME);
}
break;

default:
break;
}
}
//------------------------------------------------------------------------
#pragma inline
void led_1_on (void)
{
set_bit (LED_1_DDR, LED_1);
}

#pragma inline
void led_1_off (void)
{
clr_bit (LED_1_DDR, LED_1);
}

#pragma inline
void led_1_switch (void)
{
switch_bit (LED_1_DDR, LED_1);
}
//========================================================================
zombi
Цитата(Maxi_Man @ Oct 22 2015, 08:53) *
Помогите пожалуйста реализовать.
1)Необходимо, чтоб некая функция начинала выполняться после кратковременного нажатия кнопки и прерывалась после повторного нажатия.
2)Эта же функция начинала выполняться во время длительного нажатия кнопки (на протяжении всего нажатия) и прекращала выполняться после отпускания.
Кнопка одна и та же.
Контроллер: AtMega8;
Язык программирования:Си.

Если на кнопку будет нажимать человек, то достаточно будет прерывания
(к примеру 1 ms) в котором опрашивать состояние кнопки.
Запоминать время нажатия и по отпусканию решать длительное/кратковременно оно было.
Обязательно позаботиться об устранении дребезга контактов кнопки.
На СИ это мне не под силу.
mcheb
Это только за пиво, причём очень хорошее
One
Цитата(zombi @ Oct 23 2015, 02:13) *
...Запоминать время нажатия и по отпусканию решать длительное/кратковременно оно было.Обязательно позаботиться об устранении дребезга контактов кнопки.
На СИ это мне не под силу.

так выше demiurg1978 Вам уже все очень даже подробно изложил, осталось только перенести в тело программы его код
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.