1.聯(lián)系生活
按鍵的常用做法就像生活中的電磁爐那樣,按下電磁爐上的“+”鍵后馬上松開,發(fā)現(xiàn)電磁爐上的數(shù)就增加了。
現(xiàn)在我們打算用開發(fā)板像按電磁爐上的按鍵一樣,按一下燈被點亮,再按一次燈被熄滅這樣的來回切換燈的狀態(tài)的功能。
不過在講解實際運用之前我們還需來了解按鍵的抖動!
2.實際按鍵過程
我們之前所講的按鍵過程解析圖只是理想中的效果,真正的按鍵過程圖是這樣的
按鍵按下的前期,IO端口并不是馬上就接通地而處在穩(wěn)定狀態(tài)的,按鍵按下時,IO端口有短暫的時間接通地之后又松開了這么的一個來回的過程,這是自彈式按鍵本身的結構屬性,此處稱作按鍵抖動。
如果我們一直按著不放,這時IO端口就會處在一種很穩(wěn)定的接觸狀態(tài),當我們松開按鍵時也會產(chǎn)生彈起抖動,這種抖動持續(xù)時間一般少于10ms。
我們也知道,在上一講的實驗中,按鍵動作常速下“穩(wěn)定接觸狀態(tài)”也會持續(xù)在50ms,這個時候程序去讀取穩(wěn)定的狀態(tài)時是0,這樣就可以判斷是否按鍵已經(jīng)按下,按下了就執(zhí)行相應的程序功能。
3.軟件處理
所以我們在軟件上可以這樣處理,當程序檢測到上圖的A段時“if(KEY4==0)”滿足了條件,但是KEY4因為按鍵的抖動會在短時間里時而變?yōu)?時而變?yōu)?,所以我們在滿足第一個“if(KEY4==0)”條件的時候馬上做延時50ms,等待抖動過去,然后再次判斷此時的KEY4還是等于0嗎,是的話就執(zhí)行切換燈的狀態(tài)程序。
#include <reg52.h> sbit ADDR2 = P1^2; sbit ADDR1 = P1^1; sbit ADDR0 = P1^0; sbit ENLED = P1^4; sbit ADDR3 = P1^3; sbit LED2 = P0^0; sbit KEY4 = P2^7; void delay_ms(unsigned int x) { unsigned int i,j; if(x==1000) { for(i=0;i<19601;i++)//延時1s { for(j=5;j>0;j--); } } else while(x--)for(j=115;j>0;j--); } void main() { ADDR3 = 1;//使能三八譯碼器 ENLED = 0;// ADDR2 = 1;//************************** ADDR1 = 1;//讓三八譯碼器的IO6輸出低電平 ADDR0 = 0;//************************** P2 = 0xF7;//讓K4能具備有被拉低的條件先 while(1) { if(KEY4==0)//檢測到了A段 { delay_ms(50);//等待抖動過去 if(KEY4==0) //判斷此時是在哪個階段,如果在“穩(wěn)定接觸狀態(tài)”就執(zhí)行切換燈的亮滅,如果在I段就不滿足判斷條件 { LED2=!LED2; } } } }
4.作圖解析
對上訴代碼,我們作一下圖就會一目了然了
所以在整個按鍵的按下和松開的動作中看起來并沒有重復執(zhí)行點燈程序,這樣就達到了雖然完整的按鍵動作過程對CPU來說時間很長,但點燈程序只執(zhí)行一次而已的效果。
可是每個人的按鍵手速不同,我們發(fā)現(xiàn)如果按下的時間稍微長一點(沒松手),那么LED2就會閃爍,也就是“LED2=!LED2;”被多次執(zhí)行,要是刻意快速按下就松手,LED2沒反應,所以這樣的代碼是做不到普遍通用的。還有我們用50ms做延時太影響CPU的運行效率了,所以我們要引入“支持連按”和“不支持連按”的按鍵概念。
C語言網(wǎng)提供由在職研發(fā)工程師或ACM藍橋杯競賽優(yōu)秀選手錄制的視頻教程,并配有習題和答疑,點擊了解:
一點編程也不會寫的:零基礎C語言學練課程
解決困擾你多年的C語言疑難雜癥特性的C語言進階課程
從零到寫出一個爬蟲的Python編程課程
只會語法寫不出代碼?手把手帶你寫100個編程真題的編程百練課程
信息學奧賽或C++選手的 必學C++課程
藍橋杯ACM、信息學奧賽的必學課程:算法競賽課入門課程
手把手講解近五年真題的藍橋杯輔導課程