编号: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

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