51单片机LCD1602显示矩阵按键键值

矩阵按键原理图
51单片机LCD1602显示矩阵按键键值_第1张图片
矩阵按键怎么变成独立按键
方法一:
逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
方法二:
行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。

LCD显示部分可以参考我一篇文章
51单片机DS1302时钟LCD1602显示

以上是我在学习过程中的一点总结,用的是普中的51单片机·。

#include	
#define GPIO_KEY P1
#define LCD1602_DATAPINS P0

typedef	 unsigned int	  uint;
typedef unsigned char	 uchar;

unsigned char KeyValue;
//用来存放读取到的键值
unsigned char KeyState;
//用来存放按键状态
unsigned char PuZh[]=" Pechin Science ";
unsigned char dat[]="0123456789ABCDEF";

sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;

void DelayMs(unsigned int x);
void Delay10ms();   //延时50us
void KeyDown();		 //检测按键函数
void LcdInit();
void LcdWriteData(uchar dat);
void LcdWriteCom(uchar com);


void main(void)
{
	unsigned char i;
	LcdInit();
	KeyState=0;
	
	for(i=0;i<16;i++)
	{
//		LcdWriteCom(0x80);
		LcdWriteData(PuZh[i]);	
	}
	
	while(1)
	{
		KeyDown();
	 	LcdWriteCom(0xc0);
		LcdWriteData(dat[KeyValue]);

		/*
		if(KeyState==0)	//	 此处不能这样用,永远不变
		{

			KeyState=1;
			LcdWriteCom(0xc0);
			LcdWriteData(dat[KeyValue]);

		}
		*/
	}				
}

void KeyDown(void)
{
	char a;
	GPIO_KEY=0x0f;
	if(GPIO_KEY!=0x0f)
	{
		Delay10ms();
		if(GPIO_KEY!=0x0f)
		{
			KeyState=0;
			//测试列
			GPIO_KEY=0X0F;
// 			Delay10ms();
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=0;break;
				case(0X0b):	KeyValue=1;break;
				case(0X0d): KeyValue=2;break;
				case(0X0e):	KeyValue=3;break;
//				default:	KeyValue=17;	//检测出错回复17意思是把数码管全灭掉。
			}
			//测试行
			GPIO_KEY=0XF0;
			Delay10ms();
			switch(GPIO_KEY)
			{
				case(0X70):	KeyValue=KeyValue;break;
				case(0Xb0):	KeyValue=KeyValue+4;break;
				case(0Xd0): KeyValue=KeyValue+8;break;
				case(0Xe0):	KeyValue=KeyValue+12;break;
//				default:	KeyValue=17;
			}
			while((a<50)&&(GPIO_KEY!=0xf0))	 //检测按键松手检测
			{
				Delay10ms();
				a++;
			}
			a=0;
		}
	}
}

void Delay10ms(void)   //误差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}

void DelayMs(unsigned int x)   //0.14ms误差 0us
{
 unsigned char i;
  while(x--)
 {
  for (i = 0; i<13; i++)
 {}
 }
}


void LcdWriteCom(uchar com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令
	DelayMs(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	DelayMs(5);	  //保持时间
	LCD1602_E = 0;
}

void LcdWriteData(uchar dat)			//写入数据
{
	LCD1602_E = 0;	//使能清零
	LCD1602_RS = 1;	//选择输入数据
	LCD1602_RW = 0;	//选择写入

	LCD1602_DATAPINS = dat; //写入数据
	DelayMs(1);

	LCD1602_E = 1;   //写入时序
	DelayMs(5);   //保持时间
	LCD1602_E = 0;
}

void LcdInit()						  //LCD初始化子程序
{
 	LcdWriteCom(0x38);  //开显示
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}

你可能感兴趣的:(单片机学习)