本程序用1602液晶显示按键。当某一键按下时,液晶上显示某键按下,松开时,显示某件松开!
本人QQ:379809083
有事请联系!
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit rs = P1^2;
sbit rw = P2^2;
sbit en = P1^1;
sbit close5730 = P2^6; //此两个I/O用于关闭数码管相应控制端,防止干扰,可以不用定义
sbit close5731 = P2^7;
#define lcd_data = P0
uchar key_value=16,key_down,temp;
/************************************************************
* 函数功能:延时函数
* 入口参数:延时时间
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void delay(uint a)
{
uint b;
for(;a>0;a--)
for(b=100;b>0;b--);
}
/************************************************************
* 函数功能:向1602液晶中写命令
* 入口参数:命令参数
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void lcd_wcom(uchar com)
{
P0=0xff;
en = 0;
rs = 0; //rs=0为命令操作
rw = 0; //rw=0为写
P0 = com;
en = 1;
delay(1);
en = 0;
delay(1);
P0=0xff;
}
/************************************************************
* 函数功能:向1602液晶中写数据
* 入口参数:数据
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void lcd_wdat(uchar dat)
{
P0=0xff;
en = 0;
rs = 1; //rs=0为数据操作
rw = 0; //rw=0为写
P0 = dat;
en = 1;
delay(1);
en = 0;
delay(1);
P0=0xff;
}
/************************************************************
* 函数功能:lcd1602液晶初始化
* 入口参数:无
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void InitLcd()
{
close5730 = 0;
close5731 = 0;
lcd_wcom(0x38); //设置16*2,5*8,8为数据口
lcd_wcom(0x08); //关显示,不显示光标
lcd_wcom(0x01); //清屏
lcd_wcom(0x06); //指针自动加1
lcd_wcom(0x0c); //开显示
}
/************************************************************
* 函数功能:向1602液晶中写一字符串
* 入口参数:要写的字符串
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void lcd_wword(uchar *s)
{
while(*s)
{
lcd_wdat(*s);
s++;
}
}
/************************************************************
* 函数功能:初始化定时器0,用于键盘扫描,每5ms扫描一次
* 入口参数:无
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void InitTimer0()
{
TMOD = 0x01;
TH0 = (65536-4608)/256; //11.0592晶振一个机器周期约1.085us
TL0 = (65536-4605)%256;
TR0 = 1; //开定时器0
ET0 = 1; //开定时器0中断
EA = 1; //开总中断
}
/************************************************************
* 函数功能:扫描按键值,并显示在液晶上
* 入口参数:无
* 返 回:无
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void key_scan()
{
lcd_wcom(0x80+0x40);
lcd_wword(" Key ");
lcd_wdat(0x30+key_value/10);
lcd_wdat(0x30+key_value%10);
if(key_down==1)
lcd_wword(" Down! ");
if(key_down==0)
lcd_wword(" Up! ");
}
void main()
{
InitLcd();
InitTimer0();
lcd_wcom(0x82);
lcd_wword("KeyBoard Test");
lcd_wcom(0x80+0x40);
lcd_wword("Please Press Key");
while(1)
{
if(key_value!=16)
{
key_scan();
}
}
}
/************************************************************
* 函数功能: 定时器0中断函数,用于扫描键盘一次
* 入口参数: 无
* 返 回: 扫描按键结果
* 备 注: By Vivien Luo 2010-06-25
************************************************************/
void timer0() interrupt 1 //每5ms中断一次
{
TH0 = (65536-4608)/256;
TL0 = (65536-4605)%256;
temp = 0;
P3 = 0x0f;
if(P3!=0x0f)
{
temp=P3;
P3 = 0xf0;
if(P3!=0xf0)
{
key_down = 1;
temp = temp|P3;
switch(temp)
{
case 0xee: key_value=0;break;
case 0xde: key_value=1;break;
case 0xbe: key_value=2;break;
case 0x7e: key_value=3;break;
case 0xed: key_value=4;break;
case 0xdd: key_value=5;break;
case 0xbd: key_value=6;break;
case 0x7d: key_value=7;break;
case 0xeb: key_value=8;break;
case 0xdb: key_value=9;break;
case 0xbb: key_value=10;break;
case 0x7b: key_value=11;break;
case 0xe7: key_value=12;break;
case 0xd7: key_value=13;break;
case 0xb7: key_value=14;break;
case 0x77: key_value=15;break;
default:break;
}
}
}
if(temp==0) key_down = 0; //如果没有键按下,key_down为0
P3=0xff; //释放P3口
}