久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

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

作者:huqin   來源:本站原創   點擊數:  更新時間:2013年11月21日   【字體:

按鍵去抖,一般采用普通延時,如

if((GPIOC->IDR & 0x01)== 0)
{
    delay_ms(20);
    if(GPIOC->IDR & 0x01)== 0
    {
            //進行按鍵處理函數
    }
}

這個程序,需要有一個普通的延時程序,來檢測去抖動,這個延時一般采用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<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),如果為否,則說明按鍵確實按下,否則則為沒有按下。有按鍵按下時,則會執行按鍵處理函數。
若沒有按鍵按下,則清楚計數器。程序繼續執行。
也就是說,不管是否在延時狀態,程序,都會向下執行,而不會卡在某一個函數或循環內不動。這樣的話,程序就會向下繼續執行。
在程序中,若既有按鍵,又有一些對待實時性較高,但又不樂意放在中斷里的程序?梢圆捎眠@種方法來實現按鍵延時,可以相對的提高程序的運行效率。目前這個程序,不支持長按,但可以實現簡單的組合按鍵。
歡迎一切拍磚,轉載以及抄襲。若感覺此文章對您有所幫助,請支持一下51hei單片機論壇
您的支持,是我原創的動力,謝謝。

關閉窗口

相關文章

主站蜘蛛池模板: 亚洲精品欧美一区二区三区 | 国产精品特级片 | 在线观看亚洲欧美 | 亚洲天堂一区二区 | 国精产品一区一区三区免费完 | 久久久精品久 | 亚洲精品在线看 | 成人午夜看片 | 一区二区av | 成人亚洲精品久久久久软件 | 欧美日韩国产一区二区三区 | 国产福利精品一区 | 日韩欧美在线观看视频 | 中文字幕不卡在线88 | 国产精品久久二区 | 色婷婷av久久久久久久 | 欧洲一区二区三区 | 成人在线电影网站 | 亚洲精品女优 | 日韩在线视频一区二区三区 | 国产精品久久久久久久久免费樱桃 | 激情a | 亚洲一区二区在线播放 | 超级乱淫av片免费播放 | 欧美性视频在线播放 | 久久精品视频播放 | 亚洲午夜精品一区二区三区他趣 | 99在线免费观看视频 | 久久久2o19精品 | 日韩在线小视频 | 99中文字幕 | 成人午夜免费在线视频 | 国产精品久久久久久久久久久久久久 | 伦理一区二区 | 久久久91| 亚洲 欧美 日韩 在线 | 亚洲天堂影院 | 成人永久免费视频 | 国产成人在线播放 | 一级做a爰片性色毛片16美国 | 欧美精品第一区 |