0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

立創(chuàng)梁山派-21年電賽F題-智能送藥小車-按鍵檢測的消抖和實(shí)現(xiàn)

jf_31863339 ? 來源:jf_31863339 ? 作者:jf_31863339 ? 2023-08-04 10:09 ? 次閱讀

按鍵檢測的消抖和實(shí)現(xiàn)

在送藥小車中,預(yù)留了三個按鍵,藥品裝載檢測是通過一個輕觸開關(guān)來實(shí)現(xiàn)的,也可以把他理解成一個按鍵。

按鍵的實(shí)際電路如下:

wKgaomTMXcSAOlqLAABUymAAUXE622.jpg

我們通常用的按鍵內(nèi)部都是機(jī)械彈性開關(guān),當(dāng)它按下彈起的時候,機(jī)械觸點(diǎn)會因?yàn)閺椥宰饔枚陂]合和斷開的瞬間伴隨著一連串的抖動。這種抖動會導(dǎo)致輸入信號在高低電位之間彈跳,產(chǎn)生不正確的輸入。 這里面電阻的作用是限流(害怕初學(xué)者不小心給設(shè)置成推挽輸出了),在這里要注意的是要在芯片內(nèi)部設(shè)置一個下拉(電路圖上是沒有加下拉電阻得到)。電容作用是硬件去抖,不過軟件上還是需要軟件消抖,硬件去抖只能改善不能消除,所以在有一些批量電路中,這個電容都是可以省去的,畢竟還是省不了軟件消抖的。

輕觸開關(guān)的實(shí)際電路如下:

wKgZomTMXcSAPQ6rAABSAmOJG5Y773.jpg

在這里,我又要安利一波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;
        }
    }
}


審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 檢測
    +關(guān)注

    關(guān)注

    5

    文章

    4496

    瀏覽量

    91535
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1293

    瀏覽量

    40218
