计算器

带小数点计算器

1、本设计是实现一个有加、减、乘、除、计算功能的多功能计算器。它的硬件主要由四部分组成,一个STC89C52单片机芯片,一块LCD1602液晶显示器,一个4X4的键盘。采用STC89C52单片机为主要控制电路,然后使用液晶显示管显示数据,利用44矩阵键盘加上一些功能键完成电路的输入操作部分。电路比较简单,但是很实用方便。
2、本设计拟实现的性能指标如下:
(1) 采用LCD1602液晶屏显示
(2) 4
4键盘来输入数据。
(3) 能够进行小数运算。
(4) 可以计算不超过13位数的加减乘除。

LCD显示模块
LCD1602是一种工业字符型液晶,能够同时显示16x02 即32个字符。(16列2行)。在日常生活中,我们对液晶显示器并不陌生。液晶显示模块已作为很多电子产品的通过器件,如在计算器、万用表、电子表及很多家用电子产品中都可以看到,显示的主要是数字、专用符号和图形。在单片机的人机交流界面中,一般的输出方式有以下几种:发光管、LED数码管、液晶显示器。发光管和LED数码管比较常用,软硬件都比较简单。
在单片机系统中应用晶液显示器作为输出器件有以下几个优点:
由于液晶显示器每一个点在收到信号后就一直保持那种色彩和亮度,恒定发光,而不像阴极射线管显示器(CRT)那样需要不断刷新新亮点。因此,液晶显示器画质高且不会闪烁。
液晶显示器都是数字式的,和单片机系统的接口更加简单可靠,操作更加方便。
液晶显示器通过显示屏上的电极控制液晶分子状态来达到显示的目的,在重量上比相同显示面积的传统显示器要轻得多。
相对而言,液晶显示器的功耗主要消耗在其内部的电极和驱动IC上,因而耗电量比其它显示器要少得多。
(1)引脚说明:
第1脚:VSS为地电源。
第2脚:VDD接5V正电源。
第3脚:VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。
第5脚:R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平
R/W为高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:D0~D7为8位双向数据线。
第15脚:背光源正极。
第16脚:背光源负极。

硬件电路设计

显示电路设计
当系统需要显示少量数据时,采用LCD液晶显示屏进行显示是一种经济实用的方法。P0口作为液晶显示的数据端口,P3.5-P3.7口作为其控制端口,控制LCD液晶显示屏显示输出数据。电路如图:

LCD液晶显示屏显示
键盘电路的设计
键盘可分为两类:编码键盘和非编码键盘。编码键盘是较多按键(20个以上)和专用驱动芯片的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。通用计算机使用的标准键盘就是编码键盘。在智能仪器中,使用并行接口芯片8279或串行接口芯片HD7279均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路和接口软件均可在芯片资料中得到。当系统功能比较复杂,按键数量很多时,采用编码键盘可以简化软件设计。非编码键盘成本低廉。
从成本角度出发,本设计选用的是非编码键盘。

键盘电路接线图
源文件下载
链接: 源文件下载.

仿真图

代码

