標題:
51微控制器入門:獨立按鍵(02)
一、獨立按鍵的基本結構和功能
二、獨立按鍵在微控制器的位置
三、初次使用獨立按鍵
設計第1個程式,使用按鍵K1控制D1的亮滅
#include<regx52.h>
void main()
{
while(1)
{
if(P3_1 == 0) // 按下按鈕相當於接地 P3_1 == 0;
{
P2_0 = 0; // 亮
}
else
{
P2_0 = 1; // 滅
}
}
}
解釋一下為什麼是P3_1==0,看原理圖可以發現按下後P3_1接地,此時為低電平,且此時P3_1為讀取值,所以等於零表示按下獨立按鍵
實現現象:
需要指出的是,由於Proteus軟體是在最理想的情況下模擬,完全消除了按鍵抖動的影響,所以這段簡單的程式碼無法有效實現單次點選後LED常亮或熄滅,關於按鍵抖動下面會介紹到。
四、新的知識點也是重點:抖動
在我們按下或鬆開“獨立按鍵”時,由於材料原因金屬彈片就會在極短的時間內上下波動,造成整個電路的頻繁開關。這段抖動時間極短,大約只有10ms(不會察覺到),但由於微控制器執行頻率都在兆赫茲,所以這種抖動可以被微控制器檢測到並做出反應,所以如果不消除抖動的影響就會造成按鍵“失靈”的現象。
抖動的消除:可以分成硬體消抖和軟體消抖(這些圖片都是在網上找到的,對於原作者在這裡表示感謝。)
硬體消抖原理:利用電容充/放電需要時間起到延時的作用消抖,這種方式也可以使用軟體來實現,下面將會介紹到。
當按下按鈕K1後電容開始放電,此時引腳KeyIn1檢測到的依然是高電平1,當電容放電結束「在這段時間中按鍵抖動已消除」KeyIn1接地導通檢測到低電平0;當鬆開按鈕K1後電容開始充電,此時引腳keyIn1檢測到的依然是低電平0,當電容充電結束「在這段時間中按鍵抖動已消除」KeyIn1接地導通檢測到高電平1。
軟體消抖原理:新增延時函式,在按鍵按下後延時一段時間(一般為20ms)跳過抖動。(重點)
這也是第2個程式:獨立按鍵控制LED狀態
#include<regx52.h> // 標頭檔案
void Delay(unsigned int n) //設定延時函式,實現軟體消抖,這個函式執行依次大約延時1ms
{
unsigned char j;
while(n--)
{
for(j = 0; j < 113; j++);
}
}
void main()
{
while(1)
{
if(P3_1 == 0)
{
Delay(20); //按下按鍵延時20ms消抖
while(P3_1 == 0); //如果按鍵持續按下,就進入這個迴圈直到鬆開,進入下面的延時函式
Delay(20); //鬆開按鍵延時20ms消抖
P2_0 = ~P2_0; //取反,實現按鍵控制LED狀態
}
}
}
實驗現象:
五、獨立按鍵控制LED燈顯示二進位制
第3個程式:
#include<regx52.h>
void Delay(unsigned int n) // 延時函式
{
unsigned char j;
while(n--)
{
for(j = 0; j < 113; j++);
}
}
void main()
{
unsigned char NUM = 0; //0000 0000 定義初始值
while(1)
{
if(P3_1 == 0)
{
Delay(20);
while(P3_1 == 0);
Delay(20);
NUM++; //舉例: 0000 0001 每次加1 實現二進位制 如下次為 0000 0010
P2 = ~NUM; //舉例: 1111 1110 將NUM取反變成 1111 1101 只點亮特定的LED
}
}
}
感覺上面說的不明白,在下面詳細解釋下:
// 首先定義無符號字元型變數NUM
// 將 NUM 賦初值為 0 換算為二進位制就為 0000 0000
// 進入 while 迴圈
// 按鍵按下 NUM + 1 此時NUM等於1 二進位制表示 0000 0001 取反 1111 1110 點亮D1
// 按鍵按下 NUM + 1 此時NUM等於2 二進位制表示 0000 0010 取反 1111 1101 點亮D2
// 按鍵按下 NUM + 1 此時NUM等於3 二進位制表示 0000 0011 取反 1111 1100 點亮D1、D2
// 依次類推……
// 按鍵按下 NUM + 1 此時NUM等於15 二進位制表示 1111 1111 取反 0000 0000 點亮D1、D2、D3、D4、D5、D6、D7、D8
// 按下按鍵 NUM + 1 此時NUM等於16 資料溢位 NUM等於0 開始重新計數
實驗現象:
六、獨立按鍵控制LED燈左右移動
這個部分需要重點介紹移位運算子,第4個程式:
#include<regx52.h>
void Delay(unsigned int n) // 延時函式
{
unsigned char j;
while(n--)
{
for(j = 0; j < 113; j++);
}
}
unsigned char LEDNum = 0; // 定義無符號字元型變數 LEDNum
void main()
{
P2_0 = 0; // 初始化,點亮第一個LED
while(1)
{
if(P3_0 == 0)
{
Delay(20);
while(P3_0 == 0); // 這部分都是按鍵操作,下面不再註釋
Delay(20);
LEDNum++; // 設定移位數
if(LEDNum >= 8) // 由於是從D1(不是D0)開始移位 LEDNum 等於 7 就是D8點亮,所以當LEDNum等於8時要使其制0歸位
LEDNum = 0; // LEDNum 置0
P2 = ~(0X01 << LEDNum); // << 左移位運算子 舉例: 0000 0001 << 2 就成為 0000 0100 取反 1111 1011
}
if(P3_1 == 0)
{
Delay(20);
while(P3_1 == 0); // 按鍵
Delay(20);
if(LEDNum == 0) // 由於LEDNum是無符合字元型,小於0時LEDNum會從1111 1111倒數,所以要防止其小於0置7,使D8點亮
LEDNum = 7;
else
LEDNum--; // LEDNum依次遞減
P2 = ~(0X01 << LEDNum); // << 左移位運算子 舉例: 0000 0001 << 7 就成為 1000 0000 取反 0111 1111
}
}
}
實驗現象: