电子说
按键检测的消抖和实现
在送药小车中,预留了三个按键,药品装载检测是通过一个轻触开关来实现的,也可以把他理解成一个按键。
按键的实际电路如下:
我们通常用的按键内部都是机械弹性开关,当它按下弹起的时候,机械触点会因为弹性作用而在闭合和断开的瞬间伴随着一连串的抖动。这种抖动会导致输入信号在高低电位之间弹跳,产生不正确的输入。 这里面电阻的作用是限流(害怕初学者不小心给设置成推挽输出了),在这里要注意的是要在芯片内部设置一个下拉(电路图上是没有加下拉电阻得到)。电容作用是硬件去抖,不过软件上还是需要软件消抖,硬件去抖只能改善不能消除,所以在有一些批量电路中,这个电容都是可以省去的,毕竟还是省不了软件消抖的。
轻触开关的实际电路如下:
在这里,我又要安利一波RT-Thread的软件包的,可以在RT-Thread软件包里面,搜索button,可以看到是有很多按键的软件包,这里就选择MultiButton了。用ENV工具把他添加到工程里面就可以了。参考他自带的example建立线程就可以轻松实现按键检测的,按下,弹起,单击,双击,长按等事件了:
#include < rtthread.h > #include < rtdevice.h > #include #include "multi_button.h" #include "bsp_beep.h" static struct button btn1; static struct button btn2; static struct button btn3; #define KEY1_PIN GET_PIN(G, 11) #define KEY2_PIN GET_PIN(G, 13) #define KEY3_PIN GET_PIN(B, 3) static uint8_t button1_read_pin(void) { return rt_pin_read(KEY1_PIN); } static uint8_t button2_read_pin(void) { return rt_pin_read(KEY2_PIN); } static uint8_t button3_read_pin(void) { return rt_pin_read(KEY3_PIN); } void button1_callback(void *btn) { uint32_t btn_event_val; btn_event_val = get_button_event((struct button *)btn); switch (btn_event_val) { case PRESS_DOWN: rt_kprintf("button1 press downn"); break; case PRESS_UP: rt_kprintf("button1 press upn"); break; case PRESS_REPEAT: rt_kprintf("button1 press repeatn"); break; case SINGLE_CLICK: beep(20); rt_kprintf("button1 single clickn"); break; case DOUBLE_CLICK: rt_kprintf("button1 double clickn"); break; case LONG_PRESS_START: rt_kprintf("button1 long press startn"); break; case LONG_PRESS_HOLD: rt_kprintf("button1 long press holdn"); break; } } void button2_callback(void *btn) { uint32_t btn_event_val; btn_event_val = get_button_event((struct button *)btn); switch (btn_event_val) { case PRESS_DOWN: rt_kprintf("button2 press downn"); break; case PRESS_UP: rt_kprintf("button2 press upn"); break; case PRESS_REPEAT: rt_kprintf("button2 press repeatn"); break; case SINGLE_CLICK: beep(20); rt_kprintf("button2 single clickn"); break; case DOUBLE_CLICK: rt_kprintf("button2 double clickn"); break; case LONG_PRESS_START: rt_kprintf("button2 long press startn"); break; case LONG_PRESS_HOLD: rt_kprintf("button2 long press holdn"); break; } } void button3_callback(void *btn) { uint32_t btn_event_val; btn_event_val = get_button_event((struct button *)btn); switch (btn_event_val) { case PRESS_DOWN: rt_kprintf("button3 press downn"); break; case PRESS_UP: rt_kprintf("button3 press upn"); break; case PRESS_REPEAT: rt_kprintf("button3 press repeatn"); break; case SINGLE_CLICK: beep(20); rt_kprintf("button3 single clickn"); break; case DOUBLE_CLICK: rt_kprintf("button3 double clickn"); break; case LONG_PRESS_START: rt_kprintf("button3 long press startn"); break; case LONG_PRESS_HOLD: rt_kprintf("button3 long press holdn"); break; } } void btn_thread_entry(void *p) { while (1) { /* 5ms */ rt_thread_delay(RT_TICK_PER_SECOND / 200); button_ticks(); } } int multi_button_test(void) { rt_thread_t thread = RT_NULL; /* Create background ticks thread */ thread = rt_thread_create("btn", btn_thread_entry, RT_NULL, 2048, 20, 10); if (thread == RT_NULL) { return RT_ERROR; } rt_thread_startup(thread); /* low level drive */ rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */ button_init(&btn1, button1_read_pin, PIN_HIGH); button_attach(&btn1, PRESS_DOWN, button1_callback); button_attach(&btn1, PRESS_UP, button1_callback); button_attach(&btn1, PRESS_REPEAT, button1_callback); button_attach(&btn1, SINGLE_CLICK, button1_callback); button_attach(&btn1, DOUBLE_CLICK, button1_callback); button_attach(&btn1, LONG_PRESS_START, button1_callback); button_attach(&btn1, LONG_PRESS_HOLD, button1_callback); button_start(&btn1); rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */ button_init(&btn2, button2_read_pin, PIN_HIGH); button_attach(&btn2, PRESS_DOWN, button2_callback); button_attach(&btn2, PRESS_UP, button2_callback); button_attach(&btn2, PRESS_REPEAT, button2_callback); button_attach(&btn2, SINGLE_CLICK, button2_callback); button_attach(&btn2, DOUBLE_CLICK, button2_callback); button_attach(&btn2, LONG_PRESS_START, button2_callback); button_attach(&btn2, LONG_PRESS_HOLD, button2_callback); button_start(&btn2); rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLDOWN); /* set KEY pin mode to input */ button_init(&btn3, button3_read_pin, PIN_HIGH); button_attach(&btn3, PRESS_DOWN, button3_callback); button_attach(&btn3, PRESS_UP, button3_callback); button_attach(&btn3, PRESS_REPEAT, button3_callback); button_attach(&btn3, SINGLE_CLICK, button3_callback); button_attach(&btn3, DOUBLE_CLICK, button3_callback); button_attach(&btn3, LONG_PRESS_START, button3_callback); button_attach(&btn3, LONG_PRESS_HOLD, button3_callback); button_start(&btn3); return RT_EOK; } INIT_APP_EXPORT(multi_button_test);
不想搞这么复杂,就只是单独想检测一下药物有没有放好的话也可以用最简单的延时来消除这个按键按下的抖动。像下面这个一样:
static void button_scan(void *arg) { while (1) { rt_thread_mdelay(50); if (button_key0_read() == 1) { rt_thread_mdelay(50); if (button_key0_read() == 1) { medicine_state = 1; } } else { medicine_state = 0; } } } 审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !