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

📄 key205121.c

📁 由单片机89c2051模拟IIC和ZLG7290实现键盘的识别驱动程序。
💻 C
字号:
/*****************************************************************************************

Version2.1
电自院	校松华
2005.04.07

此程序是用AT89C2051来实现键盘电路,用其两个口P34、P35来模仿SPI总线,这样此键盘电路的接线就比较简单
这里借鉴两个MCU串行通信的思想,用电平判断来实现握手协议,
当键盘电路检测到有按键按下,CLK发一个下降沿去触发主机的中断,然后再发键值:
等待主机的回答,主机通过查询方式查询CLK位
是否为0,当查到为0是,就将DAT位置0,以示收到。
然后下位机就在CLK位的“护送”下,将键值通过DAT位送到主机。
主机也是通过CLK位的状态,将键值接受下来的
此版本是通过中断方式来实现按键功能的!

******************************************************************************************/
/******************************************************************************************
**版本号:Version3.0
**修改人:申红明
**日期:2006年12月8日10:28
**-----------------------------------------------------------------------------------------
**修改内容:(1)3*4键盘通过2051的P1.0~P1.7模拟SPI通信方式,从P3.4(CLK)、P3.5(DAT)口将数据送到
			EASYARM2100板的P0.13(CLK)和P0.11(DAT)。起初,2051的发送和ARM的接受一直无法实现同
			步,当本程序全速运行后,一直停在"while(DAT)"处,查看上位机ARM的程序发现问题:
			在上位机中有如下一段程序:
			    IO0DIR = (IO0DIR&~CLK) | DAT;		// DAT is output ,CLK is input				
				IO0CLR = DAT;	
				IO0DIR = IO0DIR & ~DAT;		// DAT is input
			问题出在第二句,在执行完第一句后,DAT变为了output,也许在此句之前,DAT是输入状态
			的高电平,那么等到执行第三句的时候,DAT又变成了高电平,也就是说,在输出口线上出现
			低电平的时间极短,下位机很难检测到。修改的方法是在上位机的ARM程序中,将第三句放到
			时钟脉冲的高电平后执行,也就是说,当CLK信号准备好的时候才开始采样DAT信号,将DAT
		    信号由输出置为输入;
			 (2)当本程的senddata()函数执行结束的时候,CLK变为了低电平,而上位机就是通过查询
			 CLK是否为低电平来判断有没有键按下,所以必须在发送键值函数senddate()执行结束后将CLK
			 拉高,所以在主程序的末尾加上了"CLK=1;DAT=1"这两句,成功实现了上下位机的同步数据传输。
*******************************************************************************************/
#include <reg51.h>
#include <stdio.h>
#define uchar unsigned char
#define uint unsigned int
#define CLK p34
#define DAT p35

sbit p30=P3^0;
sbit p31=P3^1;
sbit p32=P3^2;
sbit p33=P3^3;
sbit p34=P3^4;
sbit p35=P3^5;
sbit p36=P3^6;
sbit p37=P3^7;
sbit p20=P2^0;
sbit p21=P2^1;
sbit p22=P2^2;
sbit p23=P2^3;
sbit p24=P2^4;
sbit p25=P2^5;
sbit p26=P2^6;
sbit p27=P2^7;

uchar code keycode[12]={0x91,0xa1,0xc1,			//1,2,3
						0x92,0xa2,0xc2,			//4,5,6
						0x94,0xa4,0xc4,			//7,8,9
						0x98,0xa8,0xc8};		//*,0,#

void  delay(uint);
uchar scankey(void);
void  senddata(uchar);

void main(void)
	{
		uchar key;		
		uchar keyvalue=0;
		while(1)
			{	while((key=scankey())==0);
				if(key==keycode[0])		keyvalue=1;		//把键码转变为键值,注意‘*’,‘#’的键值!!!
				if(key==keycode[1])		keyvalue=2;
				if(key==keycode[2])		keyvalue=3;
				if(key==keycode[3])		keyvalue=4;
				if(key==keycode[4])		keyvalue=5;
				if(key==keycode[5])		keyvalue=6;
				if(key==keycode[6])		keyvalue=7;
				if(key==keycode[7])		keyvalue=8;
				if(key==keycode[8])		keyvalue=9;
				if(key==keycode[9])		keyvalue=0x0a;	//'*'键按下
				if(key==keycode[10])	keyvalue=0;		//'0'键按下
				if(key==keycode[11])	keyvalue=0x0b;	//'#'键按下	
				senddata(keyvalue);						//向上位机发送键值
			//	CLK=1;									//发送完毕,置位时钟信号
			//	DAT=1;
				}
	}
void delay(uint i)
	{
		for(i;i>0;i--){;}										//这个地方用i-而不用i++,看一下它的汇编就知道它的妙处!!!
 	}
uchar scankey(void)
	{
		uchar sccode,recode;
		P1=0xf0;
		if((P1&0xf0)!=0xf0)											//有键被按下吗?
			{	delay(5000);										//有则延时10MS
				if((P1&0xf0)!=0xf0)									//键是真的被按下了吗?
					{	sccode=0xfe;								//是则扫描键码。
						while((sccode&0x10)!=0)
						{	P1=sccode;
							if((P1&0xf0)!=0xf0)
								{	recode=(P1&0xf0)|0x0f;
									delay(5000);
				 					while((P1&0xf0)!=0xf0);
									return((~sccode)+(~recode));
								}
							else
							sccode=(sccode<<1)|0x01;
						}
					 }
				 delay(5000);
				 while((P1&0xf0)!=0xf0);							//键被放开了吗?没有则等待!!!
			}
		return (0);
	}	

void senddata(uchar	i)
	{	
		uchar j;
		CLK=1;							//发一个下降沿去触发主机的中断
		delay(2);
		CLK=0;
		delay(2);
							
		DAT=1;							//先发一个信号给ARM,告知有键被按下,并且开始发键值
		while(DAT);						//等待ARM的应答信号!!!	
		for(j=0;j<8;j++)
			{				
				if((bit)(i&0x80))	DAT=1;
					
				else				DAT=0;
					
				i<<=1;
				CLK=1;
				delay(50);				
				CLK=0;
				delay(50);				
			}	
			CLK=1;									//发送完毕,置位时钟信号
				DAT=1;
	}		

⌨️ 快捷键说明

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