#include #include "key.h" #define EVENT_CB(ev) if(key->cb[ev])key->cb[ev](key) #define PRESS_REPEAT_MAX_NUM 15 static Key_t *head_key = NULL; static void key_state_switch(Key_t *key); void key_init(Key_t *key, uint8_t key_id, uint8_t active_level, uint8_t(*read_pin)(uint8_t)) { memset(key, 0, sizeof(Key_t)); key->event = (uint8_t) NONE_PRESS; key->hal_read_pin = read_pin; key->key_level = !active_level; key->active_level = active_level; key->key_id = key_id; } void key_attach(Key_t *key, PressEvent event, Key_Callback_t cb, bool start) { // 如果事件类型为ALL_EVENT,则将回调函数cb分别赋值给所有事件类型 if (event == KEY_ALL_EVENT) { for (uint8_t i = KEY_PRESS_UP; i < number_of_event; i++) { key->cb[i] = cb; } } else { // 否则,将回调函数cb赋值给指定的事件类型 key->cb[event] = cb; } if (start)key_start(key); } PressEvent get_key_event(Key_t *key) { return (PressEvent) (key->event); } static void key_state_switch(Key_t *key) { // 读取按键的GPIO电平 uint8_t read_gpio_level = key->hal_read_pin(key->key_id); // 如果按键状态大于0,则增加ticks计数 if ((key->state) > 0) key->ticks++; // 按键去抖动处理 if (read_gpio_level != key->key_level) { if (++(key->debounce_cnt) >= DEBOUNCE_TICKS) { key->key_level = read_gpio_level; key->debounce_cnt = 0; } } else { key->debounce_cnt = 0; } // 状态机处理按键事件 switch (key->state) { case 0: if (key->key_level == key->active_level) { key->event = (uint8_t) KEY_PRESS_DOWN; EVENT_CB(KEY_PRESS_DOWN); key->ticks = 0; key->repeat = 1; key->state = 1; } else { key->event = (uint8_t) NONE_PRESS; } break; case 1: if (key->key_level != key->active_level) { key->event = (uint8_t) KEY_PRESS_UP; EVENT_CB(KEY_PRESS_UP); key->ticks = 0; key->state = 2; } else if (key->ticks > LONG_TICKS) { key->event = (uint8_t) KEY_LONG_PRESS_START; EVENT_CB(KEY_LONG_PRESS_START); key->state = 5; } break; case 2: if (key->key_level == key->active_level) { key->event = (uint8_t) KEY_PRESS_DOWN; EVENT_CB(KEY_PRESS_DOWN); if (key->repeat != PRESS_REPEAT_MAX_NUM) { key->repeat++; } EVENT_CB(KEY_PRESS_REPEAT); key->ticks = 0; key->state = 3; } else if (key->ticks > SHORT_TICKS) { if (key->repeat == 1) { key->event = (uint8_t) KEY_SINGLE_CLICK; EVENT_CB(KEY_SINGLE_CLICK); } else if (key->repeat == 2) { key->event = (uint8_t) KEY_DOUBLE_CLICK; EVENT_CB(KEY_DOUBLE_CLICK); } key->state = 0; } break; case 3: if (key->key_level != key->active_level) { key->event = (uint8_t) KEY_PRESS_UP; EVENT_CB(KEY_PRESS_UP); if (key->ticks < SHORT_TICKS) { key->ticks = 0; key->state = 2; } else { key->state = 0; } } else if (key->ticks > SHORT_TICKS) { key->state = 1; } break; case 5: if (key->key_level == key->active_level) { key->event = (uint8_t) KEY_LONG_PRESS_HOLD; EVENT_CB(KEY_LONG_PRESS_HOLD); } else { key->event = (uint8_t) KEY_PRESS_UP; EVENT_CB(KEY_PRESS_UP); key->state = 0; } break; default: key->state = 0; break; } } int key_start(Key_t *key) { Key_t *target = head_key; while (target) { if (target == key) return -1; target = target->next; } key->next = head_key; head_key = key; return 0; } void key_stop(Key_t *key) { Key_t **curr; for (curr = &head_key; *curr;) { Key_t *entry = *curr; if (entry == key) { *curr = entry->next; #if KEY_STOP_FREE free(entry); #endif return; } else { curr = &entry->next; } } } void key_ticks(void) { Key_t *target; for (target = head_key; target; target = target->next) { key_state_switch(target); } }