RT_Thread操作系统实现多个按键的短按和长按检测
在RT-Thread操作系统中,实现多个按键的短按和长按操作,不占用线程和其他资源,使用软件定时器实现。
初始化按键的软件定时器
一个按键需要一个软件定时器
key_1_timer = rt_timer_create("key_1_timer", // 软件定时器名称
key_1_timer_IRQ, // 软件定时器超时函数
RT_NULL, // 超时函数参数
300, // 超时时间
RT_TIMER_FLAG_ONE_SHOT |
RT_TIMER_FLAG_SOFT_TIMER); // 软件定时器模式,一次模式
key_2_timer = rt_timer_create("key_2_timer", // 软件定时器名称
key_2_timer_IRQ, // 软件定时器超时函数
RT_NULL, // 超时函数参数
300, // 超时时间
RT_TIMER_FLAG_ONE_SHOT |
RT_TIMER_FLAG_SOFT_TIMER); // 软件定时器模式,一次模式
key_3_timer = rt_timer_create("key_3_timer", // 软件定时器名称
key_3_timer_IRQ, // 软件定时器超时函数
RT_NULL, // 超时函数参数
300, // 超时时间
RT_TIMER_FLAG_ONE_SHOT |
RT_TIMER_FLAG_SOFT_TIMER); // 软件定时器模式,一次模式
初始化按键
将按键的引脚初始化成沿边模式使能引脚的中断
void Key_panel_GPIO_Init(void)
{
key_1 = rt_pin_get("PB.2");
key_2 = rt_pin_get("PC.3");
key_3 = rt_pin_get("PD.0");
rt_pin_attach_irq(key_1, PIN_IRQ_MODE_RISING_FALLING, key_1_RISING_FALLING_IRQ, RT_NULL);
rt_pin_irq_enable(key_1, PIN_IRQ_ENABLE);
rt_pin_attach_irq(key_2, PIN_IRQ_MODE_RISING_FALLING, key_2_RISING_FALLING_IRQ, RT_NULL);
rt_pin_irq_enable(key_2, PIN_IRQ_ENABLE);
rt_pin_attach_irq(key_3, PIN_IRQ_MODE_RISING_FALLING, key_3_RISING_FALLING_IRQ, RT_NULL);
rt_pin_irq_enable(key_3, PIN_IRQ_ENABLE);
}
INIT_DEVICE_EXPORT(Key_panel_GPIO_Init);
按键的中断函数
中断函数中,按键按下后启动定时器,按键松开后,没有超时标志,则按键为短按,关闭软件定时器
void key_1_RISING_FALLING_IRQ(void *arge)
{
if(rt_pin_read(key_1) == 1)//松开
{
key_falg_t.key_1_down_falg = Key_released;
rt_timer_stop(key_1_timer);
if(key_falg_t.key_1_timeout_falg == Key_no_timeout)
{
key_falg_t.key_1_num = Key_Num_Short_press;
}
}
else if(rt_pin_read(key_1) == 0)//按下
{
key_falg_t.key_1_down_falg = Key_Down;
key_falg_t.key_1_timeout_falg = Key_no_timeout;
rt_timer_start(key_1_timer);
}
}
void key_2_RISING_FALLING_IRQ(void *arge)
{
if(rt_pin_read(key_2) == 1)//松开
{
key_falg_t.key_2_down_falg = Key_released;
rt_timer_stop(key_2_timer);
if(key_falg_t.key_2_timeout_falg == Key_no_timeout)
{
key_falg_t.key_2_num = Key_Num_Short_press;
}
}
else if(rt_pin_read(key_2) == 0)//按下
{
key_falg_t.key_2_down_falg = Key_Down;
key_falg_t.key_2_timeout_falg = Key_no_timeout;
rt_timer_start(key_2_timer);
}
}
void key_3_RISING_FALLING_IRQ(void *arge)
{
if(rt_pin_read(key_3) == 1)//松开
{
key_falg_t.key_3_down_falg = Key_released;
rt_timer_stop(key_3_timer);
if(key_falg_t.key_3_timeout_falg == Key_no_timeout)
{
key_falg_t.key_3_num = Key_Num_Short_press;
}
}
else if(rt_pin_read(key_3) == 0)//按下
{
key_falg_t.key_3_down_falg = Key_Down;
key_falg_t.key_3_timeout_falg = Key_no_timeout;
rt_timer_start(key_3_timer);
}
}
按键的超时函数
每个按键对应一个软件定时目的是为了防止按键同时按下,开启定时器后,定时结束,说明按键还没有松开,键值为长按
void key_1_timer_IRQ(void *parameter)
{
key_falg_t.key_1_timeout_falg = Key_timeout;
key_falg_t.key_1_num = Key_Num_Long_press;
key_falg_t.key_1_down_falg = Key_released;
}
void key_2_timer_IRQ(void *parameter)
{
key_falg_t.key_2_timeout_falg = Key_timeout;
key_falg_t.key_2_num = Key_Num_Long_press;
key_falg_t.key_1_down_falg = Key_released;
}
void key_3_timer_IRQ(void *parameter)
{
key_falg_t.key_3_timeout_falg = Key_timeout;
key_falg_t.key_3_num = Key_Num_Long_press;
key_falg_t.key_1_down_falg = Key_released;
}