单片机长短按简单实现
1 原理
按键检测和处理的步骤如下:
1:定时扫描按键(使用定时器定时扫描,也可以用软件延时或者系统心跳之类的方式,总之能保证每次扫描间隔时间固定并且在一个较小的范围即可)。
2:扫描到有按键按下(通常是检测GPIO的电平状态来判断按键是否按下,具体情况需要结合实际硬件电路来看)。
3:开始计时,记录按键持续按下的时间。
4:若按下的时间达到了短按的时间(具体多长的时间为短按由自己定义),选择触发按键处理(按下即触发),或者先记录状态,等按键释放时再触发按键处理(弹起时触发)。
5:按键时间超过短按时间,继续计时。
6:按键时间达到长按时间(具体多长的时间为长按由自己定义),选择触发按键处理(按下即触发),或者先记录状态,等按键释放时再触发按键处理(弹起时触发)。
2 示例代码
该示例使用的GD32,共配置了4个按键,特点如下:
1:按键按下时电平为0,释放时为1。
2:短按时间为30ms。
3:长按时间为1s。
4:短按释放时触发按键处理。
5:长按按下时即触发按键处理。
6:按键扫描和按键处理均放在定时器中断服务函数,若按键处理的时间较长,建议分开操作(按键扫描还是放在中断,按键处理放在其他地方,以免长时间占用中断时间)。
7:按键处理我这里都是留空的,只用串口打印了一句话,表明已经触发了按键处理,具体处理什么东西看实际需求。
注:示例代码仅供参考,还需要按具体需求修改。
2.1 按键实现
key.c:
#include "key.h"
#include "main.h"
key_t key1;
key_t key2;
key_t key3;
key_t key4;
void timer_user_init(void);
// 按键初始化
void key_user_init(void)
{
/* enable the key clock */
rcu_periph_clock_enable(KEY1_CLOCK);
rcu_periph_clock_enable(KEY2_CLOCK);
rcu_periph_clock_enable(KEY3_CLOCK);
rcu_periph_clock_enable(KEY4_CLOCK);
/* configure key gpio port */
gpio_init(KEY1_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, KEY1_PIN);
gpio_init(KEY2_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, KEY2_PIN);
gpio_init(KEY3_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, KEY3_PIN);
gpio_init(KEY4_PORT, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, KEY4_PIN);
timer_user_init(); // 启动定时器,定时扫描按键
}
// 按键扫描
int key_scan(void)
{
if(READ_KEY1_STATE == KEY_PRESSED && (key1.status == 0))
{
if(++key1.debounce > KEY_SHORT_PRESSED)
{
// 短按
key1.status = 1;
// LOG("key1 short pressed.\n");
}
}
else if(READ_KEY1_STATE == KEY_PRESSED && (key1.status == 1))
{
if(++key1.debounce > KEY_LONG_PRESSED)
{
// 长按
key1.status = 2;
key1.debounce = 0;
// LOG("key1 long pressed.\n");
return KEY1_LONG_PRESSED;
}
}
else if((READ_KEY1_STATE == KEY_RELEASED) && (key1.status > 0))
{
if(key1.status == 1)
{
// 短按释放
key1.status = 0;
key1.debounce = 0;
return KEY1_SHORT_PRESSED;
}
if(key1.status == 2)
{
// 长按释放
key1.status = 0;
key1.debounce = 0;
}
}
if(READ_KEY2_STATE == KEY_PRESSED && (key2.status