基于单片机的计算器设计—可小数、负数、13位乘法运算

基于单片机的计算器设计

(仿真+程序+原理图+PCB+设计报告)

功能介绍

具体功能:

1.采用LCD1602液晶显示;

2.4*4矩阵按键输入,共16个按键;

3.能够计算加减乘除,以及带小数和负数运算;

4.最大运算:9999999999999*9999999999999,结果以指数形式显示;

​演示视频:

基于单片机的计算器设计—可小数、负数、13位乘法运算

添加图片注释,不超过 140 字(可选)

程序

#include "reg52.h"
/***微信公众号:木子单片机********/
#include <stdlib.h>        //包含atof(),字符串->实数
#include <stdio.h>         //包含sprintf(),实数->字符串
#include <string.h>        //包含strcpy(),字符串复制
#include <math.h>		   //数学函数头文件
#define uchar unsigned char
#define uint unsigned int
/*************lcd****************/
sbit lcdrs=P3^7;           //LCD控制脚
sbit lcdrw=P3^6;
sbit lcden=P3^5;
bit idata form;            //lcd显示方式切换
uchar idata state;         //lcd状态字存储

bit idata eqsign;          //按等号标志
bit idata press;           //键按标志
bit idata savesign;        //可存储结果标志
bit idata sc;			   //复用标志
uchar idata process[30],proc; //记忆计算过程
uchar idata continu=0;        //连续计算运算符号存储
uchar idata pai[2][2];        //π 前有数据标志
uchar idata ferror;        //计算检错标志					 
uchar idata ywei;		   //屏幕移位
uchar idata count=0;       //输入计数
uchar idata count_num=0;   //组号计数
uchar idata result[15];    //计算结果立存,save
uchar idata saveresult[15];//存储结果数组, sc+save
uchar idata jieguo[15];    //结果字符串
uchar idata bdate[2][14];  //待计算字符串二维组
uchar idata on_symbol;     //运算符号
uchar idata fsym[2];       
uchar idata ssym[2];       //存储组前符号
uchar idata bfun[2];       //计算值调用函数选择
uchar idata futojiao[2];   //幅度 to 角度变换
double idata date[2];      //计算值双精度变量组
double idata resultdate;   //双精度结果值


/******************函数声明**********************/

/***************延时******************/
void delay(uchar z);	
/*************lcd写命令***************/
void write_com(uchar com);
/*************lcd写数据***************/
void write_date(uchar date);
/*************lcd读状态***************/
void read_date(void);
/*************lcd写字符串*************/
void write_str(uchar *str);
/************液晶初始化***************/
void init(void );
/**************键盘扫描***************/
uchar keyscan(void);
/*************计算器复位**************/
void fuwei();          
/************error处理****************/
void callerror(void);
/***************撤销键入**************/
void huifu(void);
/**********函数组前符号处理***********/
uchar funqian(void);
/************运算符预处理*************/
void  cullars(uchar);
/***********输出存储数据预处理********/
char  memory(void);
/***********按键功能主处理************/
void process_date(uchar press_date);
/***********按键功能子处理************/
void calculator(uchar press_date);
/************************************************/
/*************LCD程序****************/
/**************延时******************/
void delay(uchar z)			   //0.2 ms
{
      uchar  x,y;
      for(x=z;x>0;x--)
      for(y=100;y>0;y--);
}

/**************写命令*****************/
void write_com(uchar com)
{
      lcdrs=0;
      lcdrw=0;
      lcden=0;
      P0=com;
      delay(5);
      lcden=1;
      delay(5);
      lcden=0;
}
/*************写数据******************/
void write_date(uchar date)
{
      lcdrs=1;
      lcdrw=0;
      lcden=0;
      P0=date;
      delay(5);
      lcden=1;
      delay(5);
      lcden=0;
}
/*************读AC 地址*****************/
void read_date(void)
{
      lcdrs=0;
      lcdrw=1;
	  delay(5);
	  P0=0xff;
      lcden=1;
      delay(5);
      state=P0;
      delay(5);
      lcden=0;delay(5);
	  state=state&127;
}
/*************写字符串******************/
void write_str(uchar *str)
{     
      uchar idata i;
      for(i=0;str[i]!='\0';i++)
         write_date(str[i]);
}
/***********液晶初始化***************/
void init(void )
{
      write_com(0x38);       //模式:8位数据,两行,5*7字体
      write_com(0x0c);       //开显示,无光标
      write_com(0x06);       //向左增量移动
      write_com(0x01);       //清屏
}


