用51单片机和lcd1602及矩阵键盘实现计算器功能

/*****************************************************************************
*标题: 通过lcd1602实现计算器功能 *
*作者:酷头 *
******************************************************************************

*****************************************************************************/
#include
#include
#define PORT P0
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define NULL 0
uint shuzu[4];
uchar dis_buf,x,fuhao;
uint ad=0,rt;
ulong date,date1,date2,pass;
void display();
void display1();
void calculate();
uchar a[9]={' ',' ',' ',' ',' ',' ',' ',' ',' '};
uchar code key_code[]={0xeb,0x77,0x7b,0x7d,0xb7,0xbb,0xbd,0xd7,0xdb,0xdd,
0x7e,0xbe,0xde,0xee,0xed,0xe7}; //4*4矩阵接键,分别显示0123456789ABCD#*
sbit EN=P2^7; //1602使能控制线
sbit RS=P2^6; //1602数据/指令选择控制线
sbit RW=P2^5; //1602读写控制线

/**延时处理程序,单位ms**/
void delayms (uint ms)
{
uint i;
while(ms--)
{
//for(i=0;i<112;i++) //11.0592M晶体
for(i=0;i<120;i++) //12M晶体
{;}
}
}

//*****lcd1602驱动******//
/**1602忙状态检测**/
void lcdbusy()
{
do{
EN=0;
RS=0;
RW=1;
PORT=0xff;
EN=1;
_nop_();
}
while(PORT&0x80);
EN=0;
}

/**1602写命令函数**/
void lcdwcmd(uchar cmd)
{
lcdbusy();
RS=0;
RW=0;
EN=1;
PORT=cmd;
EN=0;
}

/**1602写数据函数**/
void lcdwdata(uchar dat)
{
lcdbusy();
RS=1;
RW=0;
EN=1;
PORT=dat;
EN=0;
}

/**LCD数据指针位置程序**/
void lcdpos(bit x, uchar y)
{
if(x)lcdwcmd(y|0xc0); //x=1,第二行显示;x=0,第一行显示 0<=x<16
else lcdwcmd(y|0x80); //数据指针=80+地址码(00H~27H,40H~67H)
}

/**1602初使化**/
void lcdint()
{
lcdwcmd(0x38); //设置LCD为16X2显示,5X7点阵,八位数据接口
lcdwcmd(0x0c); //LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)
lcdwcmd(0x06); //LCD开显示及光标设置(光标不闪烁,不显示"_")
lcdwcmd(0x01); //清除LCD的显示内容
}

/**按键扫描程序**/
void keyscan()
{
uchar scan1,scan2,keycode,j,key;
P1=0xf0;
scan1=P1;
if(scan1!=0xf0)
{
delayms(100);
scan1=P1;
if(scan1!=0xf0)
{
P1=0xff;
P1=0x0f;
scan2=P1;
keycode=scan1|scan2;
for(j=0;j<16;j++)
{
if(keycode==key_code[j])
{
key=j;
dis_buf=key; //键值入显示缓存
dis_buf=dis_buf&0x0f;
if(dis_buf==10)dis_buf=dis_buf-15;
if(dis_buf==11)dis_buf=dis_buf-14;
if(dis_buf==12)dis_buf=dis_buf-18;
if(dis_buf==13)dis_buf=dis_buf-14;
if(dis_buf==14)dis_buf=dis_buf-1;
dis_buf=dis_buf+0x30;
P1=0xf0; //判断是否按键已经按下
while(P1!=0xf

0);
}
}
}
else dis_buf=240; // 没有按键按下的时候给dis_buf为240
}
}
/**********求 data1 和 data2 的十进制值*******/
void jisuan1()
{
date1=a[7]*10000000+a[6]*1000000+a[5]*100000+a[4]*10000+a[3]*1000+a[2]*100+a[1]*10+a[0];
}
void jisuan2()
{
date2=a[7]*10000000+a[6]*1000000+a[5]*100000+a[4]*10000+a[3]*1000+a[2]*100+a[1]*10+a[0];
}
/**********将 十进制数转化为字符串 *************/
void change()
{
pass=date;
if(pass==0)
a[0]=0;
for(rt=0;pass!=0;rt++)
{
a[rt]=pass%10;
pass/=10;
}

for(rt=0;rt<10;rt++)
{
switch(a[rt])
{
case 0:
a[rt]='0';break;
case 1:
a[rt]='1'; break;
case 2:
a[rt]='2'; break;
case 3:
a[rt]='3'; break;
case 4:
a[rt]='4'; break;
case 5:
a[rt]='5'; break;
case 6:
a[rt]='6'; break;
case 7:
a[rt]='7'; break;
case 8:
a[rt]='8'; break;
case 9:
a[rt]='9'; break;
default:
a[rt]=' ';
}
}

}

