修改:对每个按键独立,自行判断自己的短按、长按、连续按;
head file
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
| /*----------------包含头文件----------------*/
#include <stdint.h>
/*----------------按键扫描----------------*/
#define USE_SHORT_PRESS 0X01
#define USE_LONG_PRESS 0X02
#define USE_UNION_PRESS 0X04
#define USE_CONTINUE_PRESS 0X08
#define KEY_USE_PRESS (USE_SHORT_PRESS|USE_LONG_PRESS|USE_CONTINUE_PRESS)
/*----------------按键状态值设置----------------*/
#define KEY_NONE 0X00
#define KEY_PRESS 0X01
#define KEY_RELEASE 0X02
#define KEY_SHORT_PRESS 0X0A
#define KEY_LONG_PRESS 0X0B
#define KEY_CONTINUE_PRESS 0X0C
/*----------------按键返回值设置----------------*/
#define KEY_NONE 0X00
#define KEY1_SHORT_PRESS 0X01
#define KEY2_SHORT_PRESS 0X02
#define KEY3_SHORT_PRESS 0X04
#define KEY1_RELEASE 0X11
#define KEY2_RELEASE 0X12
#define KEY3_RELEASE 0X14
#define KEY1_LONG_PRESS 0X21
#define KEY2_LONG_PRESS 0X22
#define KEY3_LONG_PRESS 0X24
#define KEY1_CONTINUE_PRESS 0X31
#define KEY2_CONTINUE_PRESS 0X32
#define KEY3_CONTINUE_PRESS 0X34
#define KEY12_UNION_PRESS 0X43
#define KEY23_UNION_PRESS 0X46
#define KEY13_UNION_PRESS 0X45
/*----------------按键端口配置----------------*/
#define KEY1_READ_PIN() HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)
#define KEY2_READ_PIN() HAL_GPIO_ReadPin(KEY_UP_GPIO_Port, KEY_UP_Pin)
/*----------------按键结构体----------------*/
typedef struct
{
uint8_t current_state; /*按键当前状态*/
uint8_t previous_state; /*按键上一状态*/
uint8_t release_state; /*1表示释放,0表示未释放,ff为联合按键钳位*/
uint16_t press_count; /*按键时长计数*/
uint8_t return_value; /*按键返回状态*/
} KeyHandle;
|
source file
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
| /*----------------按键参数设置----------------*/
#define DEBOUNCE_CNT 5 /*5*10ms=50ms*/
#define LONG_PRESS_CNT 100 /*100*10ms=1000ms*/
#define CONTINUE_PRESS_CNT 20 /*20*10=200ms*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*----------------变量定义----------------*/
static KeyHandle key1 = {0};
static KeyHandle key2 = {0};
static KeyHandle key3 = {0};
uint8_t KeyJudgement(KeyHandle *key)
{
key->return_value = KEY_NONE;
if (key->current_state == 0)
{
/*按键被释放*/
if (key->previous_state != 0) /*按键刚被释放*/
{
/*消抖*/
if ((key->press_count >= DEBOUNCE_CNT) && (key->release_state != 0xff))
{
// if ((key->press_count <= LONG_PRESS_CNT) ||
// (KEY_USE_PRESS == USE_SHORT_PRESS))
{
if (key->previous_state == KEY_PRESS)
{
key->return_value = KEY_RELEASE;
}
}
}
/*清空上一个状态和按键计数*/
key->previous_state = KEY_NONE;
key->press_count = 0;
}
/*标记按键释放*/
key->release_state = TRUE;
}
else
{
/*当前值和上一个值不一致----当前状态刚按下*/
if (key->previous_state != key->current_state)
{
key->previous_state = key->current_state;
key->press_count = 0;
}
else /*持续按下*/
{
key->press_count++;
if (key->press_count >= DEBOUNCE_CNT) /*消抖*/
{
/*按键正在被按下*/
if (key->release_state == TRUE)
{
key->release_state = FALSE;
if (key->current_state == KEY_PRESS)
{
key->return_value = KEY_SHORT_PRESS;
}
}
else
{
#if (KEY_USE_PRESS & USE_LONG_PRESS)
if ((key->press_count >= LONG_PRESS_CNT) &&
(key->press_count < (LONG_PRESS_CNT + 5)))
{
key->press_count += 5;
if (key->current_state == KEY_PRESS)
{
key->return_value = KEY_LONG_PRESS;
}
}
#endif
#if (KEY_USE_PRESS & USE_CONTINUE_PRESS)
if ((key->press_count >= LONG_PRESS_CNT) &&
(key->press_count % CONTINUE_PRESS_CNT == 0))
{
if (key->current_state == KEY_PRESS)
{
key->return_value = KEY_CONTINUE_PRESS;
}
}
#endif
}
}
}
}
return key->return_value;
}
/**
@brief 按键检测,建议每10ms检测一次
@param none
@return 按键的状态
*/
uint8_t KeyScan(void)
{
uint8_t value = KEY_NONE;
/*这里可以根据需求进行联合按键的检测*/
/*目前针对多个按键同一瞬间按下/释放的情况,会丢失数据,可以使用每个按键一个返回值来做*/
/*用户根据需要修改这个函数*/
key1.current_state = KEY_NONE;
key2.current_state = KEY_NONE;
/*读取按键IO口状态*/
if (KEY1_READ_PIN() == GPIO_PIN_SET)
{
key1.current_state |= KEY_PRESS;
}
if (KEY2_READ_PIN() == GPIO_PIN_SET)
{
key2.current_state |= KEY_PRESS;
}
KeyJudgement(&key1);
KeyJudgement(&key2);
if (key1.return_value == KEY_SHORT_PRESS)
{
value = KEY1_SHORT_PRESS;
}
else if (key1.return_value == KEY_LONG_PRESS)
{
value = KEY1_LONG_PRESS;
}
else if (key1.return_value == KEY_CONTINUE_PRESS)
{
value = KEY1_CONTINUE_PRESS;
}
else if (key1.return_value == KEY_RELEASE)
{
value = KEY1_RELEASE;
}
if (key2.return_value == KEY_SHORT_PRESS)
{
value = KEY2_SHORT_PRESS;
}
else if (key2.return_value == KEY_LONG_PRESS)
{
value = KEY2_LONG_PRESS;
}
else if (key2.return_value == KEY_CONTINUE_PRESS)
{
value = KEY2_CONTINUE_PRESS;
}
else if (key2.return_value == KEY_RELEASE)
{
value = KEY2_RELEASE;
}
return value;
}
|
example
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
| key_status = KeyScan2();
switch (key_status)
{
case KEY1_SHORT_PRESS:
printf("KEY1_SHORT_PRESS\n");
break;
case KEY2_SHORT_PRESS:
printf("KEY2_SHORT_PRESS\n");
break;
case KEY1_RELEASE:
printf("KEY1_RELEASE\n");
break;
case KEY2_RELEASE:
printf("KEY2_RELEASE\n");
break;
case KEY1_LONG_PRESS:
printf("KEY1_LONG_PRESS\n");
break;
case KEY2_LONG_PRESS:
printf("KEY2_LONG_PRESS\n");
break;
case KEY1_CONTINUE_PRESS:
printf("KEY1_CONTINUE_PRESS\n");
break;
case KEY2_CONTINUE_PRESS:
printf("KEY2_CONTINUE_PRESS\n");
break;
case KEY12_UNION_PRESS:
printf("KEY1_2_UNION_PRESS\n");
break;
default:
break;
}
|
该简易版按键扫描程序支持短按、长按、联合按三个功能,没有对按键抬起做检测。
程序如下:
head file
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
| /*----------------包含头文件----------------*/
#include <stdint.h>
/*----------------按键扫描开始----------------*/
#define USE_SHORT_PRESS 0X01
#define USE_LONG_PRESS 0X02
#define USE_UNION_PRESS 0X04
#define KEY_USE_PRESS (USE_SHORT_PRESS|USE_LONG_PRESS|USE_UNION_PRESS)
#define LONG_PRESS_CNT 50 /*50*10ms=500ms*/
#define KEY_NONE 0X00
#define KEY1_SHORT_PRESS 0X01
#define KEY2_SHORT_PRESS 0X02
#define KEY3_SHORT_PRESS 0X04
#define KEY1_LONG_PRESS 0X10
#define KEY2_LONG_PRESS 0X20
#define KEY3_LONG_PRESS 0X40
#define KEY12_UNION_PRESS 0X03
#define KEY23_UNION_PRESS 0X06
#define KEY13_UNION_PRESS 0X05
/*按键端口配置*/
#define KEY1_READ_PIN() HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)
#define KEY2_READ_PIN() HAL_GPIO_ReadPin(KEY_UP_GPIO_Port, KEY_UP_Pin)
uint8_t KeyScan(void);
/*----------------按键扫描结束----------------*/
|
source file
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
|
/**
@brief 按键检测,建议每10ms检测一次
@param none
@return 按键的状态
*/
uint8_t KeyScan(void)
{
static uint8_t key_prev_state = 0; /*按键上一状态*/
static uint16_t key_press_cnt = 0; /*按键时长计数*/
static uint8_t key_release = 0; /*1表示释放,0表示未释放,ff为联合按键钳位*/
uint8_t key_curr_state = 0; /*按键当前状态*/
uint8_t ret_val = KEY_NONE; /*按键返回状态*/
/*读取按键IO口状态*/
if (KEY1_READ_PIN() == GPIO_PIN_SET)
{
key_curr_state |= 0x01; /*按键1按下*/
}
if (KEY2_READ_PIN() == GPIO_PIN_SET)
{
key_curr_state |= 0x02;
}
/*当前无按键按下*/
if (key_curr_state == 0)
{
/*按键刚刚松开*/
if (key_prev_state != 0)
{
/*消抖*/
if ((key_press_cnt >= 5) && (key_release != 0xff))
{
if ((key_prev_state == 0x01) && (key_press_cnt <= LONG_PRESS_CNT))
{
ret_val = KEY1_SHORT_PRESS;
}
else if ((key_prev_state == 0x02) && (key_press_cnt <= LONG_PRESS_CNT))
{
ret_val = KEY2_SHORT_PRESS;
}
else if ((key_prev_state == 0x04) && (key_press_cnt <= LONG_PRESS_CNT))
{
ret_val = KEY3_SHORT_PRESS;
}
#if (KEY_USE_PRESS & USE_LONG_PRESS)
else if ((key_prev_state == 0x01) && (key_press_cnt > LONG_PRESS_CNT))
{
ret_val = KEY1_LONG_PRESS;
}
else if ((key_prev_state == 0x02) && (key_press_cnt > LONG_PRESS_CNT))
{
ret_val = KEY2_LONG_PRESS;
}
else if ((key_prev_state == 0x04) && (key_press_cnt > LONG_PRESS_CNT))
{
ret_val = KEY3_LONG_PRESS;
}
#endif
else
{
ret_val = KEY_NONE;
}
}
else
{
ret_val = KEY_NONE;
}
/*清空上一个状态和按键计数*/
key_prev_state = 0;
key_press_cnt = 0;
}
/*一直无按键*/
else
{
ret_val = KEY_NONE;
}
/*标记按键释放*/
key_release = 1;
}
/*当前有按键按下*/
else
{
if (key_release == 1)
{
key_release = 0;
}
/*当前值和上一个值不一致----当前状态刚按下*/
if (key_prev_state != key_curr_state)
{
key_prev_state = key_curr_state;
key_press_cnt = 0;
}
/*持续按下*/
else
{
key_press_cnt++;
/*消抖*/
if (key_press_cnt >= 10)
{
if (key_release == 0)
{
#if (KEY_USE_PRESS & USE_UNION_PRESS)
if (key_curr_state == 0x03)
{
ret_val = KEY12_UNION_PRESS;
key_release = 0xff;
}
else if (key_curr_state == 0x05)
{
ret_val = KEY13_UNION_PRESS;
key_release = 0xff;
}
else if (key_curr_state == 0x06)
{
ret_val = KEY23_UNION_PRESS;
key_release = 0xff;
}
else
{
ret_val = KEY_NONE;
}
#endif
}
else
{
ret_val = KEY_NONE;
}
}
else
{
ret_val = KEY_NONE;
}
}
}
return ret_val;
}
|
example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| key_status = KeyScan();
switch (key_status)
{
case KEY1_SHORT_PRESS:
printf("KEY1_SHORT_PRESS\n");
break;
case KEY2_SHORT_PRESS:
printf("KEY2_SHORT_PRESS\n");
break;
case KEY1_LONG_PRESS:
printf("KEY1_LONG_PRESS\n");
break;
case KEY2_LONG_PRESS:
printf("KEY2_LONG_PRESS\n");
break;
case KEY12_UNION_PRESS:
printf("KEY1_2_UNION_PRESS\n");
break;
default:
break;
}
|