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

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

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

按鍵消抖/開關(guān)量信號(hào)監(jiān)測(cè)實(shí)現(xiàn)方案

玩轉(zhuǎn)單片機(jī)與嵌入式 ? 來(lái)源:玩轉(zhuǎn)單片機(jī)與嵌入式 ? 2023-09-19 11:35 ? 次閱讀

關(guān)于按鍵消抖或者開關(guān)量信號(hào)監(jiān)測(cè),可以參考本公眾號(hào)的另外一篇原創(chuàng)文章:按鍵消抖常用的軟硬件方法。在該文章中介紹了兩種軟件延時(shí)的方式。但也都各有缺點(diǎn)。

一:舊方案

方案一:純軟件延時(shí)

sbit KEY = P1^3;
///按鍵讀取函數(shù)
uint8_t GetKey(void)
{
    if(KEY == 1)
    {
        DelayMs(20);        //延時(shí)消抖
        if(KEY == 1)
        {
            return 1;
        }
        else 
        {
            return 0;
        }
    }
    else 
    {
        return 0;
    }
}
致命缺點(diǎn):在延時(shí)的時(shí)候一直占用cpu的資源,如果在延時(shí)的時(shí)候,有其他外部中斷或者搶占事件,系統(tǒng)完全沒有響應(yīng)的

方案二:中斷消抖

此處不在貼出代碼:感興趣的同學(xué)可到文章中查看:按鍵消抖常用的軟硬件方法

致命缺點(diǎn):多占用中斷資源。操作復(fù)雜。在資源就是成本的產(chǎn)品中(多占用一個(gè)中斷可能會(huì)導(dǎo)致需要選擇價(jià)格更高的MCU),這種方案的缺點(diǎn)更加明顯。

推薦方案

本文推薦一種更高效、合適,已在產(chǎn)品中使用過(guò)的軟件設(shè)計(jì)方案。直接上代碼。

#include 


// 定義開關(guān)信號(hào)結(jié)構(gòu)體
typedef struct {
    bool lastState;       // 上次開關(guān)信號(hào)狀態(tài)
    bool currentState;    // 當(dāng)前開關(guān)信號(hào)狀態(tài)
    bool validState;      // 有效的開關(guān)信號(hào)狀態(tài)
    int debounceDelayCounter;  // 開關(guān)信號(hào)消抖計(jì)數(shù)器
} DebouncedSwitch;


// 初始化開關(guān)信號(hào)結(jié)構(gòu)體
void initializeSwitch(DebouncedSwitch* switchObj) {
    switchObj->lastState = false;
    switchObj->currentState = false;
    switchObj->validState = false;
    switchObj->debounceDelayCounter = 0;
}


// 模擬讀取開關(guān)信號(hào)狀態(tài)的函數(shù)
bool readSwitchState() {
    // 在這里替換為實(shí)際的開關(guān)信號(hào)讀取代碼
    // 返回開關(guān)信號(hào)的當(dāng)前狀態(tài)(true表示開,false表示關(guān))
    return false;
}


// 處理開關(guān)信號(hào)消抖的函數(shù)
void debounceSwitch(DebouncedSwitch* switchObj, int debounceTime) {
    // 讀取當(dāng)前開關(guān)信號(hào)狀態(tài)
    switchObj->currentState = readSwitchState();


    // 如果當(dāng)前狀態(tài)與上次狀態(tài)不同,重置計(jì)數(shù)器并更新上次狀態(tài)
    if (switchObj->currentState != switchObj->lastState) {
        switchObj->debounceDelayCounter = 0;
    } else {
        // 如果狀態(tài)相同,增加計(jì)數(shù)器值
        switchObj->debounceDelayCounter++;
    }


    // 如果計(jì)數(shù)器達(dá)到指定的消抖時(shí)間,表示開關(guān)信號(hào)狀態(tài)穩(wěn)定
    if (switchObj->debounceDelayCounter >= (debounceTime / 10)) {
        // 如果當(dāng)前狀態(tài)與 validState 不同,表示發(fā)生了有效的狀態(tài)變化
        if (switchObj->currentState != switchObj->validState) {
            switchObj->validState = switchObj->currentState;
        }
    }
    // 更新上次狀態(tài)
    switchObj->lastState = switchObj->currentState;
}


