我們在學習51單片機用按鍵控制LED的時候,通常會遇到按鍵抖動的問題,這是因爲按鍵裏面內置彈簧片,不能夠精確的控制,下面是其原理圖(Powered by AxGlyph):
可以看到我們在按下按鍵的時候電平並沒有立馬變成低電平,而是有一個彈簧的抖動,所以我們要設計一個程序來抵消這個抖動,思路如下:
當按下按鍵的時候,我們先檢測一次是否真的爲低電平然後延時一小段時間,大概是5ms。
你們可能覺得5ms很少,但對於單片機來說,5ms是非常長的,我的單片機的晶振是11.0592MHZ,所以機器時鐘週期是晶振的倒數,1/11.0592MHZ,大概是1us,這是每條C語句執行的大概時間,當然更精確的可以通過外接示波器通過50%的佔空比來測量,所以我們延時5ms大概能夠自信5*1000條C語句,這對於單片機來說是非常長的,這一點一定不要忽略。
然後再次檢測是否真的爲低電平,若是,那就執行相應的操作。
所以整理完思路,我們的執行流程如下:
一般消除抖動有兩種方法:
- 硬件
- 程序
但是用硬件還要增加電容等一系列配套設備,增加了成本,所以我們採用程序控制
這是一個簡單的點亮小燈的程序,並循環閃爍:
#include<reg52.h>
sbit LED = P0^4;//按位操作,定義使用的引腳
void delay();//函數聲明
void main()
{
while(1)
{
LED = 0;//點亮小燈
delay();//延時1s
LED = 1;//熄滅小燈
delay();//延時1s
}
}
void delay()
{
unsigned char i;
unsigned int j;
for(i = 0;i<183;i++)
{
for(j = 0;j<1000;j++)//延時1s
{
;
}
}
}
但是我們的延時描述是固定的,假如我們想修改小燈的閃爍時間還要重複對delay()函數進行修改,那樣太麻煩,所以我們可以向delay()函數傳遞參數,來自定義我們想要的時間,修改後的代碼如下:
#include<reg52.h>
sbit LED = P0^4;//按位操作,定義使用的引腳
void delay(unsigned int n);//函數聲明
void main()
{
while(1)
{
LED = 0;//點亮小燈
delay(1000);//延時1s
LED = 1;//熄滅小燈
delay(2000);//延時2s
}
}
void delay(unsigned int n)
{
unsigned char i;
unsigned int j;
for(i = 0;i<183;i++)
{
for(j = 0;j<n;j++)//延時任意輸入秒數
{
;
}
}
}
檢測按鍵是否按下:
if(KEY==0)//判斷按鍵KEY的值是否爲0
{
delay(5);//延時5ms
if(KEY==0)//再次判斷按鍵KEY的值是否爲0
{
LED = ~LED;//LED狀態取反,點亮小燈
}
}
判斷按鍵是否鬆開:
while(!KEY);//判斷按鍵是否鬆開
按鍵重複檢測(循環):
while(1)
{
if(KEY==0)//判斷按鍵KEY的值是否爲0
{
delay(5);//延時5ms
if(KEY==0)//再次判斷按鍵KEY的值是否爲0
{
LED = ~LED;//LED狀態取反,點亮小燈
}
while(!KEY);//判斷按鍵是否鬆開
}
}
按鍵控制LED燈代碼(簡單版本):
/*
* @Author: 王雲龍
* @Date: 2020-02-23 12:48:51
* @Last Modified by: 王雲龍
* @Last Modified time: 2020-02-23 12:48:51
*/
#include<reg52.h>
sbit KEY = p3^4;
sbit LED = P0^7;//按位操作,定義使用的引腳
void delay(unsigned int n)//函數聲明
void main()
{
while(1)
{
if(KEY==0)//判斷按鍵KEY的值是否爲0
{
delay(5);//延時5ms
if(KEY==0)//再次判斷按鍵KEY的值是否爲0
{
LED = ~LED;//LED狀態取反,點亮小燈
}
while(!KEY);//判斷按鍵是否鬆開
}
}
}
void delay(unsigned int n)
{
unsigned char i;
unsigned int j;
for(i = 0;i<183;i++)
{
for(j = 0;j<n;j++)//延時任意輸入秒數
{
;
}
}
}