Skip to content

按键设备

对于按键的使用,同操作 GPIO 。将按键连接的 GPIO 设置为输入模式,通过检测输入引脚的电平变化,来判断按键是否按下。

按键消抖

通常来说,在物理按键闭合或者断开的一瞬间,所连接 GPIO 口上的电平会有多次跳变。这多次跳变会影响我们正常的判断按键是否按下。

对于按下或者抬起按键照成的跳变,通常在 20ms 左右,20ms 后电平值就会稳定下来。所以只要我们在第一次检测到电平变化,再延时 20ms 左右读取电平的值,就能准确的获取到当前按键 GPIO 的电平了。

button_click

按键原理图

最新的 IOTE 开发板上有两个按键,分别连接到 GPIO_16 和 GPIO_17

button_sch

GPIO_16, GPIO_17 首先外部下拉接地,再进过按键上拉接 3.3v 电源。所以在按键还未按下时,GPIO 读取到的是低电平,当按键按下后,GPIO 读取到的是高电平。

button_board

按键示例

在 IOTE 开发板上,我们通过按下按键,反转 led 来说明按键的使用中如何过滤按键抖动

示例代码

将按键所连接引脚设置为外部中断模式,一旦检测到外部电平变化,中断处理程序设置按键按下全局变量,主线程接收按键按下全局变量后,延时消抖,再次读取按键值。

#include <rtthread.h>
#ifdef _BUTTON_APP_
#include <rtdevice.h>
#include <rthw.h>
#include "uc_button_app.h"

#define LED_PIN_NUM             2
#define BUTTON_PIN_NUM          16

/* 按键触发全局变量 */
static volatile uint8_t key_pressed;

/* 按键中断处理函数 */
static void key_irq_handler(void *args)
{
    rt_base_t level;
    level = rt_hw_interrupt_disable();
    if (key_pressed == 0)
    {
        /* 设置按键触发 */
        key_pressed = 1;
    }
    rt_hw_interrupt_enable(level);
}

int button_app_init(void)
{
    rt_pin_mode(LED_PIN_NUM, PIN_MODE_OUTPUT);
    rt_pin_write(LED_PIN_NUM, PIN_LOW);

    /* 设置按键中断上升沿触发 */
    rt_pin_mode(BUTTON_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(BUTTON_PIN_NUM, PIN_IRQ_MODE_RISING, key_irq_handler, RT_NULL);

    return RT_EOK;
}

void button_app_sample(void)
{
    rt_err_t ret = RT_EOK;

    rt_kprintf("button test demo.\r\n");

    ret = button_app_init();
    if(ret != RT_EOK)
    {
        rt_kprintf("button test error.\r\n");
    }

    rt_pin_write(LED_PIN_NUM, PIN_LOW);

    rt_pin_irq_enable(BUTTON_PIN_NUM, PIN_IRQ_ENABLE);

    while (1)
    {
        if (key_pressed == 1)
        {
            /* 消抖延时 */
            rt_thread_mdelay(20);

            /* 复位触发信号 */
            key_pressed = 0;

            /* 再次判断 */
            if (rt_pin_read(BUTTON_PIN_NUM) == 0)
            {
                /* 未触发,重新循环 */
                continue;
            }

            rt_kprintf("key pressed, change led\r\n");

            if (rt_pin_read(LED_PIN_NUM) == 1)
            {
                rt_pin_write(LED_PIN_NUM, 0);
            }
            else
            {
                rt_pin_write(LED_PIN_NUM, 1);
            }
        }
        rt_thread_delay(50);
    }
}

#endif // _BUTTON_APP_
Back to top