基于51单片机的简易计算器(源程序+Proteus仿真)
本设计由89C52单片机+4*4矩阵键盘+液晶1602模块+声光报警电路1、主控制器是89C52单片机2、能进行加减乘除(+-x/)的基本运算,四位数以内。3、具有二次方、三次方及开方功能4、按按键会有声音提示,液晶1602显示数据5、运算结果保留后4位。
·
编号:69
基于51单片机的简易计算器设计
功能描述:
本设计由89C52单片机+4*4矩阵键盘+液晶1602模块+声光报警电路
1、主控制器是89C52单片机
2、能进行加减乘除(+-x/)的基本运算,四位数以内。
3、具有二次方、三次方及开方功能
4、按按键会有声音提示,液晶1602显示数据
5、运算结果保留后4位
视频演示链接:
69、基于51单片机的简易计算器
仿真图:


程序源码:
#include "reg52.h"
#include "intrins.h"
#include "lcd1602.h"
#include "key.h"
#include "delay.h"
#include "math.h"
#include "string.h"
#include "stdio.h"
sbit Beep=P3^7;
float num1; //第一操作数num1 (初始为零)
float num2; //第二操作数num2 (初始为零)
char sqrt_flag; //开方键按下标志 sqrt_flag
char yun_flag='+'; //运算符号 yun_flag (默认为+ )
unsigned long pos_flag=1; //小数位权pos_flag (默认为1)
char len; //小数点后位数
unsigned char l=0; //输入长度限制
char data c_num1[15]=" ";//c_num1 字符型第一操作数 (数组不定义大小与其他变量冲突)
char data c_num2[15]=" ";//c_num2 字符型第二操作数
//char data c_num1[7]=" ";//c_num1 字符型第一操作数 (数组不定义大小与其他变量冲突)
//char data c_num2[7]=" ";//c_num2 字符型第二操作数
char error; //运算法则错误;
char key_last; //上次按键状态标志 key_last 按键标志
char neg_flag; //正负标志 neg_flag
char sec_flag; //平方标志 neg_flag
char third_flag; //三次方标志 neg_flag
/******************************************************************/
/* 写入字节函数 */
/******************************************************************/
void ShowChar(unsigned char pos,unsigned char c)
{
unsigned char p;
if (pos>=0x10)
p=pos+0xb0; //是第二行则命令代码高4位为0xc
else
p=pos+0x80; //是第二行则命令代码高4位为0x8
Lcd1602_Write_Com (p);//写命令
Lcd1602_Write_Data (c); //写数据
}
/******************************************************************/
/* 写入字符串函数 */
/******************************************************************/
void ShowString (unsigned char line,char *ptr)
{
unsigned char l,i;
l=line<<4;
for (i=0;*(ptr+i)!='\0';i++)
ShowChar (l++,*(ptr+i));//循环显示16个字符
}
void float_to_char(float a,char* p)
{
char i,flag,length;
flag=0;
sprintf(p,"%f",a);
length=strlen (p);
for(i=0;i<length;i++)
{
if(*(p+i)=='.')flag=1;
}
if(flag==1)
for(i=length-1;i>=0;i--)
{
if(*(p+i)=='.'){*(p+i)='\0';break;}
if(*(p+i)!='0'){*(p+i+1)='\0';break;}
}
}
/**********************更新液晶*************************/
void refresh()//更新液晶
{
char length,i,j;
char dot;
dot=0;
float_to_char(num2,c_num2);//num2转为字符型
length=strlen(c_num2);
for(i=0,j=0;i<length;i++)
{
if(c_num2[i]=='.')
dot=1;
if(dot==1)
j++;
}
if(j<len)
{
if(dot==1)
{
for(i=length;i<(length+len-j);i++)
{
c_num2[i]='0';
}
c_num2[i]='\0';
}
else
{
c_num2[length]='.';
if(len-j>1)
{
for(i=length+1;i<(length+len-j);i++)
c_num2[i]='0';
}
c_num2[length+len-j]='\0';
}
}
if(neg_flag==1)//'+/-'按下首位加‘-’
{
length=strlen(c_num2);//计算c_num2长度
for(i=length-1;i>=0;i--)
{
c_num2[i+1]=c_num2[i];
}
c_num2[length+1]='\0';
c_num2[0]='-';
}
if(sqrt_flag==1)
{
length=strlen(c_num2);//计算c_num2长度
for(i=length-1;i>=0;i--)
{
c_num2[i+1]=c_num2[i];
}
c_num2[length+1]='\0';
c_num2[0]=0xe8;//字符根号
}
if(sec_flag==1)
{
length=strlen(c_num2);//计算c_num2长度
for(i=length-1;i>=0;i--)
{
c_num2[i+1]=c_num2[i];
}
c_num2[length+1]='\0';
c_num2[0]='^';//字符根号
}
if(third_flag==1)
{
length=strlen(c_num2);//计算c_num2长度
for(i=length-1;i>=0;i--)
{
c_num2[i+1]=c_num2[i];
}
c_num2[length+1]='\0';
c_num2[0]='#';//字符根号
}
if(error==0)
{
float_to_char(num1,c_num1);//num1转为字符型
Lcd1602_Write_Com(0x01); //显示清屏
ShowString(0,c_num1);
ShowString(1,c_num2);
ShowChar(15,yun_flag);
}
else
{
Lcd1602_Write_Com(0x01); //显示清屏
ShowString(0,"error!!!");
}
}
//键值处理
void operation1(char keynum)//按下 ’+、-、*、/处理
{
if(key_last==1)//上次按键为 数字、小数点、+/-、sqrt
{
if(neg_flag==1)num2=-num2; //'+/-'按下
if(sqrt_flag==1) //sqrt按下
{
if(num2>=0)
num2=sqrt(num2);
else
error=1;
}
if(sec_flag==1) //平方按下
{
if(num2>=0)
num2=num2*num2;
else
error=1;
}
if(third_flag==1) //平方按下
{
if(num2>=0)
// num2=pow(num2,3);
num2=num2*num2*num2;
else
error=1;
}
if(yun_flag=='+')num1=num1+num2; //按下的是‘+’
if(yun_flag=='-')num1=num1-num2 ; //按下的是‘-’
if(yun_flag=='*')num1=num1*num2; //按下的是‘*’
if(yun_flag=='/') //按下的是‘/’
{
if(num2!=0)
num1=num1/num2;
else
error=1;
}
num2=0; //num2清零
sqrt_flag=0; //sqrt_flag清零
sec_flag=0; //平方清零
third_flag=0;
neg_flag=0; //neg_flag清零
pos_flag=1; //pos_flag回1
}
if(keynum==4)yun_flag='+';//yun_flag更新
if(keynum==8)yun_flag='-';
if(keynum==12)yun_flag='*';
if(keynum==16)yun_flag='/';
len=0;
l = 0;
key_last=0; //key_last更新
refresh(); //刷新显示 暂时不管
}
void operation2(char keynum)//输入数字
{
float Data1;
if(keynum==1)Data1=7; //分析输入数字
if(keynum==2)Data1=8;
if(keynum==3)Data1=9;
if(keynum==5)Data1=4;
if(keynum==6)Data1=5;
if(keynum==7)Data1=6;
if(keynum==9)Data1=1;
if(keynum==10)Data1=2;
if(keynum==11)Data1=3;
if(keynum==13)Data1=0;
if(pos_flag==1) //更新num2
{
if(l<7)
num2=num2*10+Data1;
l++;
}
else
{
num2=num2+(Data1/pos_flag);
pos_flag=pos_flag*10;
len++;
}
key_last=1;//更新key_last
refresh();
}
void operation3() //输入小数点
{
if(pos_flag==1)//首次出现小数点
{
pos_flag=pos_flag*10;//小数位权*10
len++;
}
key_last=1; //更新key_last
refresh(); //更新液晶
}
/////////////////////////////////////////////////////
void operation4() //输入'='
{
if(neg_flag==1)num2=-num2; //'+/-'按下
if(sqrt_flag==1) //sqrt按下
{
if(num2>=0)
num2=sqrt(num2);
else
error=1;
}
if(sec_flag==1) //sqrt按下
{
if(num2>=0)
num2=num2*num2;
else
error=1;
}
if(third_flag==1) //3次方按下
{
if(num2>=0)
// num2=pow(num2,3);
num2=num2*num2*num2;
else
error=1;
}
if(yun_flag=='+')num1=num1+num2; //按下的是‘+’
if(yun_flag=='-')num1=num1-num2; //按下的是‘-’
if(yun_flag=='*')num1=num1*num2; //按下的是‘*’
if(yun_flag=='/') //按下的是‘/’
{
if(num2!=0)
num1=num1/num2;
else
error=1;
}
num2=0; //num2清零
sqrt_flag=0; //sqrt_flag清零
sec_flag=0; //平方标志清零
third_flag=0; //三次方方标志清零
neg_flag=0; //neg_flag清零
pos_flag=1; //pos_flag回1
yun_flag='+'; //yun_flag更新
len=0;
key_last=0; //key_last更新
refresh();
}
void operation5()//输入clear all
{
num1=0; // num1清零
num2=0; //num2清零
sqrt_flag=0; //清sqrt_flag
sec_flag=0; //平方标志清零
third_flag=0; //平方标志清零
neg_flag=0; // 清neg_flag
pos_flag=1; // Pos_flag=1
yun_flag='+'; // yun_flag(为'+')
error=0; //清error
len=0;
key_last=0; //更新key_flag
l = 0;
refresh(); //更新液晶
}
void operation6()//输入'C' 平方
{
// num2=0; //num2清零
// sqrt_flag=0; //清sqrt_flag
// neg_flag=0; //清neg_flag
// pos_flag=1; //pos_flag=1
// len=0;
// key_last=0; //key_last
// refresh(); //更新液晶 。
if(sec_flag==0) //sec_flag反转
sec_flag=1;
else
sec_flag=0;
key_last=1; //更新key_last
refresh(); //更新液晶
}
void operation7()//输入'+/-'
{
// if(neg_flag==0) //neg_flag反转
// neg_flag=1;
// else
// neg_flag=0;
// key_last=1; //key_last
// refresh(); // 更新液晶
if(third_flag==0) //third_flag反转
third_flag=1;
else
third_flag=0;
key_last=1; //更新key_last
refresh(); //更新液晶
}
void operation8()//输入'sqrt'
{
if(sqrt_flag==0) //sqrt_flag反转
sqrt_flag=1;
else
sqrt_flag=0;
key_last=1; //更新key_last
refresh(); //更新液晶
}
//键值分析
void key(char keynum)
{
Beep = 0;
delay_ms(100);
Beep = 1;
switch(keynum)
{
case 4 :
case 8 :
case 12:
case 16://+、-、*、/ 如果是加减运算符号
{
if(error==0)
operation1(keynum); //按下 ’+、-、*、/处理
break;
}
case 1 : //数字7
case 2 : //数字8
case 3 : //数字9
case 5 : //数字4
case 6 : //数字5
case 7 : //数字6
case 9 : //数字1
case 10 : //数字2
case 11 : //数字3
case 13 : //数字0
{ //如果是数字
if(error==0)
operation2(keynum);
break;
}
case 14 ://小数点
{
if(error==0)
operation3();
break;}
case 15 :// '='
{
if(error==0)
operation4();
break;}
case 17 :// clear all
{
operation5();
break;}
case 18 :// 'C' //改为平方
{
if(error==0)
operation6();
break;}
case 19 :// '+/-'
{
if(error==0)
operation7();
break;}
case 20 ://sqrt
{
if(error==0)
operation8();
break;}
}
}
软件免费下载地址:
1、Proteus仿真软件
文件内容:Proteus7.8安装包、Proteus8.6安装包、Proteus.8.10安装包、Proteus Professional 8.11 SP0安装包
链接:https://pan.baidu.com/s/11LNUZ9BJXWvXf1C4dPc3_w
提取码:2756
2、KEIL4 C51软件安装包
链接:https://pan.baidu.com/s/1CTZBqDsPsyIbjCIjI_birA
提取码:sy2a
文件下载:
69、基于51单片机的简易计算器
链接: https://pan.baidu.com/s/1i4VxBoUutCQ4ULtquvv6Pg?pwd=1234
提取码: 1234
更多推荐



所有评论(0)