int main() {
    // 創(chuàng)建一個(gè)開關(guān)信號(hào)的DebouncedSwitch結(jié)構(gòu)體
    DebouncedSwitch switchObj;
    initializeSwitch(&switchObj);


    while (1) {
        debounceSwitch(&switchObj, 100); // 設(shè)置消抖時(shí)間為100毫秒
        if (switchObj.validState) {
            if (switchObj.validState) {
                // 執(zhí)行開關(guān)信號(hào)為開的操作
                printf("開關(guān)信號(hào)為開
");
            } else {
                // 執(zhí)行開關(guān)信號(hào)為關(guān)的操作
                printf("開關(guān)信號(hào)為關(guān)
");
            }
        }


        // 在這里可以添加其他需要執(zhí)行的代碼


        // 模擬延時(shí)或等待開關(guān)信號(hào)狀態(tài)變化
        // 這里使用usleep函數(shù)來(lái)模擬10毫秒的延時(shí)
        // 實(shí)際上,你需要根據(jù)你的硬件和操作系統(tǒng)來(lái)等待開關(guān)信號(hào)狀態(tài)變化
        usleep(10000); // 10毫秒
    }


    return 0;
}

1、函數(shù)詳解:

debounceSwitch函數(shù)該函數(shù)用于處理開關(guān)信號(hào)的消抖,以確保穩(wěn)定的開關(guān)狀態(tài)。 它接受一個(gè)指向 DebouncedSwitch 結(jié)構(gòu)體的指針,該結(jié)構(gòu)體包含了上次狀態(tài)、當(dāng)前狀態(tài)、有效狀態(tài)等信息,以及消抖時(shí)間的設(shè)置。

該函數(shù)的被調(diào)用周期為10ms(可以與產(chǎn)品程序中其他任務(wù)并行執(zhí)行)。

2、函數(shù)的工作流程如下:

1)讀取當(dāng)前開關(guān)信號(hào)狀態(tài)。

2)如果當(dāng)前狀態(tài)與上次狀態(tài)不同,重置計(jì)數(shù)器并更新上次狀態(tài)。

3)如果當(dāng)前狀態(tài)與上次狀態(tài)相同,增加計(jì)數(shù)器值。

4)如果計(jì)數(shù)器達(dá)到指定的消抖時(shí)間,表示開關(guān)信號(hào)狀態(tài)穩(wěn)定。

5)如果當(dāng)前狀態(tài)與 validState 不同,表示發(fā)生了有效的狀態(tài)變化,更新有效狀態(tài)。

6)更新上次狀態(tài)以便下一次比較

3、優(yōu)點(diǎn)介紹:

1)擴(kuò)展性:

debounceSwitch該函數(shù)使用結(jié)構(gòu)體指針的形式,提供了開關(guān)量檢測(cè)的框架,需要多個(gè)開關(guān)量/按鍵檢測(cè)時(shí),實(shí)例化對(duì)應(yīng)的按鍵變量即可。例如:main函數(shù)的示例中實(shí)例化了switchObj,多有多個(gè)按鍵可以多定義不同的switchObj即可。如下:代碼所展示:
DebouncedSwitch switchObj_key1;
DebouncedSwitch switchObj_key2;


//其他代碼


debounceSwitch(&switchObj_key1, 100);
debounceSwitch(&switchObj_key2,50);

2、高度可定制:

 debounceSwitch函數(shù)中的消抖時(shí)間是作為參數(shù)傳遞的,這使得消抖時(shí)間可以根據(jù)不同的開關(guān)信號(hào)或應(yīng)用場(chǎng)景進(jìn)行定制。這種可定制性允許您在不同情況下使用不同的消抖時(shí)間,以滿足特定需求。

3、適用于實(shí)時(shí)系統(tǒng):

相對(duì)于純軟件延時(shí)消抖,debounceSwitch函數(shù)是更可靠的,因?yàn)樗灰蕾囉谲浖难訒r(shí),而是基于實(shí)際的狀態(tài)變化來(lái)判斷開關(guān)信號(hào)的穩(wěn)定性。這使得它適用于實(shí)時(shí)系統(tǒng)和對(duì)時(shí)間精度要求較高的應(yīng)用。

