#include
#include
#include
#include
#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit LCDEN=P3^4;
sbit RS=P3^5;
sbit RW=P3^6;
sbit BF=P0^7;
sbit BEEP=P1^0;
uchar str[17];
uchar code keyval[]=”789/456*123-c0=+”; //按键对应的符号
void delay(unsigned int xms)
{
int i,j;
for(i=xms;i>0;i–)
for(j=110;j>0;j–);
}
uchar keypad4_4()//按键扫描函数:要去抖,若有按键按下,返回对应的按键值(0-15),没有按键按下返回16
{
uchar i,row,temp;
uchar key=16;//按键号,初值设置为16,目的是:没有按键按下时返回16;
//若不设初值(默认值为0),没有按键按下时,将返回0,会误认为0被按下
row=0xef; //从第一列开始
for(i=0;i<4;i++)
{
P2=0xff;
P2=row; //第i列信号,对应列为低,其他全为高
row=_crol_(row,1); //生成下一列信号
temp=P2; //读入扫描信号
temp=temp&0x0f; //屏蔽高4位列信号,只保留低4位行信号
if(temp!=0x0f)//有按键被按下,因为第i列某行有按键按下,则低4位中有一位为低
{
delay(20); //延时去抖
temp=P2;
temp=temp&0x0f;
if(temp!=0x0f) //再次确认有按键被按下
{
switch(temp) //根据低4位行信号,判断哪个按键被按下
{
case 0x0e:key=0+i;break; //第i列第1行按键被按下
case 0x0d:key=4+i;break; //第i列第2行按键被按下
case 0x0b:key=8+i;break; //第i列第3行按键被按下
case 0x07:key=12+i; //第i列第4行按键被按下
}
do
{
temp=P2; //再次扫描按键
temp=temp&0x0f;
}while(temp!=0x0f); //等待按键释放
}
}
}
return(key);//扫面结束,返回按键值
}
uchar RdACAdr()//读当前光标地址
{
uchar result;
P2 = 0xff; //读地址前先置高电平,防止误判
RS = 0;
delay(5);
RW = 1;
LCDEN = 1;
delay(5);
result=P2&0x7f; //去掉最高位忙闲标记,只保留低7位地址值
LCDEN = 0;
return result;
}
uchar DectectBusyBit(void)//状态判断函数(忙/闲?)
{
bit result;
P0 = 0xff; //读状态前先置高电平,防止误判
RS = 0;
delay(5);
RW = 1;
LCDEN = 1;
delay(5);
result=BF; //若LCM忙,则反复测试,在此处原地踏步;当LCM闲时,才往下继续
LCDEN = 0;
return result;
}
void WrComLCD(unsigned char ComVal)//写命令函数
{
while(DectectBusyBit()==1); //先检测LCM是否空闲
RS = 0;
delay(1);
RW = 0;
LCDEN = 1;
P0 = ComVal;
delay(1);
LCDEN = 0;
}
void WrDatLCD(uchar DatVal)//写数据函数
{
while(DectectBusyBit()==1);
RS = 1;
delay(1);
RW = 0;
LCDEN = 1;
P0 = DatVal;
delay(1);
LCDEN = 0;
}
void WrStrDat(uchar *p)//显示英文字符串(长度不超过32)
{
uchar i=0,t;
while(p[i]!=’\0′)
{
WrDatLCD(p[i]);
i++;
delay(5);
t=RdACAdr();
if(t==0x10) WrComLCD(0xc0);//读当前坐标,如果第1行写完换行到第2行
if(t==0x50) WrComLCD(0x80);//读当前坐标,如果第2行写完换行到第1行
}
}
void LCD_Init(void)//1602初始化函数
{
//delay(15);
WrComLCD(0x38);
//delay(5); // 功能设定:16*2行、5*7点阵、8位数据接口
WrComLCD(0x38);
//delay(5);
WrComLCD(0x38);
//多次重复设定功能指令,因为LCD启动后并不知道使用的是4位数据接口还是8位的,所以开始时总是默认为4位,这样刚开始写入功能设定指令时,低4位被忽略,为了可靠,最好多写几遍该指令
WrComLCD(0x01); // 清屏
WrComLCD(0x06); // 光标自增、屏幕不动
delay(1); // 延时,等待上面的指令生效,下面再显示,防止出现乱码
WrComLCD(0x0C); // 开显示、关光标
}
double str2num(uchar* str)
{
uint i=0,j=0,index=0;
uchar ch[10];
long a1=atol(str),b1=0;
double a2=atof(str),b2=0,c=0;
for(i=0;str[i]!=’\0′;i++)
{
if(!isalnum(str[i]))
{
index=i;
break;
}
}
for(j=0,i=index+1;i<=strlen(str);i++)
ch[j++]=str[i];
b1=atol(ch);
b2=atof(ch);
switch(str[index])
{
case ‘+’:c=a1+b1;break;
case ‘-‘:c=a1-b1;break;
case ‘*’:c=a2*b2;break;
case ‘/’:c=a2/b2;break;
default:c=a2;break;
}
return c;
}
void main()
{
uchar i=0,j=0,y=16;
uchar flag=0;
uchar end=0;
LCD_Init();
delay(5); //延时,等待初始化完成
WrComLCD(0x80); //设置显示地址第一行第一位:0X00(0x80+0x00)
delay(1);
WrComLCD(0xc0);
delay(1);
WrDatLCD(‘0’);
delay(1);
WrComLCD(0x80);
while(1)
{
y=keypad4_4();
if(y<16)
{
if(y!=12)
{
if(end==1)
{
end=0;
flag=0;
WrComLCD(0x01);
delay(1);
WrComLCD(0xc0);
delay(1);
WrDatLCD(‘0’);
delay(1);
WrComLCD(0x80);
}
str[strlen(str)]=keyval[y];
WrDatLCD(keyval[y]);
if(y==14)
{
uchar ch[17];
flag=1;
end=1;
str[strlen(str)]=’\0′;
WrComLCD(0xc0);
sprintf(ch,”%.2f”,str2num(str));
WrStrDat(ch);
for(i=0;i<17;i++)
str[i]=’\0′;
}
}
else
{
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………