LCD计算器设计
1.能实现加减乘除、幂次方、取根号等操作
2.数据结果能实现小数
3.使用LCD1602显示
4.个人代码还有bug
代码实现
#include"reg52.h"
#include"math.h"
/*********************************************************
lcd智能计算器
矩阵键盘显示:
1 2 3 4
5 6 7 8
9 0 * /
+ - . =
独立键盘:
^ sin ^1/2 clr
***********************************************************/
typedef unsigned int u16;
typedef unsigned char u8;
//
sbit lcd_wr=P2^5;
sbit lcd_rs=P2^6;
sbit lcd_en=P2^7;
sbit k1=P3^1;
sbit k2=P3^0;
sbit k3=P3^2;
sbit k4=P3^3;
u8 dat1[]={0,1,2,3,4,5,6,7,8,9,0x2b-0x30, 0x2d-0x30, 0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };
u8 tab2[]="zhad"; //字符串形式是能---直接显示的
#define dt P0
#define key P1
u8 keyvalue,flag,acc,dat[8],dds,k,fps;
u16 z1;
float x,y;
double z,z2;
void delay(int z){
int i,j;
for(i=z;i>0;i--){
for(j=110;j>0;j--){}
}
}
void write_com(u8 com){
lcd_wr=0;
lcd_rs=0;
lcd_en=0;
P0=com;
delay(5);
lcd_en=1;
delay(5);
lcd_en=0;
}
void write_data(u8 dta){
lcd_wr=0;
lcd_rs=1;
lcd_en=0;
P0=dta;
delay(5);
lcd_en=1;
delay(5);
lcd_en=0;
}
void lcd_init(){
write_com(0x38); //8位数据总线--显示两行
write_com(0x0c); //开显示--不显示光标
write_com(0x06); //屏幕不移动--光标右移
write_com(0x01); //初始化清屏
flag=0; //符号标志位{计算符}---{是加数还是被加数}
x=0;
y=0;
z=0;
acc=0; //操作符标符标志位
dds=0; //小数点标志位
fps=1; //小数点
}
void anjian(){
int i=0;
key=0x0f;
if(key!=0x0f){
delay(5);
key=0x0f;
if(key!=0x0f){
switch(key){
case(0x07):
keyvalue=1;break;
case(0x0b):
keyvalue=2;break;
case(0x0d):
keyvalue=3;break;
case(0x0e):
keyvalue=4;break;
}
key=0xf0;
switch(key){
case(0x70):
keyvalue=keyvalue;break;
case(0xb0):
keyvalue=keyvalue+4;break;
case(0xd0):
keyvalue=keyvalue+8;break;
case(0xe0):
keyvalue=keyvalue+12;break;
}
if(keyvalue==1 ||keyvalue==2 || keyvalue==3 || keyvalue==4 || keyvalue==5 || keyvalue==6 || keyvalue==7 || keyvalue==8 || keyvalue==9){
if(dds==0){
if(flag==0){
x=x*10+dat1[keyvalue];
}else{
y=y*10+dat1[keyvalue];
}
}else{
if(flag==0){
x=x+dat1[keyvalue]*pow(0.1,k);
k++;
fps=fps*0.1;
}else{
fps=fps*0.1;
y=y+(fps*dat1[keyvalue]);
}
}
write_data(0x30+dat1[keyvalue]);
}
if(keyvalue==10){
if(flag==0){
x=x*10+dat1[keyvalue];
}else{
y=y*10+dat1[keyvalue];
}
write_data(0x30+dat1[0]);
}
if(keyvalue==13){ //+
acc=1;
flag=1;
dds=0;
write_data(0x2b);
}
if(keyvalue==14){ //-
acc=2;
flag=1;
dds=0;
write_data(0x2d);
}
if(keyvalue==11){ //*
acc=3;
flag=1;
dds=0;
write_data(0x2a);
}
if(keyvalue==12){ //除
acc=4;
flag=1;
dds=0;
write_data(0x2f);
}
if(keyvalue==15){ //.
k=1;
dds=1;
fps=0.1;
write_data(0xa5);
}
/*
if(keyvalue==15){
write_com(0x01);
flag=0;
x=0;
y=0;
z=0;
acc=0;
}
*/
if(keyvalue==16){
switch(acc){
case(1):
z=x+y;break;
case(2):
z=x-y;break;
case(3):
z=x*y;break;
case(4):
z=x/y;break;
case(5):
y=(int)y;
z=pow(x,y);
break;
case(6):
z=sin(x);//不能实现
break;
case(7):
z=sqrt(x);
break;
case(8):
break;
}
z1=z/1;
z2=z-z1;
write_data(0x3d);//=号
write_com(0x80+0x40);
write_com(0x06);
//write_com(0x04);
while(z1!=0) //一位一位显示
{
dat[i]=z1%10;
//write_data(0x30+z1%10);//显示结果的最后一位在0x4f的位置
z1=z1/10;//取前面的结果数据
i=i+1;
}
i=i-1;
for(;i>-1;i--){
write_data(0x30+dat1[dat[i]]);
}
if(z2!=0){
write_data(0xa5);
}
while(z2!=0){
write_data(0x30+(int)(z2*10));
z2=(z2*10)-((int)(z2*10));
}
}
while(key!=0xf0){
delay(10);
}
}
}
if(k1==0){ //^
delay(10);
if(k1==0){
flag=1;
acc=5;
write_data(0x5e);
}
while(!k1);
}
if(k2==0){ //sin
delay(10);
if(k2==0){
//flag=1; 只有一个操作数不需要这个判断位
acc=6;
write_data(0x73);
write_data(0x69);
write_data(0x6e);
}
while(!k2);
}
if(k3==0){ //开方
delay(10);
if(k3==0){
acc=7;
write_data(0xe8);
}
while(!k3);
}
if(k4==0){ //转二进制--符号无语义---仅作为标识
delay(10);
if(k4==0){
acc=8;
write_data(0x7e);
write_com(0x01);
flag=0;
x=0;
y=0;
z=0;
acc=0;
dds=0;
fps=1;
}
while(!k4); //到按键释放才离开这里---不然在一秒钟多次扫描程序
}
}
void main(){
lcd_init();
write_com(0x80);
while(1){
anjian();
}
}