开源按键组件BitsButton介绍
GaoSheng Lv4

继MultiButton之后,发现了一个更加全能强大、小而美的按键组件:BitsButton
https://github.com/530china/BitsButton

该组件有一个不错的创新点,使用位序列记录按键状态,1代表按下,0代表松开。使你能够按键的整个生命周期
支持单键、组合键(如Ctrl+C)和复杂按键序列(如单击→长按→双击)

键值 说明
0b0 未按下
0b010 单击
0b01010 双击
0b01010...n n 连击
0b011 长按开始
0b0111 长按保持
0b01110 长按结束
0b01011 短按然后长按
0b0101011 双击然后长按
0b01010..n11 n 连击然后长按

目前BitsButton已经支持

  • 基础按键检测功能;
  • 合按键支持;
  • 按键结果高性能缓冲区支持;
  • 按键模拟器Window环境支持;
  • 按键模拟器Linux/macOS环境支持;

移植流程

1.将编译器选为C11标准
此处选择AC6
图片4
图片5

2.将bits_button.c和bits_button.h添加到工程
这里以keil为例:
图片6
图片7

3.将examples/example_poll.c里面的内容复制到你的Main.c
(1)根据你的MCU调整read_key_state函数里面获取按键(IO口)状态的函数
图片8
(2)配置按键按下状态的电平:
图片9

(3) 按键初始化

1
bits_button_init(btns, ARRAY_SIZEhexos), btns_combo, ARRAY_SIZE(btns_combo), read_key_state, NULL, my_log_printf)

(4)5ms周期性调用bits_button_ticks(),选择常规的定时器TIMER或者SYStick中断都行,这里选择SysTick_Handler

1
2
3
4
void SysTick_Handler(void)
{
bits_button_ticks();
}

测试情况:
图片10
图片11

下面是完整的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include "main.h"
#include "log.h"
#include <stdint.h>
#include "User_Systick_Config.h"
#include "bits_button.h"
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include "SEGGER_RTT.h"

typedef enum
{
USER_BUTTON_0 = 0,
USER_BUTTON_1,
USER_BUTTON_2,
USER_BUTTON_3,
USER_BUTTON_4,
USER_BUTTON_5,
USER_BUTTON_6,
USER_BUTTON_7,
USER_BUTTON_8,
USER_BUTTON_9,
USER_BUTTON_INVALID,
USER_BUTTON_MAX,

USER_BUTTON_COMBO_0 = 0x100,
USER_BUTTON_COMBO_1,
USER_BUTTON_COMBO_2,
USER_BUTTON_COMBO_3,
USER_BUTTON_COMBO_MAX,
} user_button_t;

// 2. 定义按键参数、单按键实例、组合按键实例
static const bits_btn_obj_param_t defaul_param = {.long_press_period_triger_ms = BITS_BTN_LONG_PRESS_PERIOD_TRIGER_MS,
.long_press_start_time_ms = BITS_BTN_LONG_PRESS_START_TIME_MS,
.short_press_time_ms = BITS_BTN_SHORT_TIME_MS,
.time_window_time_ms = BITS_BTN_TIME_WINDOW_TIME_MS};
button_obj_t btns[] =
{
BITS_BUTTON_INIT(USER_BUTTON_0, 0, &defaul_param),
BITS_BUTTON_INIT(USER_BUTTON_1, 1, &defaul_param),
// BITS_BUTTON_INIT(USER_BUTTON_2, 1, &defaul_param),
};

button_obj_combo_t btns_combo[] =
{
BITS_BUTTON_COMBO_INIT(
USER_BUTTON_COMBO_0, // 组合键ID
0, // 有效电平
&defaul_param, // 参数配置
((uint16_t[]){USER_BUTTON_0, USER_BUTTON_1}), // 组合按键成员
2, // 组合键成员数量
1), // 抑制单键事件
};

// 3. 读取按键状态函数
uint8_t read_key_state(struct button_obj_t *btn)
{
uint8_t _id = btn->key_id;
// you can share the GPIO read function with multiple Buttons
switch(_id)
{
case USER_BUTTON_0:
return (GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_15) == Bit_SET); //Require self implementation
break;
// case USER_BUTTON_1:
// return get_button2_value(); //Require self implementation
// break;
default:
return 0;
break;
}

return 0;
}

void SysTick_Handler(void)
{
bits_button_ticks();
}


/**
* @brief Inserts a delay time.
* @param count specifies the delay time length.
*/
void Delay(uint32_t count)
{
for (; count > 0; count--)
;
}


void KeyInputExtiInit(GPIO_Module* GPIOx, uint16_t Pin)
{
GPIO_InitType GPIO_InitStructure;
EXTI_InitType EXTI_InitStructure;
NVIC_InitType NVIC_InitStructure;

/* Enable the GPIO Clock */

RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA | RCC_APB2_PERIPH_AFIO, ENABLE);

GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = Pin;
GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input;
GPIO_InitPeripheral(GPIOx, &GPIO_InitStructure);

}

// 4. 日志函数(可选)
int my_log_printf(const char* format, ...) {

va_list args;
va_start(args, format);
int result = vprintf(format, args);
va_end(args);

return result;
}

/**
* @brief Main program.
*/
int main(void)
{
// 5. 按键初始化;
bits_button_init(btns, ARRAY_SIZE(btns), btns_combo, ARRAY_SIZE(btns_combo), read_key_state, NULL, my_log_printf);

//make the timer invoking the button_ticks() interval 5ms.
//This function is implemented by yourself.
// 6. 5ms周期性调用bits_button_ticks()
//__timer_start(bits_button_ticks, 0, 5);

/*SystemInit() function has been called by startup file startup_n32wb43x.s*/
log_init();
Systick_MS_Config(SystemCoreClock);
//make the timer invoking the button_ticks() interval 5ms.
//This function is implemented by yourself.

/*Initialize key as external line interrupt*/
KeyInputExtiInit(GPIOA, GPIO_PIN_15);


while (1)
{
bits_btn_result_t result = {0};
int32_t res = bits_button_get_key_result(&result);

if(res == true)
{
// printf("id:%d, event:%d, key_value:%d, long press period trigger cnt:%d \r\n", result.key_id, result.event, result.key_value, result.long_press_period_trigger_cnt);
// 可在此处进行按键结果处理,可参考example_callback.c中的bits_btn_result_cb()函数;
}
}
}
/**
* @}
*/
//int fputc(int ch, FILE* f)

//{

// if (ch == '\n') {

// SEGGER_RTT_PutChar(0, '\r');

// }

// SEGGER_RTT_PutChar(0, ch);

// return ch;

//}

本站由 提供部署服务