新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 一個簡單的按鍵去抖延時程序

        一個簡單的按鍵去抖延時程序

        作者: 時間:2016-11-30 來源:網絡 收藏
        按鍵去抖,一般采用普通延時,如

        if((GPIOC->IDR & 0x01)== 0)
        {
        delay_ms(20);
        if(GPIOC->IDR & 0x01)== 0

        //進行按鍵處理函數

        }

        本文引用地址:http://www.104case.com/article/201611/324051.htm

        這個程序,需要有一個普通的延時程序,來檢測去抖動,這個延時一般采用for循環和while循環。這樣的話,就有一個問題,在延時的這20ms中,cpu一直在判斷時間有沒有到。如果不是中斷,是不會打斷cpu的程序的。這樣的話,去抖延時,就會浪費cpu的效率。
        假如,按鍵掃描的后面跟一個協議處理的函數。
        即:

        while(1)

        scan_key(); //按鍵掃描
        exe(); //協議解析

        這個時候,若接收中斷,在按鍵掃描時已經處理完成,正好按下按鍵,這個時候就必須要有20ms的間隔,在判斷完按鍵后,才可以進入協議解析函數。也就是說,如果沒有掃描函數,協議會立即執行解析并返回響應數據。而添加按鍵掃描后,協議有可能會在20ms后,進行解析并返回數據,這樣的話,就會使產品的實時性無法保證。

        所以我想了另一個方法,采用標致位,來實現延時,當然這個方法,肯定不是我第一個想出來的。如有雷同,可采用翻鋼镚方法進行選擇。
        就是采用if語句來實現延時,只不過寫程序時比較麻煩,但穩定性在stm8上測試了一下,感覺還可以。

        代碼如下
        首先申請幾個全局變量
        unsigned int time_ms,time_us,time_ns,time_flag;
        //以上這幾個是定時標志和定時計數變量
        unsigned key_old, key_new;
        //這兩個是按鍵鍵值

        /*******************************************************************************
        函數名:delay_ms()
        函數功能:延時
        參數:ms 毫秒
        返回:無
        備注:此延時函數采用if實現,使用時,必須先申請flag變量然后調用延時函數,最后在
        執行中加入flag判斷
        例:u16 time_flag,time_ms,time_us,time_ns;
        delay_ms(u16 ms);
        if(time_flag>0){time_flag=0;......內容}
        *******************************************************************************/
        void key_delay(unsigned int ms)
        {
        if(time_ms{
        if(time_us<10) //在應用時,不同的單片機,不同的頻率,需要進行調整
        {
        if(time_ns<8) //在應用時不同的單片機,不同的頻率,需要進行調整
        {
        time_ns++;
        }
        else
        {
        time_us++;
        time_ns=0;
        }
        }
        else
        {
        time_ms++;
        time_us=0;
        }
        }
        else
        {
        time_flag=1;
        time_ms=0;
        }
        }


        以上代碼,有一個time_flag,變量,這個變量就是定時標致變量。一旦這個標致置一,則說明定時器到時間
        使用時可以

        ///////////////////////////////////////////////////////////
        //函數名:scan()
        //功能:按鍵掃描
        //參數:無
        //返回值:無
        //備注:
        ///////////////////////////////////////////////////////////
        void scan()
        {
        u8 key_new;
        key_new = GPIOC->IDR;
        if(key_old != key_new)
        {
        key_delay(150);
        if(time_flag == 1)
        {
        time_flag = 0;
        if(key_old != key_new)
        {
        switch()
        {
        case 1: k1_exe(); break;
        case 2: k2_exe(); break;
        case 3: k3_exe(); break;
        case 4: k4_exe(); break;
        default: break;
        }
        key_old = key_new;
        }
        else

        time_ms=0;

        }
        }
        }

        以上就是代碼
        在大循環中,直接調用即可,和普通的按鍵函數一樣,只不過,這個的實時性,應該相對較高一些。
        while(1)

        scan_key(); //按鍵掃描
        exe(); //協議解析

        讓我們來分析一下,為啥這個函數相對較好一些。
        首先,我們來看
        scan_key();
        首先,掃描IO端口,存放如新按鍵變量
        key_new = GPIOC->IDR;
        然后將新按鍵與老按鍵號進行對比,如果新的按鍵號與老按鍵號不同,說明有按鈕按下。
        if(key_old != key_new)
        當有按鈕按下的時候進入,延時函數,
        key_delay(150);
        這時,進入多個if判斷,進行time_ns++;這個函數,最主要的功能就是判斷,當前的時間time_ms,與參數時間,是否一致,若不一致,則退出函數。這時time_flag不為1,當前的時間time_ms,與參數時間一致 ,這時time_flag為1。
        if(time_flag == 1)
        這個判斷就是判斷到時標致,如果到時,則說明去抖時間完成,則在判斷一次if(key_old != key_new),如果為否,則說明按鍵確實按下,否則則為沒有按下。有按鍵按下時,則會執行按鍵處理函數。
        若沒有按鍵按下,則清楚計數器。程序繼續執行。
        也就是說,不管是否在延時狀態,程序,都會向下執行,而不會卡在某一個函數或循環內不動。這樣的話,程序就會向下繼續執行。
        在程序中,若既有按鍵,又有一些對待實時性較高,但又不樂意放在中斷里的程序。可以采用這種方法來實現按鍵延時,可以相對的提高程序的運行效率。目前這個程序,不支持長按,但可以實現簡單的組合按鍵。



        關鍵詞: 按鍵去抖延時程

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 晋江市| 乌拉特后旗| 隆德县| 微博| 广宗县| 泊头市| 丰都县| 博乐市| 公主岭市| 新绛县| 阳泉市| 桃园县| 通榆县| 镇远县| 江油市| 中江县| 西华县| 浙江省| 讷河市| 耒阳市| 会同县| 黄骅市| 阳山县| 寻甸| 上思县| 广德县| 康乐县| 满城县| 婺源县| 长海县| 合川市| 五家渠市| 孟州市| 永安市| 江永县| 阳信县| 平度市| 东兰县| 顺平县| 桓台县| 柘城县|