大家好,這段時間又重新在學習51單片機,單片機這東東真的是要一直學,一直做項目才行,之前做按鍵和數碼管顯示的時候,實際也只是了解了一點皮毛,再次深入學習后才體會到,要搞好這東東,真的要不同的思路去擴展。先簡單說一下我的開發板硬件,數碼管采用兩片74HC573 來實現,段選P26,位選P27,采用共陽數碼管,在P0口送對應數來實現數碼管的顯示;
四個獨立按鍵P32,P33,P34,P35,LED發光管有八個,P10--P17,發光管在輸出低電平時點亮,
那么關于按鍵和數碼管的顯示,網上也有很多例子了。
第一類:關于延時的程序,如果采用延時消抖動,那么有可能按下后顯示不靈等,那么我建議用LED的顯示來抵消這個延時的做法,但一般項目的開法都不會用延時來消抖,在這里只是提供一個思路。
sbit KEY1 = P3^2; //假定P3^2代表KEY1鍵,按下為0
if(!KEY1 ) //表明有鍵按下
{
// Delayms(10); 一般情況下我們都用Delay 10ms 來消抖
為了程序的效率,和顯示等,我們這里可以用數碼管顯示的時間來抵消,
ledscan(); //數碼管一般也以10MS 100HZ無閃爍設計的。
if(!KEY1 )
{
while(!KEY1) //釋放消抖
{
KEY1 = 1; //先輸出高電平
ledscan(); //在等待的這個時間來顯示
}
// fun1(); 這里是我們按鍵按下的功能程序
}
}
第二類,我們直接以10MS定時器查詢來實現,也可以采用定時器2MS,多讀數幾次,比如8次以上都是,則實現按鍵確認
unsigned char KeySta[1] = //該定義屬于全局變量
{
0xff
};
//下面定義在定時器查詢程序里面
static unsigned char Keybuf[1] = //按鍵掃描緩沖區,保存一段時間內的掃描值
{
0xFF
};
Keybuf[0] = (Keybuf[0]<< 1) | KEY1; //KEY1 循環8次
if( Keybuf[0] ==0) //連續8次都是0
{
KeySta[0] = 0 ; //0表示有按下
}
else if( Keybuf[0] ==1) ///連續8次都是1
{
KeySta[0] = 1 ;
}
else //未穩定狀態,則不管他,這里是為了程序的完整性
{
}
}
第三類:采用狀態機的寫法
狀態機也是按10MS定時中斷去確認按鍵狀態,以使程序簡化
unsigned char keycode = 0; //這個是全局變量,表示按鍵代碼
//下面在定時中斷10MS到的函數中實現
static unsigned char Key_state = 0;
unsigned char Keypress = 0xff; //未按下為0xff;
P3 = 0xff;
Keypress &= P3
switch(Key_state )
{
case 0:
if(Keypress!=0xff)//表示有鍵按下
{
Key_state = 1;//進入S1
}
break;
case 1:
if(Keypress!=0xff) //表示確認有鍵按下
{
Key_state = 2;//進入S1
if( !KEY )
{
keycode = 0x01; //假如說我們KEY1按下的代碼是0x01
}
}
else
{
Key_state = 0; //誤動作,返回0
}
break;
case 2:
if(Keypress==0xff) //釋放
{
switch(keycode)
{
case 0x01: //按鍵KEY1的功能函數
break;
default:
break;
}
Key_state = 0; //如果有長按,則可以進入長按的狀態等等。
}
else //等待釋放
{
Key_state = 2;
}
default:
break;
}
當然為了減輕定時中斷的負擔,關于按鍵功能的程序可在主程序中去執行,在此不再詳述。
第四次:新型的TRG的寫法
核心算法如下: unsigned char Trg;
unsigned char Cont;
void KeyRead( void )
{
unsigned char ReadData =P3^0xff; // 1
Trg = ReadData & (ReadData ^Cont); // 2
Cont = ReadData; // 3
}
在定時中斷函數里每10MS去檢測一次按鍵情況,并執行。
|