diff --git a/README.md b/README.md index ea55082..2cd542c 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,37 @@ # MultiButton ## 简介 + MultiButton 是一个小巧简单易用的事件驱动型按键驱动模块,可无限量扩展按键,按键事件的回调异步处理方式可以简化你的程序结构,去除冗余的按键处理硬编码,让你的按键业务逻辑更清晰。 ## 使用方法 + 1.先申请一个按键结构 ```c struct Button button1; ``` + 2.初始化按键对象,绑定按键的GPIO电平读取接口**read_button_pin()** ,后一个参数设置有效触发电平 ```c button_init(&button1, read_button_pin, 0); ``` + 3.注册按键事件 ```c -button_attach(&button1, SINGLE_CLICK, Callback_SINGLE_CLICK_Handler); -button_attach(&button1, DOUBLE_CLICK, Callback_DOUBLE_Click_Handler); +button_attach(&button1, SINGLE_CLICK, BTN_EVENT_Handler); +button_attach(&button1, DOUBLE_CLICK, BTN_EVENT_Handler); ... ``` + 4.启动按键 ```c button_start(&button1); ``` + 5.设置一个5ms间隔的定时器循环调用后台处理函数 ```c @@ -57,64 +63,198 @@ struct Button { struct Button* next; }; ``` -这样每个按键使用单向链表相连,依次进入 button_handler(struct Button* handle) 状态机处理,所以每个按键的状态彼此独立。 +这样每个按键使用单向链表相连,依次进入 button_handler(struct Button* handle) 状态机处理,所以每个按键的状态彼此独立。 ## 按键事件 -事件 | 说明 ----|--- -PRESS_DOWN | 按键按下,每次按下都触发 -PRESS_UP | 按键弹起,每次松开都触发 -PRESS_REPEAT | 重复按下触发,变量repeat计数连击次数 -SINGLE_CLICK | 单击按键事件 -DOUBLE_CLICK | 双击按键事件 -LONG_PRESS_START | 达到长按时间阈值时触发一次 -LONG_PRESS_HOLD | 长按期间一直触发 - +| 事件 | 说明 | +| ---------------- | ------------------------------------ | +| PRESS_DOWN | 按键按下,每次按下都触发 | +| PRESS_UP | 按键弹起,每次松开都触发 | +| PRESS_REPEAT | 重复按下触发,变量repeat计数连击次数 | +| SINGLE_CLICK | 单击按键事件 | +| DOUBLE_CLICK | 双击按键事件 | +| LONG_PRESS_START | 达到长按时间阈值时触发一次 | +| LONG_PRESS_HOLD | 长按期间一直触发 | ## Examples ```c -#include "button.h" +#include "multi_button.h" -struct Button btn1; +typedef enum { + BUTTON_ID_0, + BUTTON_ID_2, -uint8_t read_button1_GPIO() -{ - return HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); -} -void BTN1_PRESS_DOWN_Handler(void* btn) + BUTTON_ID_MAX + +} BUTTON_ID_INDEX; + +struct Button btnGroup[BUTTON_ID_MAX]; +uint8_t btnActiveLevel[BUTTON_ID_MAX] = {0, 0}; + +uint8_t read_button_level() { - //do something... + uint8_t code = 0x01; + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + if (get_button_current() == &btnGroup[i]) + { + switch (i) + { + case BUTTON_ID_0: + code = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); + break; + case BUTTON_ID_2: + code = HAL_GPIO_ReadPin(B2_GPIO_Port, B2_Pin); + break; + + default: + break; + } + } + } + return code; } -void BTN1_PRESS_UP_Handler(void* btn) +void BTN_EVENT_Handler(void *btn) { - //do something... -} + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + if (((Button *)btn) == &btnGroup[i]) + { + switch (((Button *)btn)->event) + { + case PRESS_DOWN: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; -... + default: + break; + } + break; + case PRESS_UP: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case PRESS_REPEAT: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case SINGLE_CLICK: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case DOUBLE_CLICK: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case LONG_PRESS_START: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case LONG_PRESS_HOLD: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + + default: + break; + } + } + } +} int main() { - button_init(&btn1, read_button1_GPIO, 0); - button_attach(&btn1, PRESS_DOWN, BTN1_PRESS_DOWN_Handler); - button_attach(&btn1, PRESS_UP, BTN1_PRESS_UP_Handler); - button_attach(&btn1, PRESS_REPEAT, BTN1_PRESS_REPEAT_Handler); - button_attach(&btn1, SINGLE_CLICK, BTN1_SINGLE_Click_Handler); - button_attach(&btn1, DOUBLE_CLICK, BTN1_DOUBLE_Click_Handler); - button_attach(&btn1, LONG_PRESS_START, BTN1_LONG_PRESS_START_Handler); - button_attach(&btn2, LONG_PRESS_HOLD, BTN1_LONG_PRESS_HOLD_Handler); - button_start(&btn1); - - //make the timer invoking the button_ticks() interval 5ms. - //This function is implemented by yourself. + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + button_init(&btnGroup[i], read_button_level, btnActiveLevel[i]); + + button_attach(&btnGroup[i], PRESS_DOWN, BTN_EVENT_Handler); + button_attach(&btnGroup[i], PRESS_UP, BTN_EVENT_Handler); + button_attach(&btnGroup[i], PRESS_REPEAT, BTN_EVENT_Handler); + button_attach(&btnGroup[i], SINGLE_CLICK, BTN_EVENT_Handler); + button_attach(&btnGroup[i], DOUBLE_CLICK, BTN_EVENT_Handler); + button_attach(&btnGroup[i], LONG_PRESS_START, BTN_EVENT_Handler); + button_attach(&btnGroup[i], LONG_PRESS_HOLD, BTN_EVENT_Handler); + + button_start(&btnGroup[i]); + } + + // make the timer invoking the button_ticks() interval 5ms. + // This function is implemented by yourself. __timer_start(button_ticks, 0, 5); - while(1) - {} + while (1) + { + } } ``` - - diff --git a/examples/example_callback.c b/examples/example_callback.c index d774069..ce6e392 100644 --- a/examples/example_callback.c +++ b/examples/example_callback.c @@ -1,58 +1,176 @@ #include "multi_button.h" -struct Button btn1; -struct Button btn2; +typedef enum { + BUTTON_ID_0, + BUTTON_ID_2, -uint8_t read_button1_GPIO() + BUTTON_ID_MAX + +} BUTTON_ID_INDEX; + +struct Button btnGroup[BUTTON_ID_MAX]; +uint8_t btnActiveLevel[BUTTON_ID_MAX] = {0, 0}; + +uint8_t read_button_level() { - return HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); + uint8_t code = 0x01; + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + if (get_button_current() == &btnGroup[i]) + { + switch (i) + { + case BUTTON_ID_0: + code = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); + break; + case BUTTON_ID_2: + code = HAL_GPIO_ReadPin(B2_GPIO_Port, B2_Pin); + break; + + default: + break; + } + } + } + return code; } -uint8_t read_button2_GPIO() +void BTN_EVENT_Handler(void *btn) { - return HAL_GPIO_ReadPin(B2_GPIO_Port, B2_Pin); + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + if (((Button *)btn) == &btnGroup[i]) + { + switch (((Button *)btn)->event) + { + case PRESS_DOWN: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case PRESS_UP: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case PRESS_REPEAT: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case SINGLE_CLICK: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case DOUBLE_CLICK: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case LONG_PRESS_START: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + case LONG_PRESS_HOLD: + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + break; + + default: + break; + } + } + } } int main() { - button_init(&btn1, read_button1_GPIO, 0); - button_init(&btn2, read_button2_GPIO, 0); - - button_attach(&btn1, PRESS_DOWN, BTN1_PRESS_DOWN_Handler); - button_attach(&btn1, PRESS_UP, BTN1_PRESS_UP_Handler); - button_attach(&btn1, PRESS_REPEAT, BTN1_PRESS_REPEAT_Handler); - button_attach(&btn1, SINGLE_CLICK, BTN1_SINGLE_Click_Handler); - button_attach(&btn1, DOUBLE_CLICK, BTN1_DOUBLE_Click_Handler); - button_attach(&btn1, LONG_PRESS_START, BTN1_LONG_PRESS_START_Handler); - button_attach(&btn1, LONG_PRESS_HOLD, BTN1_LONG_PRESS_HOLD_Handler); - - button_attach(&btn2, PRESS_DOWN, BTN2_PRESS_DOWN_Handler); - button_attach(&btn2, PRESS_UP, BTN2_PRESS_UP_Handler); - button_attach(&btn2, PRESS_REPEAT, BTN2_PRESS_REPEAT_Handler); - button_attach(&btn2, SINGLE_CLICK, BTN2_SINGLE_Click_Handler); - button_attach(&btn2, DOUBLE_CLICK, BTN2_DOUBLE_Click_Handler); - button_attach(&btn2, LONG_PRESS_START, BTN2_LONG_PRESS_START_Handler); - button_attach(&btn2, LONG_PRESS_HOLD, BTN2_LONG_PRESS_HOLD_Handler); - - button_start(&btn1); - button_start(&btn2); - - //make the timer invoking the button_ticks() interval 5ms. - //This function is implemented by yourself. - __timer_start(button_ticks, 0, 5); + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + button_init(&btnGroup[i], read_button_level, btnActiveLevel[i]); - while(1) - {} -} + button_attach(&btnGroup[i], PRESS_DOWN, BTN_EVENT_Handler); + button_attach(&btnGroup[i], PRESS_UP, BTN_EVENT_Handler); + button_attach(&btnGroup[i], PRESS_REPEAT, BTN_EVENT_Handler); + button_attach(&btnGroup[i], SINGLE_CLICK, BTN_EVENT_Handler); + button_attach(&btnGroup[i], DOUBLE_CLICK, BTN_EVENT_Handler); + button_attach(&btnGroup[i], LONG_PRESS_START, BTN_EVENT_Handler); + button_attach(&btnGroup[i], LONG_PRESS_HOLD, BTN_EVENT_Handler); -void BTN1_PRESS_DOWN_Handler(void* btn) -{ - //do something... -} + button_start(&btnGroup[i]); + } -void BTN1_PRESS_UP_Handler(void* btn) -{ - //do something... -} + // make the timer invoking the button_ticks() interval 5ms. + // This function is implemented by yourself. + __timer_start(button_ticks, 0, 5); -... \ No newline at end of file + while (1) + { + } +} \ No newline at end of file diff --git a/examples/example_poll.c b/examples/example_poll.c index 054cd72..1e9b6f3 100644 --- a/examples/example_poll.c +++ b/examples/example_poll.c @@ -1,37 +1,109 @@ #include "multi_button.h" -struct Button btn1; +typedef enum { + BUTTON_ID_0, + BUTTON_ID_2, -uint8_t read_button1_GPIO() + BUTTON_ID_MAX + +} BUTTON_ID_INDEX; + +struct Button btnGroup[BUTTON_ID_MAX]; +uint8_t btnActiveLevel[BUTTON_ID_MAX] = {0, 0}; + +uint8_t read_button_level() { - return HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); -} + uint8_t code = 0x01; + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + if (get_button_current() == &btnGroup[i]) + { + switch (i) + { + case BUTTON_ID_0: + code = HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin); + break; + case BUTTON_ID_2: + code = HAL_GPIO_ReadPin(B2_GPIO_Port, B2_Pin); + break; + default: + break; + } + } + } + return code; +} int main() { - static uint8_t btn1_event_val; - - button_init(&btn1, read_button1_GPIO, 0); - button_start(&btn1); - - //make the timer invoking the button_ticks() interval 5ms. - //This function is implemented by yourself. - __timer_start(button_ticks, 0, 5); - - while(1) + static uint8_t btn_event_val[BUTTON_ID_MAX] = {NONE_PRESS, NONE_PRESS}; + + for (size_t i = 0; i < BUTTON_ID_MAX; i++) { - if(btn1_event_val != get_button_event(&btn1)) { - btn1_event_val = get_button_event(&btn1); - - if(btn1_event_val == PRESS_DOWN) { - //do something - } else if(btn1_event_val == PRESS_UP) { - //do something - } else if(btn1_event_val == LONG_PRESS_HOLD) { - //do something + button_init(&btnGroup[i], read_button_level, btnActiveLevel[i]); + + button_start(&btnGroup[i]); + } + + // make the timer invoking the button_ticks() interval 5ms. + // This function is implemented by yourself. + __timer_start(button_ticks, 0, 5); + + while (1) + { + for (size_t i = 0; i < BUTTON_ID_MAX; i++) + { + if (btn_event_val[i] != get_button_event(&btnGroup[i])) + { + btn_event_val[i] = get_button_event(&btnGroup[i]); + + if (btn_event_val[i] == PRESS_DOWN) + { + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + } + else if (btn_event_val[i] == PRESS_UP) + { + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + } + else if (btn_event_val[i] == LONG_PRESS_HOLD) + { + switch (i) + { + case BUTTON_ID_0: + // do something + break; + case BUTTON_ID_2: + // do something + break; + + default: + break; + } + } } } } } - diff --git a/multi_button.c b/multi_button.c index 762c797..e091b54 100644 --- a/multi_button.c +++ b/multi_button.c @@ -10,6 +10,8 @@ //button handle list head. static struct Button* head_handle = NULL; +//button handle list head. +static struct Button* cur_handle = NULL; /** * @brief Initializes the button struct handle. * @param handle: the button handle strcut. @@ -48,6 +50,15 @@ PressEvent get_button_event(struct Button* handle) return (PressEvent)(handle->event); } +/** + * @brief Inquire the button handle used. + * @retval button handler. + */ +Button* get_button_current(void) +{ + return cur_handle; +} + /** * @brief Button driver core function, driver state machine. * @param handle: the button handle strcut. @@ -56,6 +67,7 @@ PressEvent get_button_event(struct Button* handle) void button_handler(struct Button* handle) { uint8_t read_gpio_level = handle->hal_button_Level(); + cur_handle = handle; //ticks counter working.. if((handle->state) > 0) handle->ticks++; diff --git a/multi_button.h b/multi_button.h index 6cf54d7..f64bc82 100644 --- a/multi_button.h +++ b/multi_button.h @@ -50,6 +50,7 @@ extern "C" { void button_init(struct Button* handle, uint8_t(*pin_level)(), uint8_t active_level); void button_attach(struct Button* handle, PressEvent event, BtnCallback cb); PressEvent get_button_event(struct Button* handle); +Button* get_button_current(void); int button_start(struct Button* handle); void button_stop(struct Button* handle); void button_ticks(void);