/**************键盘扫描*************/
uchar keyscan(void)          //按行扫描,有键按下则返回键符号,否则返回null
{     uchar idata key0,key1,keyment=0;
      P2=0XFe;				  	   //行1
      key0=P2;
      key0=key0&0xf0;
      key1=key0;
      if(key0!=0xf0)
      {
           delay(5);               //键抖动处理
           P2=0XFe;
           key0=P2;
           key0=key0&0xf0;
           if(key0==key1)
           {
                switch(key0)
                {
                  case 0xe0:keyment='7';break;
                  case 0xd0:keyment='8';break;
                  case 0xb0:keyment='9';break;
                  case 0x70:keyment=0xfd;break;    //0xfd除号在1602液晶中的代码
                }
                while(key0!=0xf0)  //键释放处理
                {
                  key0=P2;
                  key0=key0&0xf0;
                }
                press=1;		   //键按标志置1
                return(keyment);
           }
      }
      P2=0XFd;					  //行2
      key0=P2;
      key0=key0&0xf0;
      key1=key0;
      if(key0!=0xf0)
      {
           delay(5);
           P2=0XFd;
           key0=P2;
           key0=key0&0xf0;
           if(key0==key1)
           {
               switch(key0)
               {
                  case 0xe0:keyment='4';break;
                  case 0xd0:keyment='5';break;
                  case 0xb0:keyment='6';break;
                  case 0x70:keyment='*';break;
               }
               while(key0!=0xf0)
               {
                  key0=P2;
                  key0=key0&0xf0;
               }
               press=1;
               return(keyment);
           }
      }
      P2=0XFb;						 //行3
      key0=P2;
      key0=key0&0xf0;
      key1=key0;
      if(key0!=0xf0)
      {
           delay(5);
           P2=0XFb;
           key0=P2;
           key0=key0&0xf0;
           if(key0==key1)
           {
               switch(key0)
               {
                   case 0xe0:keyment='1';break;
                   case 0xd0:keyment='2';break;
                   case 0xb0:keyment='3';break;
                   case 0x70:keyment='-';break;
               }
               while(key0!=0xf0)
               {
                   key0=P2;
                   key0=key0&0xf0;
               }
               press=1;
               return(keyment) ;
           }
      }
      P2=0XF7;					  //行4
      key0=P2;
      key0=key0&0xf0;
      key1=key0;
      if(key0!=0xf0)
      {
           delay(5);
           P2=0XF7;
           key0=P2;
           key0=key0&0xf0;
           if(key0==key1)
           {
               switch(key0)
               {
                 case 0xe0:keyment='.';break;
                 case 0xd0:keyment='0';break;
                 case 0xb0:keyment='=';break;
                 case 0x70:keyment='+';break;
               }
               while(key0!=0xf0)
               {
                 key0=P2;
                 key0=key0&0xf0;
               }
               press=1;
               return(keyment);
           }
     }
	 else return(0);	   //无键按下返回null
}

/**************计算器复位****************/
void fuwei()
{   uchar idata j,i;
    write_com(0x0f);	    //lcd设置
    write_com(0x01);
    write_com(0x81);
    resultdate=0;
    for(i=0;i<2;i++)
	{ date[i]=0;bfun[i]=0;pai[0][i]=0;pai[1][i]=0;fsym[i]=0;futojiao[i]=0; //各标志置0
	  for(j=0;j<14;j++)		//字符数组初始化
      {	
        bdate[i][j]='\0';
      }
	}
    count=0;				//各标志置0
    count_num=0;
	proc=0;
    ferror=0;
    eqsign=0;
	sc=0;
	savesign=0;
	ywei=0;
	press=0;
	on_symbol=0; 
}
/**************error处理******************/
void callerror(void)
{   uchar idata i;
    write_com(0x01);
    write_com(0x81);
    write_str("     error!     ");
    for(i=0;i<200;i++)delay(25); //持续显示 1s
}

