第11節:同一個按鍵短按與長按的區別觸發

2020-12-18 電子產品世界
開場白:

上一節講了類似電腦鍵盤組合按鍵觸發的功能,這節要教會大家一個知識點:如何在上一節的基礎上,略作修改,就可以實現同一個按鍵短按長按區別觸發

本文引用地址:http://www.eepw.com.cn/article/201611/319797.htm

具體內容,請看原始碼講解。

(1)硬體平臺:基於朱兆祺51單片機學習板。用矩陣鍵盤中的S1和S5號鍵作為獨立按鍵,記得把輸出線P0.4一直輸出低電平,模擬獨立按鍵的觸發地GND。

(2)實現功能:兩個獨立按鍵S1和S5,按住其中一個按鍵,在短時間內鬆手,則認為是短按,觸發蜂鳴器短鳴一聲。如果一直按住這個按鍵不鬆手,那麼超過規定的長時間內,則認為是長按,觸發蜂鳴器長鳴一聲。

(3)原始碼講解如下:

#include "REG52.H"

#define const_voice_short 20 //蜂鳴器短叫的持續時間

#define const_voice_long 140 //蜂鳴器長叫的持續時間

/* 注釋一:

* 調整抖動時間閥值的大小,可以更改按鍵的觸發靈敏度。

* 去抖動的時間本質上等於累計定時中斷次數的時間。

*/

#define const_key_time_short1 20 //短按的按鍵去抖動延時的時間

#define const_key_time_long1 400 //長按的按鍵去抖動延時的時間

#define const_key_time_short2 20 //短按的按鍵去抖動延時的時間

#define const_key_time_long2 400 //長按的按鍵去抖動延時的時間

void initial_myself();

void initial_peripheral();

void delay_long(unsigned int uiDelaylong);

void T0_time(); //定時中斷函數

void key_service(); //按鍵服務的應用程式

void key_scan(); //按鍵掃描函數 放在定時中斷裡

sbit key_sr1=P0^0; //對應朱兆祺學習板的S1鍵

sbit key_sr2=P0^1; //對應朱兆祺學習板的S5鍵

sbit key_gnd_dr=P0^4; //模擬獨立按鍵的地GND,因此必須一直輸出低電平

sbit beep_dr=P2^7; //蜂鳴器的驅動IO口

unsigned char ucKeySec=0; //被觸發的按鍵編號

unsigned int uiKeyTimeCnt1=0; //按鍵去抖動延時計數器

unsigned char ucKeyLock1=0; //按鍵觸發後自鎖的變量標誌

unsigned char ucShortTouchFlag1=0; //短按的觸發標誌

unsigned int uiKeyTimeCnt2=0; //按鍵去抖動延時計數器

unsigned char ucKeyLock2=0; //按鍵觸發後自鎖的變量標誌

unsigned char ucShortTouchFlag2=0; //短按的觸發標誌

unsigned int uiVoiceCnt=0; //蜂鳴器鳴叫的持續時間計數器

void main()

{

initial_myself();

delay_long(100);

initial_peripheral();

while(1)

{

key_service(); //按鍵服務的應用程式

}

}

void key_scan()//按鍵掃描函數 放在定時中斷裡

