51单片机-第十节-独立按键及数码管优化
一、优化独立按键:
独立按键的实现中,为了解决抖动问题(在按下和抬起时,按键会在高低电平之间抖动10ms),我们在按下后Delay(20),随后进入循环,直到检测到按键抬起,再Delay(20),跳出循环。
(1)问题:
如果按住按键不抬,程序会停止在独立按键的函数中。
unsigned char Key()
{
unsigned char KeyNumber = 0;
if (P3_1 == 0) { Delay(20); while (P3_1 == 0); Delay(20); KeyNumber = 1; }
if (P3_0 == 0) { Delay(20); while (P3_0 == 0); Delay(20); KeyNumber = 2; }
if (P3_2 == 0) { Delay(20); while (P3_2 == 0); Delay(20); KeyNumber = 3; }
if (P3_3 == 0) { Delay(20); while (P3_3 == 0); Delay(20); KeyNumber = 4; }
//这里顺序是乱的,是单片机型号决定的
return KeyNumber;
}
(2)优化:
利用定时器,每隔20ms(跳过抖动)检测一次独立按键情况,当按键抬起再执行操作。
//获取独立按键键码,无按下时返回0
unsigned char Key()
{
unsigned char Temp;
Temp = Key_KeyNumber;
Key_KeyNumber = 0;
return Temp;
}
unsigned char Key_GetState()
{
unsigned char KeyNumber = 0;
if (P3_1 == 0) { KeyNumber = 1; }
if (P3_0 == 0) { KeyNumber = 2; }
if (P3_2 == 0) { KeyNumber = 3; }
if (P3_3 == 0) { KeyNumber = 4; }
//这里顺序是乱的,是单片机型号决定的
return KeyNumber;
}
unsigned char Key_KeyNumber;
//独立按键中断,必须将此函数放入main的中断函数中,且中断时长20ms
void Key_Loop()
{
static unsigned char NowState, LastState;
LastState = NowState;
NowState = Key_GetState();
if (LastState == 1 && NowState == 0) { Key_KeyNumber = 1; }
if (LastState == 2 && NowState == 0) { Key_KeyNumber = 2; }
if (LastState == 3 && NowState == 0) { Key_KeyNumber = 3; }
if (LastState == 4 && NowState == 0) { Key_KeyNumber = 4; }
}
中断函数:
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count1, T0Count2 = 0;
T0Count1++;
TH0 = 64535 / 256;
TL0 = 64535 % 256 + 1;
if (T0Count1 >= 20)
{
T0Count1 = 0;
//需执行的操作
Key_Loop();
}
}
二、优化数码管:
在实现数码管时, 我们实现了在指定位置显示指定数字,并在显示一下后清零。
(1)问题:
由于每次数码管显示只显示一下,因此当一次while循环的时间过长,会导致数码管帧率过低,发生闪烁现象。
//数码管,在指定位置(1-8)显示指定数字
void Nixie(unsigned char Location, int Number)
{
switch (Location)
{
case 1:P2_4 = 1; P2_3 = 1; P2_2 = 1; break;
case 2:P2_4 = 1; P2_3 = 1; P2_2 = 0; break;
case 3:P2_4 = 1; P2_3 = 0; P2_2 = 1; break;
case 4:P2_4 = 1; P2_3 = 0; P2_2 = 0; break;
case 5:P2_4 = 0; P2_3 = 1; P2_2 = 1; break;
case 6:P2_4 = 0; P2_3 = 1; P2_2 = 0; break;
case 7:P2_4 = 0; P2_3 = 0; P2_2 = 1; break;
case 8:P2_4 = 0; P2_3 = 0; P2_2 = 0; break;
}
unsigned char NixieTable[10] = { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F };
P0 = NixieTable[Number];
Delay(1);
P0 = 0x00;//显示一下后清零
}
(2)优化:
unsigned char Nixie_Buf[9] = { 0,10,10, 10, 10, 10, 10, 10, 10, };
void Nixie_SetBuf(unsigned char Location, unsigned char Number)
{
Nixie_Buf[Location] = Number;
}
//数码管,在指定位置(1-8)显示指定数字
void Nixie_Scan(unsigned char Location, int Number)
{
P0 = 0x00;//显示一下后清零
switch (Location)
{
case 1:P2_4 = 1; P2_3 = 1; P2_2 = 1; break;
case 2:P2_4 = 1; P2_3 = 1; P2_2 = 0; break;
case 3:P2_4 = 1; P2_3 = 0; P2_2 = 1; break;
case 4:P2_4 = 1; P2_3 = 0; P2_2 = 0; break;
case 5:P2_4 = 0; P2_3 = 1; P2_2 = 1; break;
case 6:P2_4 = 0; P2_3 = 1; P2_2 = 0; break;
case 7:P2_4 = 0; P2_3 = 0; P2_2 = 1; break;
case 8:P2_4 = 0; P2_3 = 0; P2_2 = 0; break;
}
unsigned char NixieTable[11] = { 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00 };
P0 = NixieTable[Number];
}
void Nixie_Loop()
{
static unsigned char i = 1;
Nixie_Scan(i,Nixie_Buf[i]);
i++;
if (i >= 9) i = 1;
}