/*****************运算符预处理*****************/
void  cullars(uchar csym)
{	read_date();		   //看第二组是否有输入
	ferror++;              //检错标志+1
	continu=csym;		   //存储运算符号
	if(ferror==2&&state<0x43){callerror();huifu();return;}// 第二组无输入且ferror=2,错误
	if(ferror==2&&state>0x42)	//第二组有输入且ferror=2,则进行连续计算
	{  
	   press=1;					//模拟按键‘=’;将本次的计算结果作为下一次计算的第一组
	   process_date('=');
	   press=1;
	   process_date('m');
	   ferror=1;				//恢复现场,避免变化
	   if(continu=='^'||continu=='%'){process[proc]='h';
	        proc++;process[proc]=continu;proc++;}
	   else{process[proc]=continu;proc++;}	  //恢复连续计算过程
	}
	if(continu=='%'){write_str(" f");}else write_date(' ');
	write_date(continu);//将用与连续计算的运算符号取出
	ywei=0;				   
	savesign=0;
	count_num=1;     //组标志加1
	count=0;		 //输入计数清零
	on_symbol=continu;  //运算符号调用
	write_com(0xc2);
	return;
}
/*************输出存储数据预处理************/
char  memory(void)
{	if((bdate[count_num][0]=='+'||bdate[count_num][0]=='-')&&count==1)//符号处理			
    {
	 	ssym[count_num]=bdate[count_num][0];
	 	bdate[count_num][0]='\0';
		bdate[count_num][1]='\0';
		count=0;
	}
    if(bdate[count_num][0]!='\0'){callerror();huifu();return(1);}	//错误输入方式处理
	return(0);
}
/**************按键功能主处理****************/
void process_date(uchar press_date)
{    
     if(form==0){write_com(0x0f);form=1;}   //显示方式切换 光标闪烁	
     if(eqsign==1&&press==1)fuwei();		//复位再次计算,记忆过程清零
	 press=0;
	 if(press_date=='c'){huifu();press_date=0;}
	 if(press_date==0)return;         	//无按键
	 process[proc]=press_date;
	 proc++;
	 calculator(press_date);
	 return;
}

硬件设计

使用元器件:

单片机:STC89C52;

(注意:单片机是通用的,无论51还是52、无论stc还是at都一样,引脚功能都一样。程序也是一样的。)

IC座:DIP40;

万能板:9*15/7*9;

液晶屏:LCD1602;

电容:22pF;电容:10uF/16V;

电阻:1K;电阻:4.7K;

按键:6*6*5;自锁开关:8*8;

接线端子:5.08*2P;

晶振:11.0592;

导线:若干;

添加图片注释,不超过 140 字(可选)

流程图:

添加图片注释,不超过 140 字(可选)

设计资料

01仿真图

本设计使用proteus7.8和proteus8.9两个版本设计,向下兼容,无需担心!具体如图!

添加图片注释,不超过 140 字(可选)

02原理图

本系统原理图采用Altium Designer19设计,具体如图!

添加图片注释,不超过 140 字(可选)

03程序

本设计使用软件keil5版本编程设计!具体如图!

添加图片注释,不超过 140 字(可选)

04设计报告

八千字设计报告,具体如下!

添加图片注释,不超过 140 字(可选)

05设计资料

       资料获取请关注同名公众号,全部资料包括程序(含注释)、仿真源文件 、AD原理图、PCB、设计报告、流程图、实物图、元件清单、实物演示视频等。具体内容如下,全网最全!!

添加图片注释,不超过 140 字(可选)

资料获取请观看前面演示视频!

点赞分享一起学习成长。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值