/**主函数**/


void main()
{
lcdint();
while(1)
{
keyscan();
if(dis_buf!=240) // 当有键按下的时候
{
x=x+1; // 每按下一次键更新一次显示
calculate();
// 数据的更新
if(ad==0)
{
if(x==2) {a[0]=dis_buf;a[1]=0x20;}
if(x==3) {a[1]=a[0];a[0]=dis_buf;}
if(x==4) {a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==5) {a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==6) {a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==7) {a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==8) {a[6]=a[5];a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==9) {a[7]=a[6];a[6]=a[5];a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
}
// 数据的更新
if(ad==1)
{
if(x==2) {a[0]=dis_buf;a[1]=0x20;}
if(x==3) {a[1]=a[0];a[0]=dis_buf;}
if(x==4) {a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==5) {a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==6) {a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==7) {a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==8) {a[6]=a[5];a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
if(x==9) {a[7]=a[6];a[6]=a[5];a[5]=a[4];a[4]=a[3];a[3]=a[2];a[2]=a[1];a[1]=a[0];a[0]=dis_buf;}
}

display();
dis_buf=240; // 执行完一次键值后重新给键值240
}
}
}
void calculate()
{
if(dis_buf==0x2b) //当按键的码值是0x7e(键盘上的a键)
{
lcdpos(1,0); // 则在下面一行的开始显示“+”
lcdwdata(0x2b);
display1(); // 上一组数据全部搬到上面一行显示
for(rt=0;rt<10;rt++)
{
switch(a[rt])
{
cas

e '0':
a[rt]=0;
break;
case '1':
a[rt]=1;break;
case '2':
a[rt]=2;break;
case '3':
a[rt]=3; break;
case '4':
a[rt]=4;break;
case '5':
a[rt]=5;break;
case '6':
a[rt]=6; break;
case '7':
a[rt]=7;break;
case '8':
a[rt]=8;break;
case '9':
a[rt]=9;break;
default:
a[rt]=0;
}
fuhao=1;

}
jisuan1();
for(rt=0;rt<10;rt++)
a[rt]=' ';
ad=1;
x=1;
}
if(dis_buf==0x2d) //------------------------
{
lcdpos(1,0); // 则在下面一行的开始显示“-”
lcdwdata(0x2d);
display1(); // 上一组数据全部搬到上面一行显示
for(rt=0;rt<10;rt++)
{
switch(a[rt])
{
case '0':
a[rt]=0;
break;
case '1':
a[rt]=1;break;
case '2':
a[rt]=2;break;
case '3':
a[rt]=3; break;
case '4':
a[rt]=4;break;
case '5':
a[rt]=5;break;
case '6':
a[rt]=6; break;
case '7':
a[rt]=7;break;
case '8':
a[rt]=8;break;
case '9':
a[rt]=9;break;
default:
a[rt]=0;
}
fuhao=2;
}
jisuan1();
for(rt=0;rt<10;rt++)
a[rt]=' ';
ad=1;
x=1;
}
if(dis_buf==0x2a) //********************************
{
lcdpos(1,0); // 则在下面一行的开始显示“*”
lcdwdata(0x2a);
display1(); // 上一组数据全部搬到上面一行显示
for(rt=0;rt<10;rt++)
{
switch(a[rt])
{
case '0':
a[rt]=0;
break;
case '1':
a[rt]=1;break;
case '2':
a[rt]=2;break;
case '3':
a[rt]=3; break;
case '4':
a[rt]=4;break;
case '5':
a[rt]=5;break;
case '6':
a[rt]=6; break;
case '7':
a[rt]=7;break;
case '8':
a[rt]=8;break;
case '9':
a[rt]=9;break;
default:
a[rt]=0;
}
fuhao=3;
}
jisuan1();
for(rt=0;rt<10;rt++)
a[rt]=' ';
ad=1;
x=1;
}
if(dis_buf==0x2f) // //////////////////
{
lcdpos(1,0); // 则在下面一行的开始显示“/”
lcdwdata(0x2f);
display1(); // 上一组数据全部搬到上面一行显示
for(rt=0;rt<10;rt++)
{
switch(a[rt])
{
case '0':
a[rt]=0;
break;
case '1':
a[rt]=1;break;
case '2':
a[rt]=2;break;
case '3':
a[rt]=3; break;
case '4':
a[rt]=4;break;
case '5':
a[rt]=5;break;
case '6':
a[rt]=6; break;
case '7':
a[rt]=7;break;
case '8':
a[rt]=8;break;
case '9':
a[rt]=9;break;
default:
a[rt]=0;
}
fuh

ao=4;
}
jisuan1();
for(rt=0;rt<10;rt++)
a[rt]=' ';
ad=1;
x=1;
}

if(dis_buf==0x3d) // 当按键的码值是0xed(键盘上的#键)
{
lcdpos(0,0); // 则在上面一行的开始显示“=”
lcdwdata(0x3d);
lcdpos(1,0);
lcdwdata(' ');
for(rt=0;rt<10;rt++)
{
switch(a[rt])
{
case '0':
a[rt]=0;break;
case '1':
a[rt]=1;break;
case '2':
a[rt]=2;break;
case '3':
a[rt]=3;break;
case '4':
a[rt]=4;break;
case '5':
a[rt]=5;break;
case '6':
a[rt]=6;break;
case '7':
a[rt]=7;break;
case '8':
a[rt]=8;break;
case '9':
a[rt]=9;break;
default:
a[rt]=0;break;
}

}
jisuan2();
switch(fuhao)
{
case 1:
date=date1+date2;
break;
case 2:
date=date1-date2;
break;
case 3:
date=date1*date2;
break;
case 4:
date=date1/date2;
break;
}
for(rt=0;rt<10;rt++)
a[rt]=' ';
change();
ad=2;
};

}
/**显示程序1(在1602下面一行显示)**/
void display()
{
lcdpos(1,15);
lcdwdata(a[0]);

lcdpos(1,14);
lcdwdata(a[1]);

lcdpos(1,13);
lcdwdata(a[2]);

lcdpos(1,12);
lcdwdata(a[3]);

lcdpos(1,11);
lcdwdata(a[4]);

lcdpos(1,10);
lcdwdata(a[5]);

lcdpos(1,9);
lcdwdata(a[6]);

lcdpos(1,8);
lcdwdata(a[7]);




}
/**显示程序2(在上面一行显示)**/
void display1()
{
lcdpos(0,15);
lcdwdata(a[0]);

lcdpos(0,14);
lcdwdata(a[1]);

lcdpos(0,13);
lcdwdata(a[2]);

lcdpos(0,12);
lcdwdata(a[3]);

lcdpos(0,11);
lcdwdata(a[4]);

lcdpos(0,10);
lcdwdata(a[5]);

lcdpos(0,9);
lcdwdata(a[6]);

lcdpos(0,8);
lcdwdata(a[7]);



}


相关文档
最新文档