⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 l_key.c

📁 键盘扫描主要用于各种的扫描,是一个良好的程序
💻 C
字号:
/*键盘程序,本程序涉及到外中断,定时器中断,比较复杂,耐心学,帮助了解中断事件*/

#include <reg51.h>
#include <intrins.h>


sbit SPK=P3^4;		//SPK定义为P3口的第4位,就是驱动蜂鸣器的那个脚
sbit JDQ=P3^5;		//JDQ定义为P3口的第5位,就是驱动继电器的那个脚

code unsigned char table[]=
			{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
			0x77,0x7c,0x39,0x5e,0x79,0x71};
			//共阴数码管 0-9 a-f 表

code unsigned char key_tab[17]={0xed,0x7e,0x7d,0x7b,
				0xbe,0xbd,0xbb,0xde,
				0xdd,0xdb,0x77,0xb7,
				0xee,0xd7,0xeb,0xe7,0XFF};//========================此数组为键盘编码,
															//本人采用类式类似电话按键的编码方式,方便以后设计
				//	1	2	3	a			0x01 0x02 0x03 0x0a
				//	4	5	6	b	对应16进制码:	0x04 0x05 0x06 0x0b
				//	7	8	9	e			0x07 0x08 0x09 0x0e
				//	*	0	#	f			0x0c 0x00 0x0e 0x0f
				//打个比方,如果你按下0键,P0口读到数据为0xed
				//如果你按下2键,P0口读到数据为0x7d,按下9键为0xdb,
				//我们将读到的P0口数据经过查表法就能得到相应的16进制码
					
				//键盘的读取,我们采用中断法,电路用一个4与门(74HC21)接入
				//中断口(INT0),利用中断来扫描键盘矩阵,读取数据

unsigned char l_tmpdate[8]={0,0,0,0,0,0,0,0};//定义数组变量
unsigned char l_key=0x0;					//定义变量,存放键值	
unsigned char l_keyold=0xFF;	//做为按键松开否的凭证				

void ReadKey(void);   //扫描键盘 获取键值
void delay();//延时子函数,5个空指令
void display(unsigned char *lp,unsigned char lc);//数字的显示函数;lp为指向数组的地址,lc为显示的个数
													//这个函数在第二节用过不用再说了吧!


void main(void)     //入口函数
{
	EA=1;			//首先开启总中断
	EX0=1;  		//开启外部中断 0
	IT0=1;        // 设置成 下降沿触发方式
	P0=0xf0;		//P0口高位输高电平,经过74HC21四输入与门,连接外中断0,有键按下调用中断函数
	while(1){
		display(&l_key,1);			//输出获取的键值码

		if(l_key==0x0e)				//这里我们检测是否按了0x0e键,
			JDQ=0;					//是,我们就驱动继电器打开
		if(l_key==0x0c)				//检测是否按下了0x0c键,
			JDQ=1;					//是,我们就驱动继电器断开
	}
}

void key_scan()   interrupt 0    //外部中断 0  0的优先级最高 							
{	
	EX0=0;					//在读键盘期间,我们关闭中断,防止干扰带来的多次中断

							//为了消除抖动带来的干扰,在按下键后我们采用延时十多毫秒再读取键值
								//如果采用循环语句来延时,比如(for,while。。。)会使CPU处理循环而占用
								//系统资源,所以这里我们采用定时器中断法,让定时器等待十多毫秒触发定时器
								//中断,这里用到定时器0

	TMOD&=0XF1;				//设置定时器0为模式1方式,
	TH0=0X2E;				//设置初值,为12毫秒
	TL0=0X00;
	ET0=1;					//开启定时器中断0
	TR0=1;					//启动定时器计数	
} 
void timer0_isr(void) interrupt 1	//定时器0的中断函数
{	
	TR0=0;						//中断后我们停止计数
	ReadKey();					//定时器计数12毫秒后产生中断,调用此函数,读取键值
}
void ReadKey(void)						//读键盘值
{
	unsigned char i,j,key;
	j=0xfe;
	key=0xff;			//设定初值
	for (i=0;i<4;i++){		
		P0=j;				//P0口低4位循环输出0,扫描键盘
		//leday();
		if ((P0&0xf0)!=0xf0){	//如果有键按下,P0口高4位不会为1,									
			key=P0;				//读取P0口,退出循环,否则循环下次
			break;		
		}
		j=_crol_(j,1);			//此函数功能为左循环移位
	}
	if (key==0xff){				//如果读取不到P0口的值,比如是干扰,我们不做键值处理,返回
		l_keyold=0xff;
		//l_key=0xff;
		P0=0xf0;			//恢复P0口,等待按键按下
		EX0=1;					//返回之前,开启外中断
		SPK=1;
		return;
	}
	SPK=0;					//有键按下,我们驱动蜂鸣器响
	if(l_keyold==key){		//检测按键放开否,如果一样表明没放开,
		TH0=0X2E;			//我们继续启动定时器,检测按键松开否
		TL0=0;
		TR0=1;		
	   	return;
	}		
	TH0=0X2E;			
	TL0=0;
	TR0=1;					//我们继续启动定时器,检测按键松开否

	l_keyold=key;			//获取键码做为放开的凭证

	for(i=0;i<17;i++){			//查表获得相应的16进制值存放l_key变量中
		if (key==key_tab[i]){
			l_key=i;
			break;
		}
	}
			//程序运行到这里,就表明有键值被读取存放于l_key变量中,主程序就可以检测此变量做相应外理,
			//此时我们回到主程序
}  
void display(unsigned char *lp,unsigned char lc)//显示
{
	unsigned char i;		//定义变量
	P2=0;					//端口2为输出
	P1=P1&0xF8;				//将P1口的前3位输出0,对应138译门输入脚,全0为第一位数码管
	for(i=0;i<lc;i++){		//循环显示
	P2=table[lp[i]];		//查表法得到要显示数字的数码段
	delay();				//延时5个空指令	
	if(i==7)				//检测显示完8位否,完成直接退出,不让P1口再加1,否则进位影响到第四位数据
		break;
	P2=0;					//清0端口,准备显示下位
	P1++;					//下一位数码管
	}
}
void delay(void)								//空5个指令
{
	_nop_();_nop_();_nop_();_nop_();_nop_();
}  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -