按鍵掃描消抖經典算法實現以及Proteus實例仿真對比
- unsigned char Trg;
- unsigned char Cont;
- void KeyRead( void )
- {
- unsigned char ReadData = P1^0xff; // 注解1
- Trg = ReadData & (ReadData ^ Cont); // 注解2
- Cont = ReadData; // 注解3
- }
復制代碼- Trg(triger) 代表的是觸發,Cont(continue)代表的是連續按下。
- 注解1:讀P1的端口數據,取反,然后送到ReadData 臨時變量里面保存起來。
- 注解2:用來計算觸發變量的。一個位與操作,一個異或操作,我想學過C語言都應該懂吧?Trg為全局變量,其它程序可以直接引用。
- 注解3:用來計算連續變量。
- 上述實現算法不僅適用于端口以總線方式來讀取判斷,也同樣適用于獨立IO口信號的判斷和處理,具體實現函數如下:
- unsigned char Trg;
- unsigned char Cont;
- void KeyRead( void )
- {
- unsigned char ReadData = P10^0x01; //
- Trg = ReadData & (ReadData ^ Cont); //
- Cont = ReadData; /
- }
復制代碼
- 1. 沒有按鍵的時候
- 沒有按下時,IO口為高電平,就是P10為0x01,ReadData讀端口并且和0x01進行取反,很顯然,P10^0x01的值就是 0x00。
- Trg = ReadData & (ReadData ^ Cont); (初始狀態下,Cont也是為0的)很簡單的數學計算,因為ReadData為0,則它和任何數“相與”,結果也是為0。
- Cont = ReadData; 保存Cont 其實就是等于ReadData為0。
2. 第一次IO口按鍵按下的情況:- 端口沒有觸發時,IO口狀態為0x01,ReadData讀端口并且取反,很顯然,就是 0x01 。
- Trg = ReadData & (ReadData ^ Cont); 因為這是第一次按下,所以Cont是上次的值,應為為0。那么這個式子的值也不難算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01。
- Cont = ReadData = 0x01;
- ReadData = 0x01;
- Trg = 0x01;//Trg只會在這個時候對應位的值為1,其它時候都為0
- Cont = 0x01;<span style="background-color: rgb(255, 255, 255); color: rgb(79, 79, 79); font-family: "PingFang SC", "Microsoft YaHei", SimHei, Arial, SimSun; font-weight: normal;"></span>
復制代碼
3. IO口按鍵按著不松(長按鍵)的情況:- 端口數據為0xfe,ReadData讀端口并且取反是 0x01 。
- Trg = ReadData & (ReadData ^ Cont); 因為這是連續按下,所以Cont是上次的值,應為為0x01。那么這個式子就變成了 Trg = 0x01 & (0x01^0x01) = 0x00
Cont = ReadData = 0x01;- ReadData = 0x01;
- Trg = 0x00;
- Cont = 0x01;
復制代碼 因為現在按鍵是長按著,所以MCU會每個一定時間(20ms左右)不斷的執行這個函數,那么下次執行的時候情況會是怎么樣的呢?
- ReadData = 0x01;這個不會變,因為按鍵沒有松開.
- Trg = ReadData & (ReadData ^ Cont) = 0x01 & (0x01 ^ 0x01) = 0 ,只要按鍵沒有松開,這個Trg值永遠為 0.
- Cont = 0x01;只要按鍵沒有松開,這個值永遠是0x0.
4. 按鍵松開的情況:端口數據為0xff,ReadData讀端口并且取反是 0x00 。
- Trg = ReadData & (ReadData ^ Cont) = 0x00 & (0x00^0x01) = 0x00;
- Cont = ReadData = 0x00;
- ReadData = 0x00;
- Trg = 0x00;
- Cont = 0x00;
復制代碼 回到了初始狀態,也就是沒有按鍵按下的狀態.
Proteus仿真
trr.gif (207.95 KB, 下載次數: 83)
下載附件
2021-9-10 13:36 上傳
- 代碼:
- #include <REGX52.H>
- #include <intrins.h>
- sbit KeyValue=P3^7;
- unsigned char code segment[]= {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
- //定義數碼管顯示0~9
- unsigned char Trg;
- unsigned char Cont;
- static char count=1;
- void KeyRead( void )
- {
- unsigned char ReadData = KeyValue^0x01; // 注解1
- Trg = ReadData & (ReadData ^ Cont); // 注解2
- Cont = ReadData; // 注解3
-
- }
- void main() {
- P3=0XFF;
- P0=segment[0]; //開始運行顯示0
- while(1) {
- KeyRead();
- if(Trg==1) {
- P0=segment[count];
- count++;
- if(count>=10) { //超過0~9,數碼管顯示回到0
- count=0;
- }
- }
- }
- }
- //void main() {//這是沒有經過消抖處理的代碼
- // P3=0XFF;
- // P0=segment[0]; //開始運行顯示0
- // while(1) {
- //
- // if(KeyValue==0) {
- // P0=segment[count];
- // count++;
- // if(count>=10) { //超過0~9,數碼管顯示回到0
- // count=0;
- // }
- // }
- // }
- //}
復制代碼 - 這種算法摒棄了使用延時的常規做法。
- 仿真文件和程序建附件
trr02.gif (171.07 KB, 下載次數: 94)
下載附件
2021-9-10 13:39 上傳
51hei.png (12.55 KB, 下載次數: 92)
下載附件
2021-9-10 16:53 上傳
全部資料51hei附件下載:
按鍵掃描消抖算法實現.zip
(61.47 KB, 下載次數: 33)
2021-9-10 13:49 上傳
點擊文件名下載附件
按鍵掃描消抖算法 下載積分: 黑幣 -5
|