Примерно лет шесть делаю так:
CODE
// в .h-файле:
// кол-во времени до события "длинное нажатие"
#define TIMER_COUNT 250
// кол-во кнопок
#define KEY_COUNT 4
// время автоинкремента
#define TIMER_SCROLL 20
// состояние кнопки
enum {KN_DOWN =0, KN_UP =1, KN_PRESS=2 };
// тип функции кнопки
typedef byte(KeyFunc)(void);
// структура хранящая набор переменных для каждой кнопки
typedef struct key_struct__
{
byte state; // состояние кнопки
byte mask; // маска клавиши
byte pins; // буфер значений с клавиши
byte count; // счетчик нажатий
KeyFunc * exec_down;
KeyFunc * exec_up;
KeyFunc * exec_pres;
}key_struct;
// в .c-файле:
//*****************************************************************************
// Драйвер кнопок
// назначение кнопок
// 1- MiNUS 2-PLUS 3- Select 4- Enter
//*****************************************************************************
//=============================================================================
// состояния кнопок
static key_struct key_mass [KEY_COUNT] = {
//state mask pins count exec_down exec_up exec_pres
{KN_UP, PIN_KEY_MINUS, 0xFF,0x00, kn_empty, kn_minus_up ,kn_minus_up }
,{KN_UP, PIN_KEY_PLUS, 0xFF,0x00, kn_empty, kn_plus_up ,kn_plus_up }
,{KN_UP, PIN_KEY_SELECT, 0xFF,0x00, kn_empty, kn_select_up ,kn_empty }
,{KN_UP, PIN_KEY_ENTER, 0xFF,0x00, kn_empty, kn_empty ,kn_enter_press }
};
//=============================================================================
ISR(TIMER1_COMPA_vect)
{
#define Sta key->state
#define Pin key->pins
#define Cnt key->count
#define Msk key->mask
#define Down key->exec_down
#define Up key->exec_up
#define Pres key->exec_pres
key_struct * key = key_mass;
for(byte i=0; i< KEY_COUNT ; i++)
{
Pin *=2; // * or <<
if(KEY_PIN & Msk) Pin |= 0x01;
if(Sta == KN_UP)
{
if(!Pin) // начало счета - нажатие
{
Down();
Sta = KN_DOWN;
Cnt = 0x00;
}
}
else // down or press
{
if(Pin==0xFF) // отпустили
{
if(Sta == KN_DOWN) Up();
Sta = KN_UP;
}
else// удерживаем
{
if(Cnt <= TIMER_COUNT) ++Cnt;
if(Cnt == TIMER_COUNT) // длительное удержание - попадаем один раз!!
{
if(Pres()) Cnt = TIMER_COUNT - TIMER_SCROLL;
else Sta = KN_PRESS;
}
}
}
key++;
}
}
Таймер в CTC-режиме на порядка 5....15 мсек
Сообщение отредактировал alexeyv - Aug 22 2011, 04:22