<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>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                【106.1 按住不松手的先加速后勻速觸發。】 ![](https://img.kancloud.cn/89/70/8970513a066fe0726b2997dcb0329ce0_194x190.png) 上圖106.1.1 有源蜂鳴器電路 ![](https://img.kancloud.cn/73/34/7334d9d189f0de190e15939b9fff75d9_214x279.png) 上圖106.1.2 LED電路 ![](https://img.kancloud.cn/c1/8a/c18ad9232965b2a0699e388df49ac7b9_341x221.png) 上圖106.1.3 3\*3矩陣按鍵的電路 矩陣按鍵與前面章節“獨立按鍵按住不松手的先加速后勻速的觸發”的處理思路是一樣的。 當“連續加”或者“連續減”的數據范圍很大的時候,就需要按鍵的加速與勻速相結合的觸發方式。“加速”是指按住按鍵不松手,按鍵剛開始觸發是從慢到快的漸進過程,當“加速”到某個特別快的速度的時候,就“不再加速”,而是以該“恒定高速”進行“連續勻速”觸發。這種觸發方式,“加速”和“勻速”是相輔相成缺一不可的,為什么?假如沒有“加速”只有“勻速”,那么剛按下按鍵就直接以最高速的“勻速”進行,就會跑過頭,缺乏微調功能;而假如沒有“勻速”只有“加速”,那么按下按鍵不松手后,速度就會一直不斷飆升,最后失控過沖。 本節例程實現的功能如下: (1)要更改一個“設置參數”(一個全局變量),參數的范圍是0到800。 (2)8個受“設置參數”控制的跑馬燈在某一時刻只有1個LED亮,每觸發一次S1按鍵,該“設置參數”就自減1,最小值為0;相反,每觸發一次S9按鍵,該“設置參數”就自加1,最大值為800。 (3)LED燈實時顯示“設置參數”的范圍狀態: 只有第0個LED燈亮:0<=“設置參數”<100。 只有第1個LED燈亮:100<=“設置參數”<200。 只有第2個LED燈亮:200<=“設置參數”<300。 只有第3個LED燈亮:300<=“設置參數”<400。 只有第4個LED燈亮:400<=“設置參數”<500。 只有第5個LED燈亮:500<=“設置參數”<600。 只有第6個LED燈亮:600<=“設置參數”<700。 只有第7個LED燈亮:700<=“設置參數”<=800。 (4)按鍵每“單擊”一次蜂鳴器就鳴叫一次,但是,當按鍵“從單擊進入連擊”后,蜂鳴器就不鳴叫。 \#include "REG52.H" \#define KEY\_VOICE\_TIME 50 \#define KEY\_SHORT\_TIME 20 //按鍵單擊的“濾波”時間 \#define KEY\_ENTER\_CONTINUITY\_TIME 240 //按鍵“從單擊進入連擊”的間隔時間 \#define KEY\_CONTINUITY\_INITIAL\_TIME 64 //按鍵“連擊”起始的預設間隔時間 \#define KEY\_SUB\_DT\_TIME 6 //按鍵在“加速”時每次減小的時間。 \#define KEY\_CONTINUITY\_MIN\_TIME 8 //按鍵時間減小到最后的“勻速”間隔時間。 \#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 ROW\_INPUT1=P2^2; //第1行輸入口。 sbit ROW\_INPUT2=P2^1; //第2行輸入口。 sbit ROW\_INPUT3=P2^0; //第3行輸入口。 sbit COLUMN\_OUTPUT1=P2^5; //第1列輸出口。 sbit COLUMN\_OUTPUT2=P2^4; //第2列輸出口。 sbit COLUMN\_OUTPUT3=P2^3; //第3列輸出口。 volatile unsigned char vGu8BeepTimerFlag=0; volatile unsigned int vGu16BeepTimerCnt=0; unsigned int Gu16SetData=0; //“設置參數”。范圍從0到800。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; //及時清零,避免主函數“不斷去執行顯示代碼”而影響程序效率 if(Gu16SetData<100) { BUS\_P0=~(1<<0); //第0個燈亮 } else if(Gu16SetData<200) { BUS\_P0=~(1<<1); //第1個燈亮 } else if(Gu16SetData<300) { BUS\_P0=~(1<<2); //第2個燈亮 } else if(Gu16SetData<400) { BUS\_P0=~(1<<3); //第3個燈亮 } else if(Gu16SetData<500) { BUS\_P0=~(1<<4); //第4個燈亮 } else if(Gu16SetData<600) { BUS\_P0=~(1<<5); //第5個燈亮 } else if(Gu16SetData<700) { BUS\_P0=~(1<<6); //第6個燈亮 } else { BUS\_P0=~(1<<7); //第7個燈亮 } } } /\* 注釋二: \* 本節破題的關鍵: \* 矩陣按鍵涉及的按鍵數量很多,但是實際項目上一般只需要少數個別按鍵具備這種 \* “單擊”與“先加速后均勻觸發”的特殊技能,因此,在代碼上,必須把這類“特殊技能按鍵”與 \* “大眾按鍵”區分開來,才能相互清晰互不干擾。本節的“特殊技能按鍵”是S1和S9。 \* 如果覺得本節的講解不夠詳細具體,請先閱讀一下前面章節“獨立按鍵按住不松手的先加速后勻速觸發”。 \*/ void KeyScan(void) //此函數放在定時中斷里每1ms掃描一次 { static unsigned char Su8KeyLock=0; static unsigned int Su16KeyCnt=0; static unsigned char Su8KeyStep=1; static unsigned int Su16KeyContinuityTime=KEY\_CONTINUITY\_INITIAL\_TIME; //動態時間閥值 static unsigned char Su8ColumnRecord=0; switch(Su8KeyStep) { case 1: if(0==Su8ColumnRecord) { COLUMN\_OUTPUT1=0; COLUMN\_OUTPUT2=1; COLUMN\_OUTPUT3=1; } else if(1==Su8ColumnRecord) { COLUMN\_OUTPUT1=1; COLUMN\_OUTPUT2=0; COLUMN\_OUTPUT3=1; } else { COLUMN\_OUTPUT1=1; COLUMN\_OUTPUT2=1; COLUMN\_OUTPUT3=0; } Su16KeyCnt=0; Su8KeyStep++; break; case 2: //等待列輸出穩定,但不是去抖動延時 Su16KeyCnt++; if(Su16KeyCnt>=2) { Su16KeyCnt=0; Su8KeyStep++; } break; case 3: if(1==ROW\_INPUT1&&1==ROW\_INPUT2&&1==ROW\_INPUT3) { Su8KeyStep=1; //返回步驟1繼續掃描 Su8KeyLock=0; Su16KeyCnt=0; Su16KeyContinuityTime=KEY\_CONTINUITY\_INITIAL\_TIME; //動態時間閥值。重裝初始值。 Su8ColumnRecord++; if(Su8ColumnRecord>=3) { Su8ColumnRecord=0; } } else if(0==Su8KeyLock) { if(0==ROW\_INPUT1&&1==ROW\_INPUT2&&1==ROW\_INPUT3) { Su16KeyCnt++; if(Su16KeyCnt>=KEY\_SHORT\_TIME) { Su8KeyLock=1; if(0==Su8ColumnRecord) { vGu8KeySec=1; //觸發一次單擊 Su16KeyCnt=0; //計時器清零,為即將來臨的計時做準備 Su8KeyStep=4; //跳到S1按鍵的專屬區,脫離大眾按鍵 } else if(1==Su8ColumnRecord) { vGu8KeySec=2; } else if(2==Su8ColumnRecord) { vGu8KeySec=3; } } } else if(1==ROW\_INPUT1&&0==ROW\_INPUT2&&1==ROW\_INPUT3) { Su16KeyCnt++; if(Su16KeyCnt>=KEY\_SHORT\_TIME) { Su8KeyLock=1; if(0==Su8ColumnRecord) { vGu8KeySec=4; } else if(1==Su8ColumnRecord) { vGu8KeySec=5; } else if(2==Su8ColumnRecord) { vGu8KeySec=6; } } } else if(1==ROW\_INPUT1&&1==ROW\_INPUT2&&0==ROW\_INPUT3) { Su16KeyCnt++; if(Su16KeyCnt>=KEY\_SHORT\_TIME) { Su8KeyLock=1; if(0==Su8ColumnRecord) { vGu8KeySec=7; } else if(1==Su8ColumnRecord) { vGu8KeySec=8; } else if(2==Su8ColumnRecord) { vGu8KeySec=9; //觸發一次單擊 Su16KeyCnt=0; //計時器清零,為即將來臨的計時做準備 Su8KeyStep=6; //跳到S9按鍵的專屬區,脫離大眾按鍵 } } } } break; /\*---------S1按鍵的專屬區----------------\*/ case 4: if(0==ROW\_INPUT1&&1==ROW\_INPUT2&&1==ROW\_INPUT3) //僅判斷S1按鍵,避免交叉影響 { Su16KeyCnt++; if(Su16KeyCnt>=KEY\_ENTER\_CONTINUITY\_TIME)//該時間是“單擊”與“連擊”的分界線 { Su16KeyCnt=0; //計時器清零,為即將來臨的計時做準備 Su8KeyStep=5; //S1按鍵進入有節奏的連續觸發 } } else //如果期間檢查到S1按鍵已經松手 { Su8KeyStep=1; //返回步驟1繼續掃描 Su8KeyLock=0; Su16KeyCnt=0; Su16KeyContinuityTime=KEY\_CONTINUITY\_INITIAL\_TIME; //動態時間閥值。重裝初始值。 Su8ColumnRecord++; if(Su8ColumnRecord>=3) { Su8ColumnRecord=0; } } break; case 5: //S1按鍵進入有節奏的連續觸發 if(0==ROW\_INPUT1&&1==ROW\_INPUT2&&1==ROW\_INPUT3) //僅判斷S1按鍵,避免交叉影響 { Su16KeyCnt++; if(Su16KeyCnt>=Su16KeyContinuityTime) //該時間是“剛開始不斷減小,最后不變” { Su16KeyCnt=0; //清零,為了繼續連擊。 vGu8KeySec=1; //觸發一次S1按鍵 vGu8ShieldVoiceFlag=1; //因為連擊,把當前按鍵觸發的聲音屏蔽掉 if(Su16KeyContinuityTime>=KEY\_SUB\_DT\_TIME) { //Su16KeyContinuityTime數值不斷被減小,按鍵的觸發速度就不斷變快 Su16KeyContinuityTime=Su16KeyContinuityTime-KEY\_SUB\_DT\_TIME;//變快節奏 } //最小間隔時間KEY\_CONTINUITY\_MIN\_TIME就是“高速勻速” if(Su16KeyContinuityTime<KEY\_CONTINUITY\_MIN\_TIME) { //最后以KEY\_CONTINUITY\_MIN\_TIME時間為最高速進行“勻速” Su16KeyContinuityTime=KEY\_CONTINUITY\_MIN\_TIME; } } } else //如果期間檢查到S1按鍵已經松手 { Su8KeyStep=1; //返回步驟1繼續掃描 Su8KeyLock=0; Su16KeyCnt=0; Su16KeyContinuityTime=KEY\_CONTINUITY\_INITIAL\_TIME; //動態時間閥值。重裝初始值。 Su8ColumnRecord++; if(Su8ColumnRecord>=3) { Su8ColumnRecord=0; } } break; /\*---------S9按鍵的專屬區----------------\*/ case 6: if(1==ROW\_INPUT1&&1==ROW\_INPUT2&&0==ROW\_INPUT3) //僅判斷S9按鍵,避免交叉影響 { Su16KeyCnt++; if(Su16KeyCnt>=KEY\_ENTER\_CONTINUITY\_TIME)//該時間是“單擊”與“連擊”的分界線 { Su16KeyCnt=0; //計時器清零,為即將來臨的計時做準備 Su8KeyStep=7; //S9按鍵進入有節奏的連續觸發 } } else //如果期間檢查到S9按鍵已經松手 { Su8KeyStep=1; //返回步驟1繼續掃描 Su8KeyLock=0; Su16KeyCnt=0; Su16KeyContinuityTime=KEY\_CONTINUITY\_INITIAL\_TIME; //動態時間閥值。重裝初始值。 Su8ColumnRecord++; if(Su8ColumnRecord>=3) { Su8ColumnRecord=0; } } break; case 7: //S9按鍵進入有節奏的連續觸發 if(1==ROW\_INPUT1&&1==ROW\_INPUT2&&0==ROW\_INPUT3) //僅判斷S9按鍵,避免交叉影響 { Su16KeyCnt++; if(Su16KeyCnt>=Su16KeyContinuityTime) //該時間是“剛開始不斷減小,最后不變” { Su16KeyCnt=0; //清零,為了繼續連擊。 vGu8KeySec=9; //觸發一次S9按鍵 vGu8ShieldVoiceFlag=1; //因為連擊,把當前按鍵觸發的聲音屏蔽掉 if(Su16KeyContinuityTime>=KEY\_SUB\_DT\_TIME) { //Su16KeyContinuityTime數值不斷被減小,按鍵的觸發速度就不斷變快 Su16KeyContinuityTime=Su16KeyContinuityTime-KEY\_SUB\_DT\_TIME;//變快節奏 } //最小間隔時間KEY\_CONTINUITY\_MIN\_TIME就是“高速勻速” if(Su16KeyContinuityTime<KEY\_CONTINUITY\_MIN\_TIME) { //最后以KEY\_CONTINUITY\_MIN\_TIME時間為最高速進行“勻速” Su16KeyContinuityTime=KEY\_CONTINUITY\_MIN\_TIME; } } } else //如果期間檢查到S9按鍵已經松手 { Su8KeyStep=1; //返回步驟1繼續掃描 Su8KeyLock=0; Su16KeyCnt=0; Su16KeyContinuityTime=KEY\_CONTINUITY\_INITIAL\_TIME; //動態時間閥值。重裝初始值。 Su8ColumnRecord++; if(Su8ColumnRecord>=3) { Su8ColumnRecord=0; } } break; } } void KeyTask(void) { if(0==vGu8KeySec) { return; } switch(vGu8KeySec) { case 1: //S1按鍵的任務 if(Gu16SetData>0) { Gu16SetData--; //“設置參數” Gu8DisplayUpdate=1; //刷新顯示 } if(0==vGu8ShieldVoiceFlag) //聲音沒有被屏蔽 { vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; } vGu8ShieldVoiceFlag=0; //及時把屏蔽標志清零,避免平時正常的單擊聲音也被淹沒。 vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一致觸發 break; case 9: //S9按鍵的任務 if(Gu16SetData<800) { Gu16SetData++; //“設置參數” Gu8DisplayUpdate=1; //刷新顯示 } if(0==vGu8ShieldVoiceFlag) //聲音沒有被屏蔽 { vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; } vGu8ShieldVoiceFlag=0; //及時把屏蔽標志清零,避免平時正常的單擊聲音也被淹沒。 vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一致觸發 break; default: 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>

                              哎呀哎呀视频在线观看