<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之旅 廣告
                **【100.1** **“行列掃描式”矩陣按鍵。】** ![](https://img.kancloud.cn/89/70/8970513a066fe0726b2997dcb0329ce0_194x190.png) 上圖100.1.1 有源蜂鳴器電路 ![](https://img.kancloud.cn/c1/8a/c18ad9232965b2a0699e388df49ac7b9_341x221.png) 上圖100.1.2 3\*3矩陣按鍵的電路 寫程序,凡是出現“重復性、相似性”的代碼,都可以加入“循環,判斷,數組”這類語句對代碼進行壓縮優化。上一節講的矩陣按鍵,代碼是記流水賬式的,出現很多“重復性、相似性”的代碼,是沒有經過優化的“原始版”,本節的目的是對上一節的代碼進行優化,讓大家從中發現一些技巧。 多說一句,我一直認為,只要單片機容量夠,代碼多一點少一點并不重要,只要不影響運行效率就行。而且有時候,代碼寫多一點,可讀性非常強,修改起來也非常方便。如果一味的追求壓縮代碼,就會刻意用很多“循環,判斷,數組”等元素,代碼雖然緊湊了,但是可分離性,可更改性,可閱讀性就沒那么強。因此,做項目的時候,某些代碼要不要進行壓縮,是沒有絕對標準的,能因敵而取勝者謂之神。 本節例程實現的功能:9個矩陣按鍵,每按下1個按鍵都觸發一次蜂鳴器鳴叫。 \#include "REG52.H" \#define KEY\_VOICE\_TIME 50 \#define KEY\_SHORT\_TIME 20 //按鍵去抖動的“濾波”時間 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); 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; volatile unsigned char vGu8KeySec=0; //按鍵的觸發序號 void main() { SystemInitial(); Delay(10000); PeripheralInitial(); while(1) { KeyTask(); //按鍵的任務函數 } } /\* 注釋一: \* 矩陣按鍵掃描的詳細過程: \* 先輸出某1列低電平,其它2列輸出高電平,延時等待2ms后(等此3列輸出同步穩定), \* 再分別判斷3行的輸入IO口, 如果發現哪一行是低電平,就說明對應的某個按鍵被觸發。 \* 依次循環切換輸出的3種狀態,并且分別判斷輸入的3行,就可以檢測完9個按鍵。矩陣按鍵的 \* 去抖動處理方法跟我前面講的獨立按鍵去抖動方法是一樣的,不再重復多講。 \*/ void KeyScan(void) //此函數放在定時中斷里每1ms掃描一次 { static unsigned char Su8KeyLock=0; static unsigned int Su16KeyCnt=0; static unsigned char Su8KeyStep=1; 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: //延時等待2ms后(等此3列輸出同步穩定)。不是按鍵的去抖動延時。 Su16KeyCnt++; if(Su16KeyCnt>=2) { Su16KeyCnt=0; Su8KeyStep++; //切換到下一個運行步驟 } break; case 3: if(1==ROW\_INPUT1&&1==ROW\_INPUT2&&1==ROW\_INPUT3) { Su8KeyStep=1; //如果沒有按鍵按下,返回到第一個運行步驟重新開始掃描!!!!!! Su8KeyLock=0; //按鍵自鎖標志清零 Su16KeyCnt=0; //按鍵去抖動延時計數器清零,此行非常巧妙 Su8ColumnRecord++; //輸出下一列 if(Su8ColumnRecord>=3) { Su8ColumnRecord=0; //依次輸出完第3列之后,繼續從第1列開始輸出低電平 } } else if(0==Su8KeyLock) //有按鍵按下,且是第一次觸發 { if(0==ROW\_INPUT1&&1==ROW\_INPUT2&&1==ROW\_INPUT3) { Su16KeyCnt++; //去抖動延時計數器 if(Su16KeyCnt>=KEY\_SHORT\_TIME) { Su16KeyCnt=0; Su8KeyLock=1;//自鎖置1,避免一直觸發,只有松開按鍵,此標志位才會被清零 if(0==Su8ColumnRecord) //第1列輸出低電平 { vGu8KeySec=1; //觸發1號鍵 對應S1鍵 } else if(1==Su8ColumnRecord) //第2列輸出低電平 { vGu8KeySec=2; //觸發2號鍵 對應S2鍵 } else if(2==Su8ColumnRecord) //第3列輸出低電平 { vGu8KeySec=3; //觸發3號鍵 對應S3鍵 } } } else if(1==ROW\_INPUT1&&0==ROW\_INPUT2&&1==ROW\_INPUT3) { Su16KeyCnt++; //去抖動延時計數器 if(Su16KeyCnt>=KEY\_SHORT\_TIME) { Su16KeyCnt=0; Su8KeyLock=1;//自鎖置1,避免一直觸發,只有松開按鍵,此標志位才會被清零 if(0==Su8ColumnRecord) //第1列輸出低電平 { vGu8KeySec=4; //觸發4號鍵 對應S4鍵 } else if(1==Su8ColumnRecord) //第2列輸出低電平 { vGu8KeySec=5; //觸發5號鍵 對應S5鍵 } else if(2==Su8ColumnRecord) //第3列輸出低電平 { vGu8KeySec=6; //觸發6號鍵 對應S6鍵 } } } else if(1==ROW\_INPUT1&&1==ROW\_INPUT2&&0==ROW\_INPUT3) { Su16KeyCnt++; //去抖動延時計數器 if(Su16KeyCnt>=KEY\_SHORT\_TIME) { Su16KeyCnt=0; Su8KeyLock=1;//自鎖置1,避免一直觸發,只有松開按鍵,此標志位才會被清零 if(0==Su8ColumnRecord) //第1列輸出低電平 { vGu8KeySec=7; //觸發7號鍵 對應S7鍵 } else if(1==Su8ColumnRecord) //第2列輸出低電平 { vGu8KeySec=8; //觸發8號鍵 對應S8鍵 } else if(2==Su8ColumnRecord) //第3列輸出低電平 { vGu8KeySec=9; //觸發9號鍵 對應S9鍵 } } } } break; } } void KeyTask(void) //按鍵任務函數,放在主函數內 { if(0==vGu8KeySec) { return; //按鍵的觸發序號是0意味著無按鍵觸發,直接退出當前函數,不執行此函數下面的代碼 } switch(vGu8KeySec) //根據不同的按鍵觸發序號執行對應的代碼 { case 1: //S1觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 2: //S2觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 3: //S3觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 4: //S4觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 5: //S5觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 6: //S6觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 7: //S7觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 8: //S8觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; vGu8KeySec=0; //響應按鍵服務處理程序后,按鍵編號必須清零,避免一直觸發 break; case 9: //S9觸發的任務 vGu8BeepTimerFlag=0; vGu16BeepTimerCnt=KEY\_VOICE\_TIME; //發出“嘀”一聲 vGu8BeepTimerFlag=1; 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>

                              哎呀哎呀视频在线观看