{

/* 注釋二:

* 長按與短按的按鍵掃描的詳細過程:

* 第一步:平時只要按鍵沒有被按下時,按鍵的自鎖標誌,去抖動延時計數器一直被清零。

* 第二步:一旦兩個按鍵都被按下,去抖動延時計數器開始在定時中斷函數裡累加,在還沒累加到

* 閥值const_key_time_short1或者const_key_time_long1時,如果在這期間由於受外界幹擾或者按鍵抖動,而使

* IO口突然瞬間觸發成高電平,這個時候馬上把延時計數器uiKeyTimeCnt1

* 清零了,這個過程非常巧妙,非常有效地去除瞬間的雜波幹擾。這是我實戰中摸索出來的。

* 以後凡是用到開關感應器的時候,都可以用類似這樣的方法去幹擾。

* 第三步:如果按鍵按下的時間超過了短按閥值const_key_time_short1,則馬上把短按標誌ucShortTouchFlag1=1;

* 如果還沒有鬆手,一旦發現按下的時間超過長按閥值const_key_time_long1時,

* 先把短按標誌ucShortTouchFlag1清零,然後觸髮長按。在這段程序裡,把自鎖標誌ucKeyLock1置位,

* 是為了防止按住按鍵不鬆手後一直觸發。

* 第四步:等按鍵鬆開後,自鎖標誌ucKeyLock12及時清零,為下一次自鎖做準備。如果發現ucShortTouchFlag1等於1,

* 說明短按有效,這時觸發一次短按。

* 第五步:以上整個過程,就是識別按鍵IO口下降沿觸發的過程。

*/

if(key_sr1==1)//IO是高電平,說明兩個按鍵沒有全部被按下,這時要及時清零一些標誌位

{

ucKeyLock1=0; //按鍵自鎖標誌清零

uiKeyTimeCnt1=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。

if(ucShortTouchFlag1==1) //短按觸發標誌

{

ucShortTouchFlag1=0;

ucKeySec=1; //觸發一號鍵的短按

}

}

else if(ucKeyLock1==0)//有按鍵按下,且是第一次被按下

{

uiKeyTimeCnt1++; //累加定時中斷次數

if(uiKeyTimeCnt1>const_key_time_short1)

{

ucShortTouchFlag1=1; //激活按鍵短按的有效標誌

}

if(uiKeyTimeCnt1>const_key_time_long1)

{

ucShortTouchFlag1=0; //清除按鍵短按的有效標誌

uiKeyTimeCnt1=0;

ucKeyLock1=1; //自鎖按鍵置位,避免一直觸發

ucKeySec=2; //觸發1號鍵的長按

}

}

if(key_sr2==1)//IO是高電平,說明兩個按鍵沒有全部被按下,這時要及時清零一些標誌位

{

ucKeyLock2=0; //按鍵自鎖標誌清零

uiKeyTimeCnt2=0;//按鍵去抖動延時計數器清零,此行非常巧妙,是我實戰中摸索出來的。

if(ucShortTouchFlag2==1) //短按觸發標誌

{

ucShortTouchFlag2=0;

ucKeySec=3; //觸發2號鍵的短按

}

}

else if(ucKeyLock2==0)//有按鍵按下,且是第一次被按下

{

uiKeyTimeCnt2++; //累加定時中斷次數

if(uiKeyTimeCnt2>const_key_time_short2)

{

ucShortTouchFlag2=1; //激活按鍵短按的有效標誌

}

if(uiKeyTimeCnt2>const_key_time_long2)

{

ucShortTouchFlag2=0; //清除按鍵短按的有效標誌

uiKeyTimeCnt2=0;

ucKeyLock2=1; //自鎖按鍵置位,避免一直觸發

ucKeySec=4; //觸發2號鍵的長按

}

}

}

void key_service() //第三區 按鍵服務的應用程式

{

switch(ucKeySec) //按鍵服務狀態切換

{

case 1:// 1號鍵的短按 對應朱兆祺學習板的S1鍵

uiVoiceCnt=const_voice_short; //按鍵聲音的短觸發,滴一聲就停。

ucKeySec=0; //響應按鍵服務處理程序後,按鍵編號清零,避免一致觸發

break;

case 2:// 1號鍵的長按 對應朱兆祺學習板的S1鍵

uiVoiceCnt=const_voice_long; //按鍵聲音的長觸發,滴一聲就停。

ucKeySec=0; //響應按鍵服務處理程序後,按鍵編號清零,避免一致觸發

break;

case 3:// 2號鍵的短按 對應朱兆祺學習板的S5鍵

uiVoiceCnt=const_voice_short; //按鍵聲音的短觸發,滴一聲就停。

ucKeySec=0; //響應按鍵服務處理程序後,按鍵編號清零,避免一致觸發

break;

case 4:// 2號鍵的長按 對應朱兆祺學習板的S5鍵

uiVoiceCnt=const_voice_long; //按鍵聲音的長觸發,滴一聲就停。

ucKeySec=0; //響應按鍵服務處理程序後,按鍵編號清零,避免一致觸發

break;

}

}

void T0_time() interrupt 1

