<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                【97.1 按住不松手的連續均勻觸發。】 ![](https://img.kancloud.cn/a2/3d/a23df87ac21f61d2182864f67461b009_359x103.png) 上圖97.1.1 獨立按鍵電路 ![](https://img.kancloud.cn/73/34/7334d9d189f0de190e15939b9fff75d9_214x279.png) 上圖97.1.2 灌入式驅動8個LED ![](https://img.kancloud.cn/89/70/8970513a066fe0726b2997dcb0329ce0_194x190.png) 上圖97.1.3 有源蜂鳴器電路 在電腦上刪除某個文件某行文字的時候,單擊一次“退格按鍵\[Backspace\]”,就刪除一個文字,如果按住“退格按鍵\[Backspace\]”不松手,就會“連續均勻”的觸發“刪除”的功能,自動逐個把整行文字刪除清空,這就是“按住不松手的連續均勻觸發”應用案例之一。除此之外,在很多需要人機交互的項目中都有這樣的功能,為了快速加減某個數值,按住某個按鍵不松手,某個數值有節奏地快速往上加或者快速往下減。這種“按住不松手連續均勻觸發”的按鍵識別,在程序上有“3個時間”需要留意,第1個是按鍵單擊的“濾波”時間,第2個是按鍵“從單擊進入連擊”的間隔時間(此時間是“單擊”與“連擊”的分界線),第3個是按鍵“連擊”的間隔時間, 本節例程實現的功能如下:(1)8個受按鍵控制的跑馬燈在某一時刻只有1個LED亮,每觸發一次K1按鍵,“亮的LED”就“往左邊跑一步”;相反,每觸發一次K2按鍵,“亮的LED”就“往右邊跑一步”。如果按住K1或者K2不松手就連續觸發,“亮的LED”就“連續跑”,一直跑到左邊或者右邊的盡頭。(2)按鍵每“單擊”一次蜂鳴器就鳴叫一次,但是,當按鍵“從單擊進入連擊”后,蜂鳴器就不鳴叫。 \#include "REG52.H" \#define KEY\_VOICE\_TIME 50 \#define KEY\_SHORT\_TIME 25 //按鍵單擊的“濾波”時間25ms \#define KEY\_ENTER\_CONTINUITY\_TIME 300 //按鍵“從單擊進入連擊”的間隔時間300ms \#define KEY\_CONTINUITY\_TIME 80 //按鍵“連擊”的間隔時間80ms \#define BUS\_P0 P0 //8個LED燈一一對應單片機的P0口總線 void T0\_time(); void SystemInitial(void) ; void Delay(unsigned long u32DelayTime) ; void PeripheralInitial(void) ; void BeepOpen(void); void BeepClose(void); void VoiceScan(void); void KeyScan(void); void KeyTask(void); void DisplayTask(void); //顯示的任務函數(LED顯示狀態) sbit P3\_4=P3^4; //蜂鳴器 sbit KEY\_INPUT1=P2^2; //K1按鍵識別的輸入口。 sbit KEY\_INPUT2=P2^1; //K2按鍵識別的輸入口。 volatile unsigned char vGu8BeepTimerFlag=0; volatile unsigned int vGu16BeepTimerCnt=0; unsigned char Gu8LedStatus=0; //LED燈的狀態 unsigned char Gu8DisplayUpdate=1; //顯示的刷新標志 volatile unsigned char vGu8KeySec=0; //按鍵的觸發序號 volatile unsigned char vGu8ShieldVoiceFlag=0; //屏蔽聲音的標志 void main() { SystemInitial(); Delay(10000); PeripheralInitial(); while(1) { KeyTask(); //按鍵的任務函數 DisplayTask(); //顯示的任務函數(LED顯示狀態) } } /\* 注釋一: \* Gu8DisplayUpdate這類“顯示刷新變量”在“顯示框架”里是很常見的,而且屢用屢爽。 \* 目的是,既能及時刷新顯示,又能避免主函數“不斷去執行顯示代碼”而影響程序效率。 \*/ void DisplayTask(void) //顯示的任務函數(LED顯示狀態) { if(1==Gu8DisplayUpdate) //需要刷新一次顯示 { Gu8DisplayUpdate=0; //及時清零,避免主函數“不斷去執行顯示代碼”而影響程序效率 //Gu8LedStatus是左移的位數,范圍(0至7),決定了跑馬燈的顯示狀態。 BUS\_P0=~(1<<Gu8LedStatus); //“左移<<”之后的“取反~”,因為LED電路是灌入式驅動方式。 } } /\* 注釋二: \* 按鍵“連續均勻觸發”的識別過程: \* 第一步:平時只要K1沒有被按下,按鍵的自鎖標志Su8KeyLock1、去抖動延時計數器Su16KeyCnt1、 \* 連擊計數器Su16KeyContinuityCnt1,一直被清零。 \* 第二步:一旦K1按鍵被按下,去抖動延時計數器Su16KeyCnt1開始在定時中斷函數里累加,在還沒 \* 累加到閥值KEY\_SHORT\_TIME時,如果在這期間由于受外界干擾或者按鍵抖動, \* 而使IO口突然瞬間觸發成高電平,這個時候馬上把延時計數器Su16KeyCnt1清零, \* 這個過程非常巧妙,非常有效地去除瞬間的雜波干擾。 \* 第三步:如果K1按鍵按下的時間超過了閥值KEY\_SHORT\_TIME,則觸發一次“單擊”, 同時,馬上把自鎖 \* 標志Su8KeyLock1置1防止按住按鍵不松手后一直觸發,并且把計數器Su16KeyCnt1清零為了下 \* 一步用來累加“從單擊進入連擊的間隔時間1000ms”。如果此時還沒有松手,直到發現按下的時 \* 間超過“從單擊進入連擊的間隔時間”閥值KEY\_ENTER\_CONTINUITY\_TIME時,從此進入“連擊” \* 的模式,連擊計數器Su16KeyContinuityCnt1開始累加,每到達一次閥值 \* KEY\_CONTINUITY\_TIME就觸發1次按鍵,為了屏蔽按鍵聲音及時把vGu8ShieldVoiceFlag也置1, \* 同時,Su16KeyContinuityCnt1馬上清零為繼續連擊作準備。 \* 第四步:等K1按鍵松手后,自鎖標志Su8KeyLock1、去抖動延時計數器Su16KeyCnt1、 \* 連擊計數器Su16KeyContinuityCnt1,及時清零,為下一次按鍵觸發做準備。 \*/ void KeyScan(void) //此函數放在定時中斷里每1ms掃描一次 { static unsigned char Su8KeyLock1; static unsigned int Su16KeyCnt1; static unsigned int Su16KeyContinuityCnt1; //連擊計數器 static unsigned char Su8KeyLock2; static unsigned int Su16KeyCnt2; static unsigned int Su16KeyContinuityCnt2; //連擊計數器 //K1按鍵 if(0!=KEY\_INPUT1)//單個K1按鍵沒有按下,及時清零一些標志。 { Su8KeyLock1=0; //按鍵解鎖 Su16KeyCnt1=0; //去抖動延時計數器清零,此行非常巧妙,是全場的亮點。 Su16KeyContinuityCnt1=0; //連擊計數器 } else if(0==Su8KeyLock1)//單個按鍵K1被按下 { Su16KeyCnt1++; //累加定時中斷次數,每一次累加額度是1ms if(Su16KeyCnt1>=KEY\_SHORT\_TIME) //按鍵的“濾波”時間25ms { Su8KeyLock1=1; //“自鎖” vGu8KeySec=1; //觸發一次K1按鍵 Su16KeyCnt1=0; //清零,為了下一步用來累加“從單擊進入連擊的間隔時間300ms” } } else if(Su16KeyCnt1<=KEY\_ENTER\_CONTINUITY\_TIME)//按住不松手累加到300ms { Su16KeyCnt1++; //累加定時中斷次數,每一次累加額度是1ms } else //按住累加到300ms后仍然不放手,這個時候進入有節奏的連續觸發 { Su16KeyContinuityCnt1++; //連擊計數器開始累加,每一次累加額度是1ms if(Su16KeyContinuityCnt1>=KEY\_CONTINUITY\_TIME) //按住沒松手,每0.08秒就觸發一次 { Su16KeyContinuityCnt1=0; //清零,為了繼續連擊。 vGu8KeySec=1; //觸發一次K1按鍵 vGu8ShieldVoiceFlag=1; //把當前按鍵觸發的聲音屏蔽掉 } } //K2按鍵 if(0!=KEY\_INPUT2) { Su8KeyLock2=0; Su16KeyCnt2=0; Su16KeyContinuityCnt2=0; } else if(0==Su8KeyLock2) { Su16KeyCnt2++; if(Su16KeyCnt2>=KEY\_SHORT\_TIME) { Su8KeyLock2=1; vGu8KeySec=2; //觸發一次K2按鍵 Su16KeyCnt2=0; } } else if(Su16KeyCnt2<=KEY\_ENTER\_CONTINUITY\_TIME) { Su16KeyCnt2++; } else { Su16KeyContinuityCnt2++; if(Su16KeyContinuityCnt2>=KEY\_CONTINUITY\_TIME) { Su16KeyContinuityCnt2=0; vGu8KeySec=2; //觸發一次K2按鍵 vGu8ShieldVoiceFlag=1; //把當前按鍵觸發的聲音屏蔽掉 } } } void KeyTask(void) //按鍵任務函數,放在主函數內 { if(0==vGu8KeySec) { return; //按鍵的觸發序號是0意味著無按鍵觸發,直接退出當前函數,不執行此函數下面的代碼 } switch(vGu8KeySec) //根據不同的按鍵觸發序號執行對應的代碼 { case 1: //K1觸發的任務 if(Gu8LedStatus>0) { Gu8LedStatus--; //控制LED“往左邊跑” Gu8DisplayUpdate=1; //刷新顯示 } if(0==vGu8ShieldVoiceFlag) //聲音沒有被屏蔽 { vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; } vGu8ShieldVoiceFlag=0; //及時把屏蔽標志清零,避免平時正常的單擊聲音也被淹沒。 vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 2: //K2觸發的任務 if(Gu8LedStatus<7) { Gu8LedStatus++; //控制LED“往右邊跑” Gu8DisplayUpdate=1; //刷新顯示 } if(0==vGu8ShieldVoiceFlag) //聲音沒有被屏蔽 { vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; } vGu8ShieldVoiceFlag=0; //及時把屏蔽標志清零,避免平時正常的單擊聲音也被淹沒。 vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; } } void T0\_time() interrupt 1 { VoiceScan(); KeyScan(); //按鍵識別的驅動函數 TH0=0xfc; TL0=0x66; } void SystemInitial(void) { TMOD=0x01; TH0=0xfc; TL0=0x66; EA=1; ET0=1; TR0=1; } void Delay(unsigned long u32DelayTime) { for(;u32DelayTime>0;u32DelayTime--); } void PeripheralInitial(void) { } void BeepOpen(void) { P3\_4=0; } void BeepClose(void) { P3\_4=1; } void VoiceScan(void) { static unsigned char Su8Lock=0; if(1==vGu8BeepTimerFlag&&vGu16BeepTimerCnt>0) { if(0==Su8Lock) { Su8Lock=1; BeepOpen(); } else { vGu16BeepTimerCnt--; if(0==vGu16BeepTimerCnt) { Su8Lock=0; BeepClose(); } } } }
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看