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

2020-12-15 電子產品世界

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

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

//進行按鍵處理函數

}

本文引用地址:http://www.eepw.com.cn/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),如果為否,則說明按鍵確實按下,否則則為沒有按下。有按鍵按下時,則會執行按鍵處理函數。
若沒有按鍵按下,則清楚計數器。程序繼續執行。
也就是說,不管是否在延時狀態,程序,都會向下執行,而不會卡在某一個函數或循環內不動。這樣的話,程序就會向下繼續執行。
在程序中,若既有按鍵,又有一些對待實時性較高,但又不樂意放在中斷裡的程序。可以採用這種方法來實現按鍵延時,可以相對的提高程序的運行效率。目前這個程序,不支持長按,但可以實現簡單的組合按鍵。


相關焦點

  • 自學單片機第二十二篇:延時消抖
    按鍵的延時消抖是初學單片機的必經之路,因為只要是機械開關所傳遞的信號,都會存在波動,有時這些波動是「致命」的,所以消除其影響就是一門手藝了。硬體消抖有其優點,同樣的也有不方便的地方,開發成本高,操作難度大,可移植性差。軟體消抖就相對較好些,新手即可操作,延時消抖,並非消抖的最終最優方法,但好在簡單易懂,我們先認識消抖的方法和目的。
  • 高手談單片機裸奔的程序框架
    而且對MCU的編程控制會提升一個高度概況——就是對各種外圍進行控制(如果是對複雜算法的運算就會用DSP了),而外圍與MCU的通信方式一般也就幾種時序:IIC,SPI,intel8080,M6800。這樣看來MCU周圍的編程就是一個很簡單的東西了。
  • 在進行C51程序設計時如何精確延時的常見方法介紹
    單片機開發者在編制各種應用程式時經常會遇到實現精確延時的問題,比如按鍵去抖、數據傳輸等操作都要在程序中插入一段或幾段延時,時間從幾十微秒到幾秒。有時還要求有很高的精度,如使用單總線晶片DS18B20時,允許誤差範圍在十幾微秒以內,否則,晶片無法工作。
  • 第13節:按住一個獨立按鍵不鬆手的加速勻速觸發
    按鍵觸發節奏不斷加快,蜂鳴器鳴叫的節奏也不斷加快。直到它們都到達一個極限值,然後以此極限值間隔勻速觸發。在剛開始加速的時候,按鍵觸發與蜂鳴器觸發的步驟是一致的,等它們任意一個達到極限值的時候,急促的聲音跟按鍵的觸發不一致,並不是蜂鳴器每叫一次,按鍵就觸發一次。實際上加速到最後,按鍵觸發的速度遠遠比蜂鳴器的觸發速度快。
  • 51單片機學習之5-獨立按鍵和矩陣鍵盤
    第14集本文引用地址:http://www.eepw.com.cn/article/201611/323867.htm鍵盤的原理鍵盤分編碼鍵盤(例如電腦鍵盤)和非編碼鍵盤(自己用程序去識別
  • 單片機彙編延時程序的理解
    MOV R7,#250 ;D1: MOV R6,#250 ;D2: DJNZ R6,D2 ;DJNZ R7,D1 ;RET如果用高級語言編程,只需要簡單地調用延時函數就可以實現,但是計算機具體是怎麼實現的呢?
  • 碰撞開關(按鈕傳感器)消抖秘籍第一招
    消抖?你看到這個標題是不是有點懵?為什麼要消抖?我們先看一個實例,你就會感覺抖動的威力了。先把測試神器拿出來,在一個Aruduino UNO主板(為了方便,用上了擴展板)的3號數字管腳上外接了一個按鈕傳感器(碰撞開關),如圖1所示:
  • 談談51單片機延時子程序
    延時程序在單片機編程中使用非常廣泛,但一些讀者在學習中不知道延時程序怎麼編程,不知道機器周期和指令周期的區別,不知道延時程序指令的用法, ,本文就此問題從延時程序的基本概念、機器周期和指本文引用地址:http://www.eepw.com.cn/article/201611/321877.htm令周期的區別和聯繫
  • 按鍵識別方法之一
    其實,作為一個按鍵從沒有按下到按下以及釋放是一個完整的過程,也就是說,當我們按下一個按鍵時,總希望某個命令只執行一次,而在按鍵按下的因此在按鍵按下的時候, 圖4.8.2要把我們手上的幹擾信號以及按鍵的機械接觸等幹擾信號給濾除掉,一般情況下,我們可以採用電容來濾除掉這些幹擾信號,但實際上,會增加硬體成本及硬體電路的體積,這是我們不希望,總得有個辦法解決這個問題,因此我們可以採用軟體濾波的方法去除這些幹擾信號,一般情況下,一個按鍵按下的時候,
  • 編寫延時函數的簡單方法
    如果從keil裡看了c語言的反彙編代碼然後根據晶振和指令計算延時的時間這樣雖然非常的準確但是相當的麻煩而且容易搞錯,我這裡介紹一個最簡單的方法.可以驗證你的延時函數這裡用一個例程詳細介紹一下。下面這個sec就是程序運行到現在的這一行所用的時間。兩次時間差就是延時函數使用的時間,如果與1ms相差比較多,用戶可以調整j參數的值,使延時時間儘量接近1ms。
  • 各種彙編延時程序大集合
    在論壇上看到不少不錯的延時程序,整理如下共同分享:本文引用地址:http://www.eepw.com.cn/article/201611/321248.htm精確延時計算公式:延時時間=[(2*第一層循環+3)*第二層循環
  • 一篇文章告訴你,按鍵設計3種方案優缺點分析!
    一般的在按鍵的設計上,一般有三種方案:三是將按鍵接到外部中斷引腳上,利用按鍵按下產生的邊沿信號進行按鍵檢測,如圖1.3所示;第一種是最簡單和最基礎的,對於單片機初學者很容易理解和使用,但是缺點是,需要在主循環中不斷檢測按鍵是否按下,並且需要做消抖處理。若主循環中某個函數任務佔用時間較長,則按鍵會有不同程度的「失靈」。第二種,優點是能夠在有限的GPIO情況下,擴展儘可能多的按鍵。
  • VBA程序中,利用API函數讓程序達到毫秒級的延時
    大家好,我們今日繼續講解VBA代碼解決方案的第82講內容:如何利用代碼讓程序延時,SLEEP函數和timeGetTime函數兩個API函數的講解。在上一講中我們講了使用Wait方法,但這種方法的不足是只能提供精度為1秒的延時,如果需要更低精度的延時,需要使用Sleep API函數,如下面的代碼所示。
  • 嵌入式C實現延時程序的不同變量的區別
    在嵌入式系統中,延時是經常需要使用的一種手段,延時的方法可以通過使用類似於"NOP"的指令來實現,但是如果延時的時間比較長,如果使用太多的"NOP"指令則會消耗過多的儲存空間,最好的方法是使用子程序(彙編語言中)或子函數(高級語言中)。當然這裡並不打算討論如果使用定時器中斷來實現延時。
  • 單片機延時程序經驗
    但在單片機的C語言編程中,經常需要用幾個空指令產生短延時的效果。這在彙編語言中很容易實現,寫幾個nop就行了。在keil C51中,直接調用庫函數:#include // 聲明了void _nop_(void);_nop_(); // 產生一條NOP指令作用:對於延時很短的,要求在us級的,採用「_nop_」函數,這個函數相當彙編NOP指令,延時幾微秒。
  • STM32 嵌入式學習入門(3)——STM32F103 按鍵輸入控制LED燈
    這裡是按鍵控制LED燈,所以我們首先要掃描與按鍵相連的IO口的電平。如果IO電平發生變化,那麼說明按鍵被按下了,我們就要讓燈的狀態發生反轉。如果IO電平沒有發生變化,那麼說明按鍵沒有被按下,我們可以過一個很小的時間間隔再去掃描與按鍵相連的IO口看是否發生變化,這樣形成了一個死循環。
  • 簡單拍攝延時大作 Brinno TLC200評測
    不過,如果說到延時攝影,相信大家瞬間就知道我們要介紹的是什麼了。隨著越來越多攝影器材的普及,大家漸漸對傳統拍攝模式下的作品感到麻木,我們開始希望有更新鮮的影像作品來刺激我們的感官。而延時攝影無疑正是這樣的作品,通常我們拍攝延時作品都需要非常複雜的設備,有沒有什麼能讓我們更加方便拍攝延時攝影作品的設備或方法呢?Brinno帶來的縮時拍攝像機,替過我們解決了這個問題。
  • 按鍵與菜單在嵌入式系統中的設計與應用
    所以採用液晶提供菜單與按鍵反饋相組合的方式為理想的人機互動方式。根據實際不同的設計,本文主要介紹了在嵌入式系統中按鍵的軟、硬體設計及菜單和程序模式之間的關係。二、按鍵的軟、硬體設計在嵌入式系統中,按鍵是常用的人機互動接口,其硬體電路設計的質量直接關係著最終產品的使用,決定著用戶對產品的第一印象,所以,決不可輕視按鍵設計在電路中的作用。下面介紹幾種常用的按鍵設計電路及其特點。1. 埠按鍵一對一方式這種方式在所需按鍵較少的系統中經常採用,其典型電路圖1所示。