#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
//sbit choose=P3^4;          //时钟和计算器选择键
/*************lcd****************/
sbit lcdrs=P2^7;           //LCD控制脚
sbit lcdrw=P2^6;
sbit lcden=P2^5;
bit idata form;            //lcd显示方式切换
uchar idata state;         //lcd状态字存储
/************计算器*************/
//sbit reset=P3^0;           //计算器复位
//sbit back=P3^1;            //撤销上次键入键
//sbit save=P3^2;            //存储键,存储有上次的结果和另外某次计算值
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;   //双精度结果值
/***************时钟****************/
sbit stime=P3^3;           //时间设置键,同时用于计算器模式的复用键
uchar idata ms50=0;        //时间调节变量
uchar idata s=0;           //秒
uchar idata m=0;           //分
uchar idata h=0;           //小时/******************函数声明**********************//***************延时******************/
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;P1=0Xef;                       //行1key0=P1;key0=key0&0x0f;key1=key0;if(key0!=0x0f){delay(5);               //键抖动处理P1=0Xef;key0=P1;key0=key0&0x0f;if(key0==key1){switch(key0){case 0x0e:keyment='7';break;case 0x0d:keyment='8';break;case 0x0b:keyment='9';break;case 0x07:keyment=0xfd;break;  //0xfd除号在1602液晶中的代码}while(key0!=0x0f)  //键释放处理{key0=P1;key0=key0&0x0f;}press=1;         //键按标志置1return(keyment);}}P1=0Xdf;                    //行2key0=P1;key0=key0&0x0f;key1=key0;if(key0!=0x0f){delay(5);P1=0Xdf;key0=P1;key0=key0&0x0f;if(key0==key1){switch(key0){case 0x0e:keyment='4';break;case 0x0d:keyment='5';break;case 0x0b:keyment='6';break;case 0x07:keyment='*';break;}while(key0!=0x0f){key0=P1;key0=key0&0x0f;}press=1;return(keyment);}}P1=0Xbf;                        //行3key0=P1;key0=key0&0x0f;key1=key0;if(key0!=0x0f){delay(5);P1=0Xbf;key0=P1;key0=key0&0x0f;if(key0==key1){switch(key0){case 0x0e:keyment='1';break;case 0x0d:keyment='2';break;case 0x0b:keyment='3';break;case 0x07:keyment='-';break;}while(key0!=0x0f){key0=P1;key0=key0&0x0f;}press=1;return(keyment) ;}}P1=0X7f;                     //行4key0=P1;key0=key0&0x0f;key1=key0;if(key0!=0x0f){delay(5);P1=0X7f;key0=P1;key0=key0&0x0f;if(key0==key1){switch(key0){case 0x0e:keyment='.';break;case 0x0d:keyment='0';break;case 0x0b:keyment='=';break;case 0x07:keyment='+';break;}while(key0!=0x0f){key0=P1;key0=key0&0x0f;}press=1;return(keyment);}}
/*     else  if(save==0)         //储存数据键{ delay(5);if(save==0)   { if(sc==0)     //输出前次计算结果键{ keyment='m';press=1;while(save==0);return(keyment);}else             //更新存储的数据或输出存储的数据{keyment='n';press=1;sc=0;while(save==0);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; //各标志置0for(j=0;j<14;j++)      //字符数组初始化{  bdate[i][j]='\0';}}count=0;             //各标志置0count_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++;              //检错标志+1continu=csym;         //存储运算符号if(ferror==2&&state<0x43){callerror();huifu();return;}// 第二组无输入且ferror=2,错误if(ferror==2&&state>0x42)   //第二组有输入且ferror=2,则进行连续计算{  press=1;                   //模拟按键‘=’和‘M+’;将本次的计算结果作为下一次计算的第一组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;     //组标志加1count=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;
}
/***************按键功能子处理***************/
void calculator(uchar press_date)
{    uchar idata j=0;/*************************************/if((press_date<='9'&&press_date>='0')||(press_date=='.')) //数字键处理{ savesign=0;              //不可更新存储数据if(sc==0)           //是否为复用sc为0,是数字{ if(count<14-ywei)  //未调用函数时最多输入14位数,包括小数点{  write_date(press_date);bdate[count_num][count]=press_date; //储存键值count++;}else {callerror();huifu();}  //超出14位出错,恢复}}/*************************************************/else if(press_date=='m')       //上次计算结果输出{    if(memory()==1)return;                         //输出存储数据预处理for(j=0;result[j]!='\0';j++)write_date(result[j]);           //输出存储值strcpy(bdate[count_num],result);savesign=1;       //此时可以更新saveresult中存储的数据count=14;          //count=14是让本组数据已确定}/****************'+','-'处理*****************/else if((press_date=='+')||(press_date=='-')){    if(count==0)      // 表示输入数据的符号,此时默认数值为0{                       write_date(press_date);bdate[count_num][0]=press_date; bdate[count_num][1]='0';read_date();          //读状态write_date('0');write_com(state+0x81);//光标还回原来位置count=1;}else             //为运算符号{   cullars(press_date);}         }/****************'*','/'处理*****************/else if(press_date==0xfd) //0xfd除号在1602液晶中的代码{   if(sc==1)    //幅度 to 角度{  if(count!=0){futojiao[count_num]=1;sc=0;write_date(0xDF);count=14;}else {callerror();huifu();}}else cullars(press_date);}else if(press_date=='*') //0xfd除号在1602液晶中的代码{             cullars(press_date);}/*******************'='号处理*****************/else if(press_date=='='){ write_com(0x01);           //清屏write_com(0x80+0x40+4);write_date(press_date);    //显示等号for(j=0;j<2;j++)          //两运算组的函数处理{date[j]=atof(bdate[j]);  //俩组数据,字符串->实数if(fsym[j]=='-')date[j]=-date[j];  //函数前的符号处理 }if(ferror==0)                             //仅仅函数计算{  resultdate=date[0];}else                                    //运算符号计算{switch(on_symbol){case '+':resultdate=date[0]+date[1];break;case '-':resultdate=date[0]-date[1];break;case '*':resultdate=date[0]*date[1];break;case 0xfd:resultdate=date[0]/date[1];break;       //0xfd除号在1602液晶中的代码case '^':resultdate=pow(date[0],date[1]);break;   //pow()函数   x^ycase '%':resultdate=fmod(date[0],date[1]);break;  //fmod()函数 求余数(双精度)}}         sprintf(jieguo,"%g",resultdate);//结果实数->字符串,采用格式字符g,系统选择%f或%e输出格式,六位有效数字           if((jieguo[0]>'9'||jieguo[0]<'0')&&(jieguo[1]>'9'||jieguo[1]<'0')&&jieguo[1]!='\0'&&jieguo[1]!='.'){   callerror();fuwei();return;  }   //错误处理,当组1或组2不合法时结果是几个英文字母提示    else strcpy(result,jieguo);   //没错误,保存结果,结果立存 M+键                                                                     for(j=0;jieguo[j]!='\0';j++)               //显示结果write_date(jieguo[j]);for(;j<15;j++)write_date(' ');  //让光标出屏幕eqsign=1;                      //按等号键标志置1}return;
}
/*********************主程序**********************/
void main()
{   fuwei();        //计算器初始化init();       //显示初始化     TH0=0x3c;     //定时器0初始化TL0=0xb7;TMOD=0x1;     //定时器0,方式1TR0=1;        //开始计时ET0=1;EA=1;         //允许溢出中断设置form=1;       //显示方式初始化proc=0;       //计算工程存储初始化write_com(0x81); while(1)      {process_date(keyscan()); //计算器}
}
/*********************end**********************/
/**********************************************/

