按鍵檢測的消抖和實(shí)現(xiàn)
在送藥小車中,預(yù)留了三個按鍵,藥品裝載檢測是通過一個輕觸開關(guān)來實(shí)現(xiàn)的,也可以把他理解成一個按鍵。
按鍵的實(shí)際電路如下:
我們通常用的按鍵內(nèi)部都是機(jī)械彈性開關(guān),當(dāng)它按下彈起的時候,機(jī)械觸點(diǎn)會因?yàn)閺椥宰饔枚陂]合和斷開的瞬間伴隨著一連串的抖動。這種抖動會導(dǎo)致輸入信號在高低電位之間彈跳,產(chǎn)生不正確的輸入。 這里面電阻的作用是限流(害怕初學(xué)者不小心給設(shè)置成推挽輸出了),在這里要注意的是要在芯片內(nèi)部設(shè)置一個下拉(電路圖上是沒有加下拉電阻得到)。電容作用是硬件去抖,不過軟件上還是需要軟件消抖,硬件去抖只能改善不能消除,所以在有一些批量電路中,這個電容都是可以省去的,畢竟還是省不了軟件消抖的。
輕觸開關(guān)的實(shí)際電路如下:
在這里,我又要安利一波RT-Thread的軟件包的,可以在RT-Thread軟件包里面,搜索button,可以看到是有很多按鍵的軟件包,這里就選擇MultiButton了。用ENV工具把他添加到工程里面就可以了。參考他自帶的example建立線程就可以輕松實(shí)現(xiàn)按鍵檢測的,按下,彈起,單擊,雙擊,長按等事件了:
#include #include #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);
不想搞這么復(fù)雜,就只是單獨(dú)想檢測一下藥物有沒有放好的話也可以用最簡單的延時來消除這個按鍵按下的抖動。像下面這個一樣:
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; } } } 審核編輯 黃宇
-
檢測
+關(guān)注
關(guān)注
5文章
4496瀏覽量
91535 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1293瀏覽量
40218
發(fā)布評論請先 登錄
相關(guān)推薦
評論