按键设备
对于按键的使用,同操作 GPIO 。将按键连接的 GPIO 设置为输入模式,通过检测输入引脚的电平变化,来判断按键是否按下。
按键消抖
通常来说,在物理按键闭合或者断开的一瞬间,所连接 GPIO 口上的电平会有多次跳变。这多次跳变会影响我们正常的判断按键是否按下。
对于按下或者抬起按键照成的跳变,通常在 20ms 左右,20ms 后电平值就会稳定下来。所以只要我们在第一次检测到电平变化,再延时 20ms 左右读取电平的值,就能准确的获取到当前按键 GPIO 的电平了。
按键原理图
最新的 IOTE 开发板上有两个按键,分别连接到 GPIO_16 和 GPIO_17
GPIO_16, GPIO_17 首先外部下拉接地,再进过按键上拉接 3.3v 电源。所以在按键还未按下时,GPIO 读取到的是低电平,当按键按下后,GPIO 读取到的是高电平。
按键示例
在 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_