按鍵檢測的消抖和實現
在送藥小車中,預留了三個按鍵,藥品裝載檢測是通過一個輕觸開關來實現的,也可以把他理解成一個按鍵。
按鍵的實際電路如下:

我們通常用的按鍵內部都是機械彈性開關,當它按下彈起的時候,機械觸點會因為彈性作用而在閉合和斷開的瞬間伴隨著一連串的抖動。這種抖動會導致輸入信號在高低電位之間彈跳,產生不正確的輸入。 這里面電阻的作用是限流(害怕初學者不小心給設置成推挽輸出了),在這里要注意的是要在芯片內部設置一個下拉(電路圖上是沒有加下拉電阻得到)。電容作用是硬件去抖,不過軟件上還是需要軟件消抖,硬件去抖只能改善不能消除,所以在有一些批量電路中,這個電容都是可以省去的,畢竟還是省不了軟件消抖的。
輕觸開關的實際電路如下:

在這里,我又要安利一波RT-Thread的軟件包的,可以在RT-Thread軟件包里面,搜索button,可以看到是有很多按鍵的軟件包,這里就選擇MultiButton了。用ENV工具把他添加到工程里面就可以了。參考他自帶的example建立線程就可以輕松實現按鍵檢測的,按下,彈起,單擊,雙擊,長按等事件了:
#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);
不想搞這么復雜,就只是單獨想檢測一下藥物有沒有放好的話也可以用最簡單的延時來消除這個按鍵按下的抖動。像下面這個一樣:
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; } } } 審核編輯 黃宇
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
檢測
+關注
關注
5文章
4859瀏覽量
94140 -
RT-Thread
+關注
關注
32文章
1613瀏覽量
44868
發布評論請先 登錄
相關推薦
熱點推薦
立創·梁山派開發板-21年電賽F題-送藥小車-K210功能實現代碼講解
關鍵的注釋都添加了,可以幫助理解代碼,這段代碼同時實現了尋紅線和數字識別,但是還做不到同時運行,在尋紅線的時候沒法數字識別,這兩個狀態之間的切換可以通過長按K210上的用戶按鍵或者由立創
開發板-21年電賽F題-送藥小車-小車尋紅線環的調試與實現
PID控制來說,測量值是紅線相較屏幕中線的偏移,目標值是想讓紅線偏移為0,輸出值是電機的速度。
根據14_立創梁山派與K210串口通信協議框架搭建.md文檔我們的
立創·梁山派開發板-21年電賽F題-送藥小車實現思路
基本要求
1. 根據走廊上的標識信息自動識別,尋徑將藥品送到指定病房,投影要在門口區域內,
2. 到了指定病房后,點亮紅色指示燈,等待卸載藥品。
3. 人工卸掉藥品后,小車自動熄滅紅色指示燈,開始返回。
4. 自動返回藥房,點亮綠色指示燈。
VHDL—按鍵消抖
達到去抖動的目的。本例中用狀態機實現了消抖電路:端口描述:clk 輸入檢測時鐘;reset 復位信號;din 原始按鍵信號輸入; dout
發表于 11-11 17:17
?2次下載
立創梁山派開發板-21年電賽F題-送藥小車-小車角度環的調試與實現
來達到目標值。
第二種是在實現小車輪子位置環的基礎上,控制兩邊輪子同時向不同的方向旋轉一定的圈數(編碼器脈沖),在小車輪子不打滑的情況下轉過的角度就是一個確定的值,在送藥
立創·梁山派開發板-21年電賽F題-送藥小車-與K210串口通信協議框架搭建
在K210可以識別到色塊和識別數字后,就需要把這些信息傳遞給立創梁山派了。而立創梁山派也需要控制
立創·梁山派開發板-21年電賽F題-送藥小車數據的發布與訂閱
推薦或不建議使用全局變量來傳遞信息的原因主要有以下幾點:
1. 競爭條件:在多任務環境下,全局變量會面臨競爭條件的問題。當多個任務同時讀寫同一個全局變量時,會導致數據的不一致性和錯誤的結果。這是因為任務的執行是并發的,無法控制它們的執行順序。
2. 數據共享和保護:全局變量被所有任務共享,這意味著多個任務可以同時訪問和修改該變量。如果沒有正確的數據保護機制,可能會導致數據損壞或沖突。
3. 可維護性和調試困難:使用全局變量傳遞信息可能導致代碼的可維護性和調試的困難。由于全局變量可以被任何任務修改,追蹤問題的根源和調試錯誤可能會變得更加困難。
如何在FPGA中實現按鍵消抖
在FPGA(現場可編程門陣列)中實現按鍵消抖是一個重要的設計環節,特別是在處理用戶輸入時,由于物理按鍵的機械特性和電氣特性,
立創梁山派-21年電賽F題-智能送藥小車-按鍵檢測的消抖和實現
評論