源文件下载
链接: 源文件下载.

简易计算器--带小数点--单片机课程设计相关推荐

  1. 单片机音乐播放器课程设计C语言,单片机课程设计简易音乐播放器

    单片机课程设计简易音乐播放器 论文题目:简易音乐播放器所属系部:电子工程系 指导教师: 学生姓名: 学 号: 专 业: 电子信息工程技术 题目: 简易音乐播放器任务与要求:本设计以 MCS-51 系列 ...

  2. 单片机节日彩灯c语言程序,单片机课程设计简易节日彩灯

    <单片机课程设计简易节日彩灯>由会员分享,可在线阅读,更多相关<单片机课程设计简易节日彩灯(7页珍藏版)>请在人人文库网上搜索. 1.单片机课程设计节日彩灯一. 需求分析:1. ...

  3. 单片机模拟计算机课设,单片机课程设计题目汇总(全)

    单片机原理与接口技术课程设计题目汇总,说明:为便于同学提前探讨开发思路,要求:课程设计考核内容包括:源程序,一.基于单片机的电子时钟设计,设计内容:1.用LCD液晶作为显示设备(30分),2.可以分别 ...

  4. c语言c51单片机点亮8个灯,单片机课程设计-8个LED灯来回点亮

    <单片机课程设计-8个LED灯来回点亮>由会员分享,可在线阅读,更多相关<单片机课程设计-8个LED灯来回点亮(20页珍藏版)>请在人人文库网上搜索. 1.目录第一章 绪论-3 ...

  5. 51单片机课程设计《三路步进电机控制》

    说明:最近抽出了几天时间完成了单片机的课程设计,用了51单片机做了三路步进电机控制器,美名其曰3d打印机控制器(其实是瞎搞的,与3D打印机毫无关系),因为单片机课程设计是在大四上学期,与考研复习时间冲 ...

  6. 温度报警程序c语言设计,51单片机课程设计:基于DS18B20的温度报警器

    51单片机课程设计:基于DS18B20的温度报警器 本程序用于读取DS18B20温度,同时具备报警功能,工程分为3个文件,main.c.temp.c.temp.h,经本人修改部分代码,适用于吉林农业大 ...

  7. Linux课程设计八音盒,单片机课程设计——八音盒精要.doc

    单片机课程设计--八音盒精要 <单片机原理及应用>课程设计 ---八音盒设计--- 院 系: 机电汽车工程学院 姓 名: 班 级: 机101-4班 组 长: 组 员: 指导教师: 姜风国 ...

  8. 单片机彩灯移动实验_单片机课程设计彩灯实验.doc

    单片机课程设计彩灯实验 彩灯控制器设计 1.项目要求及参数 1.1用指令语句实现对C51的控制,从而实现对彩灯变化的控制. 1.2用定时器控制彩灯变化,用语句查询方式实现程序设计. 1.3用定时器控制 ...

  9. 检测噪声大小的c语言程序,单片机课程设计(论文)_基于AT89C51的噪音检测自适应系统设计.doc...

    单片机课程设计(论文)_基于AT89C51的噪音检测自适应系统设计 摘 要 本文以AT89S52 单片机为控制核心,通过播音判断电路寻找广播间歇时段,实时采集噪声环境内的噪音信 号,根据A/ D 转换 ...

  10. 单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》...

    引言 本设计以AT89S52单片机为控制核心,时钟芯片DS1302提供时钟源,配合LCD1602液晶显示模块,组成基本硬件系统,同时利用HC-05嵌入式蓝牙串口通讯模块,可在手机端进行日期.时间的校准 ...

