#include<reg52.h>
#include<INTRINS.H>
#define uint unsigned int
#define uchar unsigned char
#define NOKEY 0xff
#define KEY_WOBBLE_TIME 500 //按键去抖动时间
#define KEY_OVER_TIME 15000 //等待进入连击时间(待定),该常数要比正常按键时间要长,防止非目的性进入连击模式
#define KEY_QUICK_TIME 1000 //等待按键抬起的连击时间(待定)
/*****************************************
LCD1602液晶接口
P2.0——RS
P2.1——RW
P2.2——EN
P1——DB0~DB7
—————————————
按键接口
p2.4 按键set
p2.5 按键add
p2.6 按键next
p2.7 按键esc
*****************************************/
sbit rs=P2^0; //YM1602C LCD的数据/指令选择控制线
sbit rw=P2^1; //YM1602C LCD的读写控制线
sbit en=P2^2; //YM1602C LCD的使能控制线
sbit keySET=P2^4; //按键set
sbit keyADD=P2^5; //按键add
sbit keyNEXT=P2^6; //按键next
sbit keyESC=P2^7; //按键esc
sbit buz1=P3^7; //音乐蜂鸣器高频控制口
sbit buz2=P3^5; //音乐蜂鸣器低频控制口
/*P1口接1602的D0~D7,注意不要接错了顺序。*/
/******定义函数******/
void Delay10us(); //延时10us函数
void Delay20us(); //延时20us函数
void Delay50us(); //延时20us函数
void delay_1ms(uint z); //延时1ms函数
void delay(uint n); //延时函数
void lcd_init(); //YM1602C LCD初始化函数
void lcd_wcom(uchar com); //YM1602C LCD写命令函数
void lcd_wdat(uchar dat); //YM1602C LCD写数据函数
void v_KeyInit_f(); //按键初始化(相应端口写1)
uchar ReadKey_f(); //按键读取扫描函数
uchar code table[]=”YM1602C Check Ok”; //要显示的内容1放入数组table
uchar code table1[]=”Ready Go”; //要显示的内容2放入数组table1
void Delay10us()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void Delay20us()
{
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
void Delay50us()
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void delay_1ms(uint z) //延时1ms函数
{
uint x,y;
for(x=z;z>0;x–)
for(y=920;y>0;y–);
}
void delay(uint n) //延时函数
{
uint x,y;
for(x=n;x>0;x–)
for(y=110;y>0;y–);
}
void lcd_init() //YM1602C LCD初始化函数
{
lcd_wcom(0x38); //8位数据,双列,5*7字形
lcd_wcom(0x0c); //开启显示屏,关光标,光标不闪烁
lcd_wcom(0x06); //显示地址递增,即写一个数据后,显示位置右移一位
lcd_wcom(0x01); //清屏
delay(5);
}
void lcd_wcom(uchar com) //YM1602C LCD写命令函数
{
P1=com; //把命令字送入P1
rs=0; //选择指令寄存器
rw=0; //选择写
delay(5); //延时一小会儿,让1602准备接收数据
en=1; //使能线电平变化,命令送入1602的8位数据口
en=0;
}
void lcd_wdat(uchar dat) //YM1602C LCD写数据函数
{
P1=dat; //把要显示的数据送入P1
rs=1; //选择数据寄存器
rw=0; //选择写
delay(5); //延时一小会儿,让1602准备接收数据
en=1; //使能线电平变化,数据送入1602的8位数据口
en=0;
}
void v_KeyInit_f()
{
//按键初始化(相应端口写1)
keySET=1; //按键set
keyADD=1; //按键add
keyNEXT=1; //按键next
keyESC=1; //按键esc
}
uchar ReadKey_f() //按键读取扫描函数
{
static uchar LastKey = NOKEY; //保存上一次的键值
static uint KeyCount = 0; //按键延时计数器
static uint KeyOverTime = KEY_OVER_TIME; //按键抬起时间
uchar KeyTemp = NOKEY ; //临时保存读到的键值
KeyTemp = P2 & 0xf0; //读键值
if( KeyTemp == 0xf0 )
{
KeyCount = 0;
KeyOverTime = KEY_OVER_TIME;
return NOKEY; //无键按下返回NOKEY
}
else
{
if( KeyTemp == LastKey ) //是否第一次按下
{
if(++KeyCount == KEY_WOBBLE_TIME ) //不是第一次按下,则判断抖动是否结?
{
return KeyTemp; //去抖动结束,返回键值
}
else
{
if( KeyCount > KeyOverTime )
{
KeyCount = 0;
KeyOverTime = KEY_QUICK_TIME;
}
return NOKEY;
}
}
else //是第一次按下则保存键值,以便下次执行此函数时与读到的键值作比较
{
LastKey = KeyTemp; //保存第一次读到的键值
KeyCount = 0; //延时计数器清零
KeyOverTime = KEY_OVER_TIME;
return NOKEY;
}
}
}
void main()
{
uchar n,m=0;
uchar KeyValue;
lcd_init(); //YM1602 LCD液晶初始化
lcd_wcom(0x80); //显示地址设为80H(即00H,)上排第一位
for(m=0;m<16;m++) //将table[]中的数据依次写入1602显示
{
lcd_wdat(table[m]);
delay(200);
}
lcd_wcom(0x80+0x44); //重新设定显示地址为0xc4,即下排第5位
for(n=0;n<8;n++) //将table1[]中的数据依次写入1602显示
{
lcd_wdat(table1[n]);
delay(200);
}
v_KeyInit_f(); //按键扫描初始化
while(1)
{
KeyValue = ReadKey_f();
if( KeyValue != NOKEY )
{
if( KeyValue == 0xe0 )
{
//table[]=”LCD1602 check ok”;
lcd_wcom(0x80);
for(m=0;m<16;m++)
{
lcd_wdat(‘r’);
delay(100);
}
for(m=0;m<20;m++)
{
buz1=0;
delay(1);
buz1=1;
delay(10);
buz1=0;
delay(20);
buz1=1;
delay(30);
}
}
if( KeyValue == 0xd0 )
{
lcd_wcom(0x80);
for(m=0;m<16;m++)
{
lcd_wdat(‘t’);
delay(100);
}
for(m=0;m<20;m++)
{
buz1=0;
delay(8);
buz1=1;
delay(10);
buz1=0;
delay(8);
buz1=1;
delay(10);
}
}
if( KeyValue == 0xb0 )
{
lcd_wcom(0x80);
for(m=0;m<16;m++)
{
lcd_wdat(‘c’);
delay(100);
}
for(m=0;m<20;m++)
{
buz1=0;
delay(10);
buz1=1;
delay(10);
buz1=0;
delay(10);
buz1=1;
delay(10);
}
}
if( KeyValue == 0x70 )
{
lcd_wcom(0x80);
for(m=0;m<16;m++)
{
lcd_wdat(‘y’);
delay(100);
}
for(m=0;m<200;m++)
{
buz1=0;
Delay10us();
buz1=1;
Delay20us();
buz1=0;
Delay50us();
buz1=1;
Delay10us();
buz1=0;
Delay10us();
buz1=1;
Delay20us();
buz1=0;
Delay20us();
buz1=1;
Delay10us();
}
}
}
else
{
//SHOW_ICON
//lcd_wcom(0x80);
//for(m=0;m<16;m++)
// {
// lcd_wdat(‘k’);
// delay(100);
// }
//KeyValue = ReadKey_f();
}
}
//while(1); //动态停机
}