【按鍵】[獨立按鍵]
二、 [雙擊]程式
1.雙擊介紹
- 雙擊的判定
在完成第一次【單擊】之後,在一定的時間間隔內(本程式使用的是300ms),接著完成第二次【單擊】,及判定為【雙擊】。 - 雙擊的響應
1)在預設的時間間隔內完成第二次【單擊】,按鍵釋放後,響應返回有效鍵值【雙擊】。
2)如果第二次按下鍵並一直按住,當按住的時間超過設定的時間間隔(300ms)後,會響應第一個【單擊】,並返回有效鍵值【單擊】。
注:【單擊】是包括按下和釋放按鍵的過程,判定方式沿用上文所說的,如果忘了,可以參考上文。 - 雙擊響應時序圖
注:
T1:是單擊判定的時間,範圍:30ms < T1 < 3000ms
T2:是判定雙擊的時間間隔,是個定值 300ms。在完成第一次【單擊】後(釋放按鍵後開始計時),在這個時間間隔內,如果再一次完成【單擊】(釋放按鍵後結束計時),則判定為【雙擊】。
T3:與T1相同。
2.按鍵程結構
按鍵程式可以分為四個部分,第一部分:判斷有無單擊按鍵;第二部分:判斷雙擊即是在預設的時間間隔內,有無第二次【單擊】;第三部分:等待按鍵釋放。
3.雙擊程式的原始碼以及註釋
程式的註釋寫的很詳細,應該是可以讀懂的,如果有疑問可以留言討論。
上文的【單擊】函式作為這次【雙擊】程式的子函式
以下是key.c 的原始碼:
// =========================== key.c ======================
#include"reg51.h"
#define KEY_INPUT P1.0 // 按鍵IO
#define KEY_STATE_0 0 // 按鍵狀態
#define KEY_STATE_1 1
#define KEY_STATE_2 2
#define KEY_STATE_3 3
#define SINGLE_KEY_TIME 3 // SINGLE_KEY_TIME*10MS = 30MS 判定單擊的時間長度,軟體消抖
#define KEY_INTERVAL 30 // KEY_INTERVAL*10MS = 300MS 判定雙擊的時間間隔
#define LONG_KEY_TIME 300 // LONG_KEY_TIME*10MS = 3S 判定長按的時間長度
#define N_KEY 0 // no click
#define S_KEY 1 // single click
#define D_KEY 2 // double click
#define L_KEY 10 // long press
// ----------------------------------- key_driver --------------------------
unsigned char key_driver(void)
{
static unsigned char key_state = 0;
static unsigned int key_time = 0;
unsigned char key_press, key_return;
key_return = N_KEY; // 清除 返回按鍵值
key_press = key_input; // 讀取當前鍵值
switch (key_state)
{
case KEY_STATE_0: // 按鍵狀態0:判斷有無按鍵按下
if (!key_press) // 有按鍵按下
{
key_time = 0; // 清零時間間隔計數
key_state = KEY_STATE_1; // 然後進入 按鍵狀態1
}
break;
case KEY_STATE_1: // 按鍵狀態1:軟體消抖(確定按鍵是否有效,而不是誤觸)。按鍵有效的定義:按鍵持續按下超過設定的消抖時間。
if (!key_press)
{
key_time++; // 一次10ms
if(key_time>=SINGLE_KEY_TIME) // 消抖時間為:SINGLE_KEY_TIME*10ms = 30ms;
{
key_state = KEY_STATE_2; // 如果按鍵時間超過 消抖時間,即判定為按下的按鍵有效。按鍵有效包括兩種:單擊或者長按,進入 按鍵狀態2, 繼續判定到底是那種有效按鍵
}
}
else key_state = KEY_STATE_0; // 如果按鍵時間沒有超過,判定為誤觸,按鍵無效,返回 按鍵狀態0,繼續等待按鍵
break;
case KEY_STATE_2: // 按鍵狀態2:判定按鍵有效的種類:是單擊,還是長按
if(key_press) // 如果按鍵在 設定的長按時間 內釋放,則判定為單擊
{
key_return = S_KEY; // 返回 有效按鍵值:單擊
key_state = KEY_STATE_0; // 返回 按鍵狀態0,繼續等待按鍵
}
else
{
key_time++;
if(key_time >= LONG_KEY_TIME) // 如果按鍵時間超過 設定的長按時間(LONG_KEY_TIME*10ms=300*10ms=3000ms), 則判定為 長按
{
key_return = L_KEY; // 返回 有效鍵值值:長按
key_state = KEY_STATE_3; // 去狀態3,等待按鍵釋放
}
}
break;
case KEY_STATE_3: // 等待按鍵釋放
if (key_press)
{
key_state = KEY_STATE_0; // 按鍵釋放後,進入 按鍵狀態0 ,進行下一次按鍵的判定
}
break;
default: // 特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現在 沒有初始化key_state,第一次執行這個函式的時候
key_state = KEY_STATE_0;
break;
}
return key_return; // 返回 按鍵值
}
// ----------------------------------- key_read --------------------------------
unsigned char key_read(void)
{
static unsigned char key_state1=0, key_time1=0;
unsigned char key_return,key_temp;
key_return = N_KEY; // 清零 返回按鍵值
key_temp = key_driver(); // 讀取鍵值
switch(key_state1)
{
case KEY_STATE_0: // 按鍵狀態0:等待有效按鍵(通過 key_driver 返回的有效按鍵值)
if (key_temp == S_KEY ) // 如果是[單擊],不馬上返回單擊按鍵值,先進入 按鍵狀態1,判斷是否有[雙擊]的可能
{
key_time1 = 0; // 清零計時
key_state1 = KEY_STATE_1;
}
else // 如果不是[單擊],直接返回按鍵值。這裡的按鍵值可能是:[長按],[無效按鍵]
{
key_return = key_temp; // 返回 按鍵值
}
break;
case KEY_STATE_1: // 按鍵狀態1:判定是否有[雙擊]
if (key_temp == S_KEY) // 有[單擊]後,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms) 內,再次有[單擊],則為[雙擊],但是不馬上返回 有效按鍵值為[雙擊],先進入 按鍵狀態2,判斷是否有[三擊]
{
key_return = D_KEY; // 返回 有效按鍵:[雙擊]
key_state1 = KEY_STATE_0; // 返回 按鍵狀態0,等待新的有效按鍵
}
else // 有[單擊]後,如果在 設定的時間間隔(KEY_INTERVAL*10ms=30*10ms=300ms)內,沒有[單擊]出現,則判定為 [單擊]
{
key_time1++; // 計數 時間間隔
if(key_time1 >= KEY_INTERVAL) // 超過 時間間隔
{
key_return = S_KEY; // 返回 有效按鍵:[單擊]
key_state1 = KEY_STATE_0; // 返回 按鍵狀態0,等待新的有效按鍵
}
}
break;
default: // 特殊情況:key_state是其他值得情況,清零key_state。這種情況一般出現在 沒有初始化key_state,第一次執行這個函式的時候
key_state1 = KEY_STATE_0;
break;
}
return key_return; // 返回 按鍵值
}
使用注意:
1)硬體:按鍵的一端接地(GND),另一端接IO口。IO為輸入,一定要有上拉電阻。
2)定時器:這裡為了精確的定時,所以使用了定時器,定時器的時間是10ms。
3)掃描週期:呼叫此函式時,一定確保”掃描週期“要小於10ms。不然按鍵內所涉及的時間就會不準,會偏大。所涉及的時間包括消抖時長,按鍵長按時長等。
掃描週期定義:從 第一次進入按鍵掃描程式 開始,到第二次進入按鍵掃描程式時 結束,之間所用的時間。
測量掃描週期的方法:可以在按鍵掃描程式的第一句,新增IO口取反函式,然後用示波器檢視改IO口,其IO口週期的一般就是掃描週期了。
4)特別注意以上程式的3個關於時間的巨集,相當的重要。如果想更改按鍵的單擊的靈敏度,雙擊的速度,或者長按的時間,只需要修改這些巨集的值即可。
比如:針對於老人的使用的按鍵,就需要將雙擊的速度調節的慢一點,就可以將KEY_INTERVAL的值增大。
- SINGLE_KEY_TIME:單擊的靈敏度,值越小,越靈敏。
- KEY_INTERVAL :雙擊的點選速度,修改這個值,值越小,速度越快。同時這個值也決定了單擊的響應時間,因為單擊之後,還需要判斷在這個時間間隔內沒有第二次單擊,如果沒有才是真正的單擊,所以單擊響應的時間為:SINGLE_KEY_TIME+KEY_INTERVAL;
- LONG_KEY_TIME :長按的時間,修改這個即可,值越大,時間越長。
4.按鍵程式的使用例項
這裡以C51位硬體平臺進行例項講解
1)例項程式的功能:
- 單擊:點亮LED1
- 雙擊:熄滅LED1
- 長按:熄滅LED1
2)硬體:
- 按鍵IO:P1.0
- LED1 :P2.0
以下是 main.c 原始碼:
// =========================== main.c ======================
#include "reg51.h"
#include "key.c"
sbit LED1 = P2.0; // 定義LEDIO口
unsigned char g_u8_KeyValue; // 按鍵值
unsigned char g_flag_10ms_key; // 10ms 計時標誌
unsigned char key_read(); // 宣告讀取按鍵函式
void T0_Init_10ms(void) // timer0,初始化函式 ,定時時間為 10ms
{
TMOD |= 0x01;
TH0 = (65535 - 10000)/256;
TL0 = (65535 - 10000)%256;
ET0 = 1;
TR0 = 1;
EA = 1;
}
// 主函式
void main(void)
{
P1.0 = 1; // P1.0 拉高
T0_Init_10ms(); // 定時器0,初始化,定時10ms
while(1)
{
if(g_flag_10ms_key) // 等待10ms,定時完成
{
g_flag_10ms_key = 0; // 清零10ms定時標誌
g_u8_KeyValue = key_read(); // 讀取按鍵值
switch(g_u8_KeyValue)
{
case S_KEY: LED1 = 1; break; // 單擊 點亮LED1
case D_KEY: LED1 = 0; break; // 單擊 熄滅LED1
case L_KEY: LED1 = 0; break; // 長按 熄滅LED1
}
}
}
}
// timer0 中斷服務程式
void IRQ_T0(void) interrupt 1
{
g_flag_10ms_key = 1; // 置位 10ms 定時標誌
}
Pillar Peng
2016.3.29 10:25
其餘分享連結:
相關推薦
【按鍵】[獨立按鍵] - 3:三擊 以及 N擊
三、 [三擊]程式 1.三擊介紹 三擊判定:在完成第一次【單擊】之後,在一定的時間間隔內(本程式使用的是300ms),接著完成第二次【單擊】,時間間隔重新計時,然後又在這個時間間隔內,完成第三次【單擊】,及判定為【三擊】。 注:【單擊】是包括按下和釋放按鍵的過程,判定方式沿
【按鍵】[獨立按鍵] - 2:雙擊
二、 [雙擊]程式 1.雙擊介紹 雙擊的判定 在完成第一次【單擊】之後,在一定的時間間隔內(本程式使用的是300ms),接著完成第二次【單擊】,及判定為【雙擊】。 雙擊的響應 1)在預設的時間間隔內完成第二次【單擊】,按鍵釋放後,響應返回有效鍵值【雙擊】。 2)如
【按鍵】[獨立按鍵] - 1: 單擊,雙擊,三擊以及N擊
此按鍵程式的實現的功能是單個獨立按鍵的[單擊],[長按],[雙擊],[三擊]以及[多擊]。本文分為三個部分, 第一個部分是說[單擊],[長按]的程式; 第二部分是講[雙擊]; 第三部分是講[三擊],[N擊]; 一、 [單擊]、[長按]程式 1. 簡單介紹
(79)【按鍵】[獨立按鍵] - 1: 單擊,雙擊,三擊以及N擊
此按鍵程式的實現的功能是單個獨立按鍵的[單擊],[長按],[雙擊],[三擊]以及[多擊]。本文分為三個部分, 第一個部分是說[單擊],[長按]的程式; 第二部分是講[雙擊]; 第三部分是講[三擊],[N擊]; 一、 [單擊]、[長按]程式 1. 簡單介紹本按鍵程式的單擊和長按 首先說一下單擊,
【按鍵】[獨立按鍵]
二、 [雙擊]程式 1.雙擊介紹 雙擊的判定 在完成第一次【單擊】之後,在一定的時間間隔內(本程式使用的是300ms),接著完成第二次【單擊】,及判定為【雙擊】。 雙擊的響應 1)在預設的時間間隔內完成第二次【單擊】,按鍵釋放後,響應返回有效鍵值【
【stm32f407】獨立看門狗 iwdog
一.獨立看門狗 STM32F4的獨立看門狗由內部專門的32Khz低速時鐘(LSI)驅動,即使主時鐘發生故障,它也仍然有效。這裡需要注意獨立看門狗的時鐘是一個內部RC時鐘,所以並不是準確的32Khz,而
adb.【轉】模擬點擊、滑動、輸入、按鍵
按鍵 roi tps mut sta previous col ast ear 1、android adb 模擬點擊、滑動、輸入、按鍵 - 陽光檸檬_的技術筆記 - CSDN博客.html(https://blog.csdn.net/liukang325/article/d
【按鍵】短按,長按,按鍵釋放,三種模式的按鍵掃描程式(軟體消抖動)--- 矩陣鍵盤
請先閱讀上篇: 短按,長按,按鍵釋放,三種模式的按鍵掃描程式(軟體消抖動) 上面的程式適用於單個按鍵,那是不是也可以適用於矩陣鍵盤呢? 答案是肯定的。 接下來在這裡做一個簡單的擴充套件,具體框架不用改變,所以具體的框架內容和思路在這裡不詳述了,自行參考上篇文章,這裡就說說擴充套件
【按鍵】短按,長按,按鍵釋放,三種模式的按鍵掃描程式(軟體消抖動)
先來說一下這三種模式的意思: 1. 短按模式:單擊按鍵時,返回一次有效按鍵值;長按時也只返回一次有效按鍵值。這樣可以有效地排除因不小心長按帶來的返回多次有效按鍵,進而執行多次按鍵處理程式。 2. 長按模式: 單擊按鍵時,返回一次有效按鍵;長按時,返回多次有效按鍵值。這樣可以很快的調節
adb.【轉】模擬點選、滑動、輸入、按鍵
1、android adb 模擬點選、滑動、輸入、按鍵 - 陽光檸檬_的技術筆記 - CSDN部落格.html(https://blog.csdn.net/liukang325/article/details/79268173) ZC:“模擬滑動” 2、 //模擬輸入“001” adb shell
adb.【轉】Android手機可以通過adb執行按鍵操作
1、Android手機可以通過adb執行按鍵操作 - sealee01 - CSDN部落格.html(https://blog.csdn.net/u013678906/article/details/78540585) 2、 Android手機可以通過adb執行按鍵操作 如下,執行的是home鍵的操作
【PHP】安卓手機監聽物理返回按鍵
if(window.history && window.history.pushState) { $(window).on('popstate', function() { var hashLocation = location.hash;
【QTP】使用SendKeys來模擬鍵盤按鍵
在測試的過程中,經常會遇到這樣的情況: 1. 需要使用到一些按鍵的操作,如按Enter,F1什麼的情況; 2. 需要模擬組合鍵的情況,如按Ctrl+A什麼的; 3. 需要無法識別的控制元件中輸入一些東西。 在這時候就可以使用SendKeys來進行模擬按鍵的
【平凡曉聲 Cocos2d-x】虛擬按鍵控制精靈移動1
虛擬按鍵控制精靈移動1 最近想做過街機類的遊戲,做這類遊戲,首先我想到的就是精靈的移動,就是當按鍵按下時,精靈進行移動,當按鍵擡起時,精靈停止移動。 查閱了相關資料,最後整理出了兩種方法分享給大家,廢話不多說了,開幹。 1.通過touch點選事件和sche
【轉載兩篇關於android按鍵事件傳遞的文章,流程非常完整】Android按鍵事件傳遞流程(二)
5 應用層如何從Framework層接收按鍵事件 由3.2和4.5.4節可知,當InputDispatcher通過服務端管道向socket檔案描述符傳送訊息後,epoll機制監聽到了I/O事件,epoll_wait就會執行返回發生事件的個數給eve
Unity3D - 【API】檢測滑鼠的點選與鍵盤按鍵的按下
呼叫Input類中的GetButtonDown()或GetButtonUp()函式; 呼叫Input類中的GetKeyDown()或GetKeyUp()函式; ****************************************************
【Unity&按鍵設定】按下任意按鍵,返回按鍵的名稱
實現的是:按下任意按鍵,返回按鍵的名稱 根據參考資料1 1.方法 OnGUI() 函式的時間Event方法 using UnityEngine; using System.Collections; public class example : MonoBehaviou
【stm32f407】外部中斷實現按鍵中斷方式
一.外部中斷 STM32F4的每個IO都可以作為外部中斷的中斷輸入口,這點也是STM32F4的強大之處。STM32F407的中斷控制器支援22個外部中斷/事件請求。每個中斷設有狀態位,每個中斷/事件都
【TINY4412】LINUX移植筆記:(22)裝置樹LCD按鍵驅動
【TINY4412】LINUX移植筆記:(22)裝置樹 LCD按鍵驅動 宿主機 : 虛擬機器 Ubuntu 16.04 LTS / X64 目標板[底板]: Tiny4412SDK - 1506 目標板[核心板]:
對於 紅外遙控的訊號處理 每一個按鍵都會有單獨的操作【Arduino】
長話短說,Arduino下的紅外遙控器實驗。需要一跟10歐電阻。麵包線 子對子 *3.遙控一個。紅外接收頭一個。 已經做好按下每一個鍵的處理,螢幕上會輸出你按下的那個鍵。 紅外遙控器長這樣子 線這樣子接: 看好線的顏色 最後是程式碼部分,已經設定好按下指定