總結(jié)

當(dāng)然,作為一個(gè)產(chǎn)品中使用的函數(shù)還有很多可優(yōu)化的空間,比如:函數(shù)內(nèi)判斷指針不為空。進(jìn)行參數(shù)的有效性檢查等等。

審核編輯:湯梓紅

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

    關(guān)注

    2

    文章

    169

    瀏覽量

    14952
  • 源碼
    +關(guān)注

    關(guān)注

    8

    文章

    626

    瀏覽量

    28965
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4235

    瀏覽量

    61965
  • 按鍵消抖
    +關(guān)注

    關(guān)注

    2

    文章

    24

    瀏覽量

    10422

原文標(biāo)題:共享一個(gè)產(chǎn)品中使用的按鍵消抖/開關(guān)量監(jiān)測(cè)函數(shù)(附源碼,可移植)

文章出處:【微信號(hào):玩轉(zhuǎn)單片機(jī)與嵌入式,微信公眾號(hào):玩轉(zhuǎn)單片機(jī)與嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    按鍵的硬件電路原理詳解

    按鍵通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)
    的頭像 發(fā)表于 02-02 09:42 ?8936次閱讀
    <b class='flag-5'>按鍵</b>的硬件<b class='flag-5'>消</b><b class='flag-5'>抖</b>電路原理詳解

    按鍵電路的實(shí)現(xiàn)方式

    按鍵通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)
    的頭像 發(fā)表于 08-29 11:25 ?4450次閱讀

    按鍵

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

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

    ,利用硬件來(lái)減輕軟件工作,通過(guò)硬件加速軟件處理,即可做到軟件并行化,因而在按鍵
    發(fā)表于 08-02 10:38

    按鍵及原理是什么

    淺談:在設(shè)計(jì)單片機(jī)按鍵輸入的時(shí)候,進(jìn)行按鍵是防止按鍵輸入被CPU誤讀多次的必要手段。一、按鍵
    發(fā)表于 07-21 06:02

    MCU按鍵問(wèn)題

    按鍵問(wèn)題機(jī)械按鍵是必須的,1、延時(shí)
    發(fā)表于 11-04 06:37

    有什么方法去實(shí)現(xiàn)按鍵

    怎樣用軟件即程序來(lái)實(shí)現(xiàn)按鍵呢?有什么方法去實(shí)現(xiàn)按鍵
    發(fā)表于 12-15 07:25

    介紹獨(dú)立按鍵方法

    目錄按鍵介紹按鍵方法按鍵檢測(cè)原理C51例程歡迎加QQ及郵件交流按鍵介紹
    發(fā)表于 01-14 07:49

    VHDL—按鍵

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

    vhdl按鍵程序(七種方式實(shí)現(xiàn)按鍵

    按鍵通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)
    發(fā)表于 01-29 16:04 ?5.6w次閱讀
    vhdl<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>程序(七種方式<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>)

    基于尖峰脈沖的按鍵

    按鍵通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)
    的頭像 發(fā)表于 11-20 07:09 ?2943次閱讀

    為什么要進(jìn)行按鍵

    按鍵通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)
    的頭像 發(fā)表于 04-19 14:55 ?1w次閱讀

    FPGA內(nèi)實(shí)現(xiàn)按鍵的方法

    通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)按鍵開關(guān)在閉合時(shí)不會(huì)馬上穩(wěn)定地接通,在斷開時(shí)也不會(huì)一下
    的頭像 發(fā)表于 09-05 10:43 ?1089次閱讀
    FPGA內(nèi)<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的方法

    為什么要進(jìn)行按鍵?按鍵抖動(dòng)的原理 按鍵的方法

    按鍵通常的按鍵所用開關(guān)為機(jī)械彈性開關(guān),當(dāng)機(jī)械觸點(diǎn)斷開、閉合時(shí),由于機(jī)械觸點(diǎn)的彈性作用,一個(gè)
    的頭像 發(fā)表于 02-17 17:07 ?1.4w次閱讀
    為什么要進(jìn)行<b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>?<b class='flag-5'>按鍵</b>抖動(dòng)的原理 <b class='flag-5'>按鍵</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的方法

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

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