在STC89C52RC中,键盘接口分为独立式按键和矩阵式键盘。如果项目中需要的交互较少,使用独立式键盘即可;如果输入参数较多,比方说打印机什么的,功能复杂的系统,则需要采用矩阵式键盘进行输入控制。

     键盘的可靠输入要考虑两个方面的问题:

  1.      去抖动:目前的单片机键盘按键均为机械式触点,由于触点的机械弹性效应,在按键闭合和断开的时候,接触点的电压并不是立即变化,而是会出现抖动。根据按键的不同机械特性,抖动的时间长短不等,大致在5ms~20ms。
  2.      一次按键处理:当键盘按下之后,相应的按键编码以高电平的方式输入到单片机的I/O接口。按键闭合是有一定时间的。一般来说的,大致是0.1us~0.5us。因为单片机的执行速度很快,如果处理不当,就有可能一次按键操作被执行多次。

     一般来说,硬件解决以上两个问题比较复杂,成本也高,而软件处理择简单实用。软件处理的方法是:当程序检测到有键按下时,执行一个10ms的延时程序,然后再监测一次,看是否该键仍然闭合。如果仍然闭合择可以确认确实有键按下,从而可以消除抖动的影响。

  单片机对键盘的输入检测可以有查询和中断两种方式。查询适合用于一般用途的程序;中断适合一些较为复杂的单片机系统。

      在程序中,对键盘的处理包括以下几个方面:

  •       检测按键是否按下;
  •       如果检测到按键被按下,可以执行软件去抖动,消除抖动的影响;
  •       准确判断是哪个按键被按下;
  •       转向相应的程序处理子程序

1、独立式按键实验

/*************************************************************************
用实验板上的独立按键K1、K2、K3和K4这四个按键控制8位红色LED灯,按一下K1,L1
亮,其他灯都不亮;按一下K2,L3亮,其他灯都不亮;按一下K3,L5亮,其他灯都不
亮;按一下K4,L7亮,其他灯都不亮。
*************************************************************************/
#include<reg52.h>
sbit K1=P1^0;			   //位定义P1.0引脚为K1
sbit K2=P1^1;			   //位定义P1.1引脚为K2
sbit K3=P1^2;			   //位定义P1.2引脚为K3
sbit K4=P1^3;			   //位定义P1.3引脚为K4
char key_scan();		   //声明返回值为char型的独立按键检索函数key_scan()   
void display(char a);	   //声明无返回值的显示函数display()
void delay(unsigned int z);	//声明延时函数

/*主函数开始*/
void main()
{
	 while(1)	           //进入大循环					  
	 {
		display(key_scan());  //检索并显示
	 }
}

/*定义返回值为char型的独立按键检索函数*/
char key_scan()
{
	char i;				   //声明char型变量i,作为返回标志
	P1=0xff;			   //P1口全部置高电平,等待读取引脚数据
	if(K1==0)			   //判断是否K1键被按下
	{
		delay(20);		   //延时20ms,消抖
		if(K1==0)		   //再次确认按键K1是否真的被按下
		{
			while(!K1);	   //确认按键K1真的被按下后,等待松手
			delay(20);	   //延时20ms,消抖
			i=1;		   //返回标志为1
		}	
	}
	if(K2==0)			   //判断是否K2键被按下
	{					   
		delay(20);		   //延时20ms,消抖
		if(K2==0)		   //再次确认按键K2是否真的被按下
		{
			while(!K2);	   //确认按键K2真的被按下后,等待松手
			delay(20);	   //延时20ms,消抖
			i=2;		   //返回标志为2
		}	
	}
	if(K3==0)			   //判断是否K3键被按下
	{
		delay(20);		   //延时20ms,消抖
		if(K3==0)		   //再次确认按键K3是否真的被按下
		{
			while(!K3);	   //确认按键K3真的被按下后,等待松手
			delay(20);	   //延时20ms,消抖
			i=3;		   //返回标志为3
		}	
	}
	if(K4==0)			   //判断是否K4键被按下
	{
		delay(20);		   //延时20ms,消抖
		if(K4==0)		   //再次确认按键K4是否真的被按下
		{
			while(!K4);	   //确认按键K4真的被按下后,等待松手
			delay(20);	   //延时20ms,消抖
			i=4;		   //返回标志为4
		}	
	}
	return i;			   //返回char型变量i的值
}

/*定义显示函数*/
void display(char a)
{
	switch(a)			   //判断返回值对应的是哪一个键被按下
	{
		case 1:
			P0=0xfe;	   //K1键被按下,点亮L1灯
			break;
		case 2:
			P0=0xfb;	   //K2键被按下,点亮L2灯
			break;
		case 3:
			P0=0xef;	   //K3键被按下,点亮L3灯
			break;
		case 4:
			P0=0xbf;	   //K4键被按下,点亮L4灯
			break;
		default:
			P0=0xff;	   //其他状态时,所有灯都不亮
			break;
	}
}

/*定义延时函数*/
void delay(unsigned int z)
{
	unsigned int x,y;
	for(x=z;x>0;x--)
		for(y=110;y>0;y--);
}