{

TF0=0; //清除中斷標誌

TR0=0; //關中斷

key_scan(); //按鍵掃描函數

if(uiVoiceCnt!=0)

{

uiVoiceCnt--; //每次進入定時中斷都自減1,直到等於零為止。才停止鳴叫

beep_dr=0; //蜂鳴器是PNP三極體控制,低電平就開始鳴叫。

}

else

{

; //此處多加一個空指令,想維持跟if括號語句的數量對稱,都是兩條指令。不加也可以。

beep_dr=1; //蜂鳴器是PNP三極體控制,高電平就停止鳴叫。

}

TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

TR0=1; //開中斷

}

void delay_long(unsigned int uiDelayLong)

{

unsigned int i;

unsigned int j;

for(i=0;i

{

for(j=0;j<500;j++) //內嵌循環的空指令數量

{

; //一個分號相當於執行一條空語句

}

}

}

void initial_myself() //第一區 初始化單片機

{

/* 注釋三:

* 矩陣鍵盤也可以做獨立按鍵,前提是把某一根公共輸出線輸出低電平,

* 模擬獨立按鍵的觸發地,本程序中,把key_gnd_dr輸出低電平。

* 朱兆祺51學習板的S1和S5兩個按鍵就是本程序中用到的兩個獨立按鍵。

*/

key_gnd_dr=0; //模擬獨立按鍵的地GND,因此必須一直輸出低電平

beep_dr=1; //用PNP三極體控制蜂鳴器,輸出高電平時不叫。

TMOD=0x01; //設置定時器0為工作方式1

TH0=0xf8; //重裝初始值(65535-2000)=63535=0xf82f

TL0=0x2f;

}

void initial_peripheral() //第二區 初始化外圍

{

EA=1; //開總中斷

ET0=1; //允許定時中斷

TR0=1; //啟動定時中斷

}

總結陳詞:

在很多需要人機互動的項目中,需要用按鍵來快速加減某個數值,這個時候如果按住一個按鍵不鬆手,這個數值要有節奏地快速往上加或者快速往下減。要現實這種功能,我們該怎麼寫程序?欲知詳情,請聽下回分解-----按住一個獨立按鍵不鬆手的連續步進觸發。

相關焦點

  • 第13節:按住一個獨立按鍵不鬆手的加速勻速觸發
    開場白:上一節講了按住一個獨立按鍵不鬆手的連續步進觸發功能,這節要教會大家如何在上一節的基礎上,略作修改,就可以實現按鍵的加速勻速觸發。需要注意的是:第一步:每次按下去觸發一次單擊按鍵,如果按下去到鬆手的時間不超過1秒,則不會進入連續加速觸發模式。第二步:如果按下去不鬆手的時間超過1秒,則進入連續加速觸發模式。按鍵觸發節奏不斷加快,蜂鳴器鳴叫的節奏也不斷加快。直到它們都到達一個極限值,然後以此極限值間隔勻速觸發。
  • 長按關機鍵卻不能關機,iPhone 11究竟如何關機?
    為什麼我長按iPhone 11手機的電源鍵卻不出現關機界面,而是Siri呢?而如果你此前用的是蘋果發布的取消了HOME鍵的iPhone X等手機的話,那麼你肯定知道手機的關機方法。而如果你此前用的根本就不是蘋果手機,或是還是有HOME鍵的蘋果8、7p等手機的話,那麼你可能根本不熟悉手機的關機方法,甚至和上面有疑問的小夥伴一樣,找不到手機的關機界面。
  • 車上這四個「按鍵」千萬不要亂按
    原標題:車上這四個「按鍵」千萬不要亂按   現在的中國幾乎是每個家庭都有屬於自己的汽車,在早晚高峰的時候很多城市都會出現堵車的現象,不過雖然現在汽車的
  • 第29節:數碼管通過切換窗口來設置參數不顯示為0的高位
    開場白:上一節在第4,3,2,1位顯示設置的參數時,還有一點小瑕疵。比如設置參數等於56時,實際顯示的是「0056」,也就是高位為0的如果不顯示,效果才會更好。這一節要教會大家兩個知識點:第一個:在上一節display_service()函數裡略作修改,把高位為0的去掉不顯示。
  • 德生獻給盲人朋友的厚禮——PL990收音機的按鍵、開關分布說明
    收音機右方靠近頂部,水平排列有5個按鍵,是插卡(或藍牙)播放的控制和收音機電源開關。從左到右分別是:第一個:播放/暫停按鍵。短按一下,暫停播放。再短按一下,恢復播放。長按一下,循環播放當前的音樂。再長按一下,取消循環播放。第二個:上一首選擇鍵。短按一次,則重播當前音樂。如果短按兩次,則選擇上一首音樂。
  • 清明節為何按陽曆而不按陰曆?和寒食節、上巳節有區別嗎?
    今天是2018年4月4日,明天4月5日就是清明節了,清明節是我國傳統節日,很多朋友疑惑:為何春節、中秋、端午等其它傳統節日都按陰曆,清明卻按陽曆?一、陰曆、陽曆、農曆的區別:要弄清楚這個問題,必須先介紹一下農曆、陰曆和陽曆的區別。先說陰曆,陰曆在天文學中主要指按月亮的月相周期來安排的曆法,也就是說,陰曆只考慮地球和月亮的相對位置變化,所以月圓總是在陰曆十五十六日。
  • 華為手機怎麼設置長按?這些長按小技巧你一定要掌握~
    大家在使用了這麼久的華為手機以後,知道在華為手機中有非常強大實用的長按功能呢?其實,當我們遇到這樣的問題時,我們完全可以使用華為手機的分屏功能來解決這樣的問題,而要開啟分屏模式,我們就可以直接長按華為手機的虛擬按鍵進行分屏操作,非常簡單。2.狀態欄打開功能設置我們在使用華為手機的時候,當我們想要打開某個功能的時候,都會從【設置】中進入再進行選擇使用。
  • 1毫秒決定成敗 鍵盤按鍵延時你在意麼?
    在格鬥類型的遊戲中,160ms按鍵延時給人更加乾脆利落的感覺,而255ms按鍵延時會讓使用慣160ms按鍵延時的玩家感到阻塞感。對於星際玩家來說同樣如此,更快的觸發按鍵往往引導勝利的走向。隨著科技實力的提升,USB鍵盤已經解決了按鍵衝突等諸多問題,並且可以實現調整傳輸速率,在傳輸速率上已經可以並肩並且超越PS/2接口了。觸發鍵程、信號抖動所產生的影響    鍵盤按鍵觸發鍵程長短對於按鍵響應有著不小的影響,這點對於分秒必爭的遊戲用戶來說也是不可接受的。
  • 絕地求生大逃殺按鍵、畫面及基礎設置推薦
    按鍵又該如何定義?下面來看絕地求生大逃殺按鍵、畫面及基礎設置推薦。1.靜走鍵刪除,長按肩射步行或者歪頭步行都可以取代此效果2.右鍵長按開鏡,滑鼠側鍵大拇指長按肩射,這個是沒有辦法的辦法,默認設置其實很不錯(XDD包括加強版XDD的BOMIN都是默認,因此他們的肩射,閃身噴都很流暢,而且我敢說很多默認設置的高手,很多肩射殺人一開始根本就是想開鏡的誤操作),但有2個缺點:開鏡慢,會先切到肩射畫面幾幀再開鏡
  • iPhone X長按電源鍵關機?千萬別這麼做了:正確方法在此
    此前我們已經介紹過,在iPhone X上,使用物理按鍵截圖的方式從電源鍵+Home調整為電源鍵+音量加。而通過已經放出的iPhone X上手體驗來看,iPhone X的關機也不能通過長按電源鍵來達到了,因為那樣只會呼出Siri。
  • 無限法則按鍵表大全按鍵怎麼設置比較好用,鍵位按鍵設置一覽
    近期不少玩家在評論區留言,詢問按鍵的問題,畢竟按鍵關係到遊戲操作的順手與否,無限法則大部分按鍵和絕地求生相同,但也有少許區別,小編整理了最全的按鍵表說明,我們一起來看。跳傘、開門、撿東西、上車、下車 : F前後左右移動 : W、S、A、D跳躍、翻牆 : 空格鍵趴下 : Z蹲下 : C加速跑(設置界面可以設置長按/切換) : Shift
  • 安徽基督教協會舉行按牧典禮 11人被按立為牧師
    2017年6月29下午,安徽省基督教協會在合肥市基督教堂舉行按牧典禮,洪路平、黃靈(女)、孫珣(女)、劉磊、張欣欣(女)、關玉仁、朱春暉(女)、陳立(女)、邢潔、王玉清、潘志樓11名同工被按立為牧師。
  • 雷蛇Tartarus Pro單手鍵盤,32枚可編程按鍵,戰鬥力強悍
    雙11囤電競裝備,雷蛇全新的塔洛斯魔蠍單手鍵盤或許就是你一直在尋找的那一款。塔洛斯魔蠍專業版配備了Razer模擬光軸,使其能夠感應到每個按鍵的按壓深度,甚至得以模擬類似於遊戲手柄扳機鍵的操控感。此外,玩家還可調整觸發點,最低至1.5毫米——以實現更快的觸發;亦或最高達3.6毫米,實現更深、更從容不迫的觸發。
  • 《絕地求生》吃雞畫面怎麼設置最好 最佳畫面參數及按鍵設置教程
    加上能不改就不改的理念,我的鍵位改動重點及說明如下: 1.靜走鍵刪除,長按肩射步行或者歪頭步行都可以取代此效果。 2.右鍵長按開鏡,滑鼠側鍵大拇指長按肩射,這個是沒有辦法的辦法,默認設置其實很不錯(XDD包括加強版XDD的BOMIN都是默認,因此他們的肩射,閃身噴都很流暢,而且我敢說很多默認設置的高手,很多肩射殺人一開始根本就是想開鏡的誤操作),但有2個缺點:開鏡慢,會先切到肩射畫面幾幀再開鏡。 射擊時肩射和開鏡無法交替覆蓋。
  • 當風箏節紛紛按下了暫停鍵
    然而,嚴重的疫情打亂了生活的節奏,各國的大型風箏節也紛紛按下了暫停鍵。在這裡,讓我們一起雲想關於風箏的記憶,放飛無拘無束的內心吧! 受新冠肺炎疫情影響,本應於4月20日至25日舉辦的第37屆濰坊國際風箏節宣布推遲。
  • 《尼爾機械紀元》F-Z結局按劇情順序解鎖攻略 全分支結局觸發條件
    導 讀 《尼爾機械紀元》F-Z總共21個惡搞分支結局,需按照一定的順序來解鎖,下面是由hyun310翻譯的《尼爾機械紀元》F-Z結局按劇情順序解鎖攻略
  • 湖南高速公路按最短路徑收費,持續到正月初十!
    途經湖南的高速公路又能省下一筆錢不管你走哪條路都將按最短路徑收費2月5日省高速公路建設開發總公司發布>自6日零時起至25日24時(共20天)全省高速公路將實行按最短路徑收費的應急保暢措施為何要調整?省內易擁堵的6個重點路段中,長張高速長益段雙向流量較上一日有明顯減少,變化幅度超過40%。省會長沙方面,長沙、長沙西收費站仍然高位運行。
  • 彈吉他按高把位按和弦是怎樣推算出來的?
    首先我們要了解如果你用非橫按和弦(比喻說AM和弦)來推導的話,這個按音名排列推算也是沒問題的,只是如果不是用橫按和弦的話,光用開放式和弦來推算的話,都是能推算出的,那種推算出的按法就非常難按或可以說按不出的了,一般人好少這樣來了!所以推算這些和弦我們只能用大橫按或小橫按和弦來推算會更好......
  • 四種情況下,三維觸摸是一個優越的功能,一個簡單的長按
    好了,讓我們來探討一下,與單個長按相比,3D觸摸實際上是一個更好的功能。一個小點開始,當然,但這是一個立即顯而易見的任何人誰嘗試3D觸摸第一次。一個平滑的動畫,回應你的手指壓力和一個非常好的,令人放心的「流行」觸覺反饋效果,從Taptic引擎使整個體驗非常滿意。就好像應用圖標或UI元素是實際的按鈕。
  • 圍棋初級對戰實錄(第十節:不按定式)
    第十節 不按定式初學者想要更快地提高下棋水平,學習並牢記定式是必須的,定式是前人總結出來的最佳應對方法。不按定式走,對高手來說或許是創新,但對初學者來說,肯定是損失。