最新文章

  1. Elasticsearch入门Demo(二)
  2. TensorFlow快餐教程:程序员快速入门深度学习五步法
  3. android实现过程,Android:一个完整app开发流程
  4. 运营商部署4.5G热情高涨:将影响5G商用
  5. 后台开发人员面试内容——JVM虚拟机(四)
  6. Gh0st 3.6 存在的BUG及修改方法(收集整理)
  7. gitl更新最近代码_常见的蓝屏代码以及解决方法
  8. js面向对象写法,一个小例子
  9. const char* p 、char* const p、const (char*) p 理解记忆
  10. 多线程启动定时器 会等待上一次执行完成?_Java多线程
  11. 为什么相关性不等于因果性?终于有人讲明白了
  12. Wi-FiR CC3000 模块
  13. 凌阳单片机c语言延时函数,凌阳单片机C语言(网站整理).doc
  14. 推荐一款.NET开源免费的图表控件ScottPlot
  15. win32汇编--创建窗口程序(RadAsm)
  16. SSD算法原理与代码(三)
  17. html5微相册,微信开发 微信H5开发 微信小程序 微报名 微相册 微**
  18. Clock skew detected. Your build may be incomplete
  19. HoloView 在 jyputer lab/notebook 不显示总结
  20. 利用动网论坛dvBBS漏洞上传webshell

热门文章

  1. Windows 最值得推荐的装机必备“神器”软件大合集
  2. Ulipad安装失败解决办法
  3. mapxtreme java_MapXtreme Java Edition 4.8使用心得(二)
  4. c语言及程序设计基础 pdf,c语言程序设计基础.pdf
  5. ekho嵌入式Linux移植全过程
  6. 「旅游信息管理系统」 · Java Swing + MySQL 开发
  7. 通达信公式系统 入门 LTS
  8. linux下JMeter安装
  9. Java调用python传参数并获取python返回的值
  10. uu云验证码识别平台,验证码,验证码识别,全自动验证码识别技术,优优云全自动打码,代答题系统,优优云远程打码平台,uu云打码...