RT_Thread操作系统实现多个按键的短按和长按检测

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;
}
  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以帮你写一个简单的按键控制 LED 开关的程序,使用 RT-Thread 操作系统。以下是程序代码: ```c #include <rtthread.h> #define LED_PIN GET_PIN(B, 5) #define LED_ON 0 /* LED 亮 */ #define LED_OFF 1 /* LED 灭 */ #define KEY_PIN GET_PIN(D, 2) #define KEY_DOWN 0 /* 按键按下 */ #define KEY_UP 1 /* 按键弹起 */ static rt_uint8_t led_state = LED_OFF; /* LED 初始状态为灭 */ static void key_thread_entry(void *param) { rt_pin_mode(KEY_PIN, PIN_MODE_INPUT_PULLUP); /* 配置按键引脚为输入模式,并开启上拉电阻 */ while (1) { if (rt_pin_read(KEY_PIN) == KEY_DOWN) /* 检测按键按下 */ { led_state = !led_state; /* 反转 LED 状态 */ rt_pin_write(LED_PIN, led_state); /* 更新 LED 状态 */ rt_thread_mdelay(100); /* 延时 100 毫秒,防止抖动 */ } else { rt_thread_mdelay(10); /* 延时 10 毫秒,降低 CPU 占用率 */ } } } static void led_thread_entry(void *param) { rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT); /* 配置 LED 引脚为输出模式 */ while (1) { rt_pin_write(LED_PIN, led_state); /* 更新 LED 状态 */ rt_thread_mdelay(10); /* 延时 10 毫秒,降低 CPU 占用率 */ } } int key_led_thread_init(void) { rt_thread_t tid_key, tid_led; tid_key = rt_thread_create("key", key_thread_entry, RT_NULL, 512, 10, 10); tid_led = rt_thread_create("led", led_thread_entry, RT_NULL, 512, 10, 10); if ((tid_key != RT_NULL) && (tid_led != RT_NULL)) { rt_thread_startup(tid_key); rt_thread_startup(tid_led); return 0; } else { return -1; } } MSH_CMD_EXPORT(key_led_thread_init, start key led thread); ``` 上述代码中,我们通过调用 `rt_pin_mode` 函数将 LED 和按键对应的引脚配置为输出和输入模式,并通过 `rt_pin_read` 和 `rt_pin_write` 函数来读取和更新引脚电平,实现按键控制 LED 的开关。我们还创建了两个线程 `key_thread` 和 `led_thread`,分别用于检测按键状态和更新 LED 状态。 你可以将上述代码保存为 `key_led.c` 文件,并在 RT-Thread 的配置文件中添加对应的编译选项和驱动支持,然后编译烧录到目标板上运行即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HTIAN1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值