蓝桥杯单片机开发板的独立按键和矩阵按键用的时候根据题目要求二选一,开发板上有个跳线帽,用到哪个连哪个。同样这里也摒弃了使用延时和死循环,采用定时器扫描按键状态,避免浪费CPU运行时间。
先以独立按键为例(其实独立按键和矩阵按键都一样,原理相同)
使用独立按键需要用跳线帽连接原理图2、3两端,开发板也有文字说明。
unsigned char Key(void)
{
unsigned char KeyNumber=0;
if(P33==0){KeyNumber=4;}
if(P32==0){KeyNumber=5;}
if(P31==0){KeyNumber=6;}
if(P30==0){KeyNumber=7;}
return KeyNumber;
}
void Key_Deal(void)
{
unsigned char Key_Temp,Key_Down=0;
static unsigned char Key_Old=0;
Key_Temp=Key();
Key_Down=Key_Temp&(Key_Temp^Key_Old);
Key_Old=Key_Temp;
}
void Timer1_Init(void) //2ms@12.000MHz
{
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x30; //设置定时初始值
TH1 = 0xF8; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA=1;
}
void Timer1_Isr(void) interrupt 3 //2ms进入一次
{
static unsigned int Count_1=0;
Count_1++;
if(Count_1>=5) //10ms扫描一次
{
Count_1=0;
Key_Deal(); //这里可以设置一个标志位,避免在中断执行太多代码了,我这里为了方便就不
改了
}
}
这里面的核心就是这个函数
void Key_Deal(void)
{
unsigned char Key_Temp,Key_Down=0;
static unsigned char Key_Old=0;
Key_Temp=Key();
Key_Down=Key_Temp&(Key_Temp^Key_Old);
Key_Old=Key_Temp;
}
我们来详细分析一下:
Key_Temp=Key(); //每10ms读取一次按键状态,并将它赋值给Key_Temp
Key_Down=Key_Temp&(Key_Temp^Key_Old); //这是最关键的一行代码,一个按位与,一个按位异或。(& 两个都为1,才为1,否则为0;^ 相同为0,不同为1) Key_Old=Key_Temp; //Key_Old为静态局部变量,离开函数,值仍保留:数据存储在静态存储区,在程序整个运行期间都不释放,且只能在该函数中调用。将这次读取到的临时按键值Key_Temp
更新到Key_Old
中,作为下一次的旧的按键值;
注意!!!!!!!!!!!!!!
如果我们要使用哪个按键就判断Key_Down的状态,注意Key_Down是局部变量,判断Key_Down不要放在函数外面!