收藏 人收藏

    評論

    相關(guān)推薦

    創(chuàng)·梁山開發(fā)板-21F-送藥小車-K210功能實(shí)現(xiàn)代碼講解

    關(guān)鍵的注釋都添加了,可以幫助理解代碼,這段代碼同時實(shí)現(xiàn)了尋紅線和數(shù)字識別,但是還做不到同時運(yùn)行,在尋紅線的時候沒法數(shù)字識別,這兩個狀態(tài)之間的切換可以通過長按K210上的用戶按鍵或者由創(chuàng)
    的頭像 發(fā)表于 08-01 09:49 ?1166次閱讀

    開發(fā)板-21F-送藥小車-小車尋紅線環(huán)的調(diào)試與實(shí)現(xiàn)

    PID控制來說,測量值是紅線相較屏幕中線的偏移,目標(biāo)值是想讓紅線偏移為0,輸出值是電機(jī)的速度。 根據(jù)14_創(chuàng)梁山與K210串口通信協(xié)議框架搭建.md文檔我們的
    的頭像 發(fā)表于 08-03 10:10 ?1375次閱讀

    創(chuàng)·梁山開發(fā)板-21F-送藥小車實(shí)現(xiàn)思路

    基本要求 1. 根據(jù)走廊上的標(biāo)識信息自動識別,尋徑將藥品送到指定病房,投影要在門口區(qū)域內(nèi), 2. 到了指定病房后,點(diǎn)亮紅色指示燈,等待卸載藥品。 3. 人工卸掉藥品后,小車自動熄滅紅色指示燈,開始返回。 4. 自動返回藥房,點(diǎn)亮綠色指示燈。
    的頭像 發(fā)表于 08-08 09:44 ?911次閱讀
    <b class='flag-5'>立</b><b class='flag-5'>創(chuàng)</b>·<b class='flag-5'>梁山</b><b class='flag-5'>派</b>開發(fā)板-<b class='flag-5'>21</b><b class='flag-5'>年</b><b class='flag-5'>電</b><b class='flag-5'>賽</b><b class='flag-5'>F</b><b class='flag-5'>題</b>-<b class='flag-5'>送藥</b><b class='flag-5'>小車</b><b class='flag-5'>實(shí)現(xiàn)</b>思路

    按鍵

    請問大家的按鍵是用什么方法解決的,如普通的按鍵如何。
    發(fā)表于 09-26 22:17

    技術(shù)分享:明德?lián)P按鍵的原理和基于fpga的設(shè)計

    高頻抖動略去。需要注意的是,軟件需要占據(jù)一定的系統(tǒng)資源。盡管硬件和軟件
    發(fā)表于 08-02 10:38

    怎樣去設(shè)計一個智能送藥小車

    2021F智能送藥小車原文鏈接:openmv巡
    發(fā)表于 01-07 08:19

    MSP430F5529按鍵實(shí)現(xiàn)

    MSP430F5529 按鍵實(shí)現(xiàn)
    發(fā)表于 02-15 07:21

    創(chuàng)梁山-21F-智能送藥小車-按鍵檢測實(shí)現(xiàn)

    按鍵檢測實(shí)現(xiàn)送藥小車中,預(yù)留了三個
    發(fā)表于 08-04 09:48

    VHDL—按鍵

    達(dá)到去抖動的目的。本例中用狀態(tài)機(jī)實(shí)現(xiàn)電路:端口描述:clk 輸入檢測時鐘;reset 復(fù)位信號;din 原始按鍵信號輸入; dout
    發(fā)表于 11-11 17:17 ?2次下載

    【庫函數(shù)】MSP430F5529 按鍵

    MSP430F5529 按鍵實(shí)現(xiàn)
    發(fā)表于 12-16 16:55 ?17次下載
    【庫函數(shù)】MSP430<b class='flag-5'>F</b>5529 <b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>

    梁山開發(fā)板-21F-送藥小車-分析

    全國產(chǎn)開源開發(fā)板,基于GD32F4系列,21F-送藥
    的頭像 發(fā)表于 07-31 10:13 ?1260次閱讀
    <b class='flag-5'>梁山</b><b class='flag-5'>派</b>開發(fā)板-<b class='flag-5'>21</b><b class='flag-5'>年</b><b class='flag-5'>電</b><b class='flag-5'>賽</b><b class='flag-5'>F</b><b class='flag-5'>題</b>-<b class='flag-5'>送藥</b><b class='flag-5'>小車</b>-<b class='flag-5'>賽</b><b class='flag-5'>題</b>分析

    創(chuàng)梁山開發(fā)板-21F-送藥小車-小車角度環(huán)的調(diào)試與實(shí)現(xiàn)

    來達(dá)到目標(biāo)值。 第二種是在實(shí)現(xiàn)小車輪子位置環(huán)的基礎(chǔ)上,控制兩邊輪子同時向不同的方向旋轉(zhuǎn)一定的圈數(shù)(編碼器脈沖),在小車輪子不打滑的情況下轉(zhuǎn)過的角度就是一個確定的值,在送藥
    的頭像 發(fā)表于 07-27 10:18 ?964次閱讀
    <b class='flag-5'>立</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>梁山</b><b class='flag-5'>派</b>開發(fā)板-<b class='flag-5'>21</b><b class='flag-5'>年</b><b class='flag-5'>電</b><b class='flag-5'>賽</b><b class='flag-5'>F</b><b class='flag-5'>題</b>-<b class='flag-5'>送藥</b><b class='flag-5'>小車</b>-<b class='flag-5'>小車</b>角度環(huán)的調(diào)試與<b class='flag-5'>實(shí)現(xiàn)</b>

    創(chuàng)·梁山開發(fā)板-21F-送藥小車-與K210串口通信協(xié)議框架搭建

    在K210可以識別到色塊和識別數(shù)字后,就需要把這些信息傳遞給創(chuàng)梁山派了。而立創(chuàng)梁山也需要控制
    的頭像 發(fā)表于 08-02 10:57 ?763次閱讀

    創(chuàng)·梁山開發(fā)板-21F-送藥小車數(shù)據(jù)的發(fā)布與訂閱

    推薦或不建議使用全局變量來傳遞信息的原因主要有以下幾點(diǎn): 1. 競爭條件:在多任務(wù)環(huán)境下,全局變量會面臨競爭條件的問題。當(dāng)多個任務(wù)同時讀寫同一個全局變量時,會導(dǎo)致數(shù)據(jù)的不一致性和錯誤的結(jié)果。這是因?yàn)槿蝿?wù)的執(zhí)行是并發(fā)的,無法控制它們的執(zhí)行順序。 2. 數(shù)據(jù)共享和保護(hù):全局變量被所有任務(wù)共享,這意味著多個任務(wù)可以同時訪問和修改該變量。如果沒有正確的數(shù)據(jù)保護(hù)機(jī)制,可能會導(dǎo)致數(shù)據(jù)損壞或沖突。 3. 可維護(hù)性和調(diào)試?yán)щy:使用全局變量傳遞信息可能導(dǎo)致代碼的可維護(hù)性和調(diào)試的困難。由于全局變量可以被任何任務(wù)修改,追蹤問題的根源和調(diào)試錯誤可能會變得更加困難。
    的頭像 發(fā)表于 08-07 09:55 ?492次閱讀
    <b class='flag-5'>立</b><b class='flag-5'>創(chuàng)</b>·<b class='flag-5'>梁山</b><b class='flag-5'>派</b>開發(fā)板-<b class='flag-5'>21</b><b class='flag-5'>年</b><b class='flag-5'>電</b><b class='flag-5'>賽</b><b class='flag-5'>F</b><b class='flag-5'>題</b>-<b class='flag-5'>送藥</b><b class='flag-5'>小車</b>數(shù)據(jù)的發(fā)布與訂閱

    如何在FPGA中實(shí)現(xiàn)按鍵

    在FPGA(現(xiàn)場可編程門陣列)中實(shí)現(xiàn)按鍵是一個重要的設(shè)計環(huán)節(jié),特別是在處理用戶輸入時,由于物理按鍵的機(jī)械特性和電氣特性,
    的頭像 發(fā)表于 08-19 18:15 ?2037次閱讀