当前位置:文档之家› 简易计算器

简易计算器

简易计算器设计学院:电气信息工程学院专业:电子科学与技术年级:2010级_小组:王会祥(主力)王成龙余勇老师:_翁嘉铭基于C51单片机的简易计算器1.前言1、本系统选用51单片机为主控机。

通过扩展必要的外围电路接口实现计算的设计。

2、由于要设计的是简单的计算器,可以进行四则运算,为了得到较好的显示效果,采用LCD显示数据和结果。

3、键盘部分由3*4矩阵键盘外加8个独立按键共同实现。

通过软件编程可实现整数和小数的简单加、减、乘、除、平方、立方、开根号、清除结果功能。

2.系统总体设计框图3.系统主流程图4.LCD显示1、LCD显示器介绍LCD显示器,它是利用液晶经过处理后能改变光线的传输方向的特性实现信息的显示。

液晶显示器具有体积小、重量轻、功耗低、显示内容丰富灯特点,在单片机的应用系统中得到广泛的应用,液晶显示器按功能可分为三类:笔段式液晶显示器、字符型液晶显示器和图像点阵式液晶显示器。

前两种可显示数字、字符和符号等,而图形点阵式液晶显示器还可以显示汉字和任意图行,达到图文并茂的效果,本次实验是采用LCD1602字符型液晶显示器,LCD1602能够同时显示16x2即32个字符。

1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。

每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用。

2、LCD1602管脚功能1602采用标准的16脚接口,其中:第1脚:VSS为电源地;第2脚:VDD接5V电源正极;第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。

第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。

第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。

第6脚:E(或EN)端为使能(enable)端。

第7~14脚:D0~D7为8位双向数据端。

第15~16脚:空脚或背灯电源。

15脚背光正极,16脚背光负极。

2、LCD1602字符点阵LCD1602内已经存储了160个不同的点阵字符图形,实现阿拉伯数字、英文字母的大小写、常用符号和日文字符的显示5.键盘检测原理与应用1、键盘电路图3*4键盘8个独立键盘2、独立键盘、矩阵键盘(中断式,扫描式,反转式)在实验中应用。

STC90C51单片机矩阵键盘是3*4=12按键,实现计算器的功能需要约20个按键,12个明显不够,这时考虑用红外遥控来控制,这虽然可以实现,但是在实际中,我们很少用红外的遥控来进行计算,因为容易受到外界的干扰,所以最终采用3*4矩阵键盘和8个独立键盘共同实现。

设计行列键盘接口,一般常采用3种方法读取键值。

一种是中断式,另外两种是扫描法和反转法。

中断式:在键盘按下时产生一个外部中断通知CPU,并由中断处理程序通过不同的地址读取数据线上的状态,判断哪个案件被按下。

扫描法:对键盘上的某一行送低电平,其他行为高电平,然后读取列值。

若列值中有一位是低,则表明该行与低电平对应列的键被按下;否则,扫描下一行。

反转法:先将所有行扫描线输出低电平,读列值。

若列值有一位是低,则表明有键按下,读列值;然后所有列扫描线输出低电平,再读行值。

根据读到的值组合就可以查表得到的键码。

6.实现:1、LCD初始化显示初始化,在这一步进行初始化及设置显示模式等操作,包括以下步骤:设置①显示方式:设置LCD为16X2显示,5X7点阵,八位数据接口②延时③清理显示缓存:清除LCD的显示内容④设置显示模式:LCD显示光标移动设置(光标地址指针加1,整屏显示不移动)2、键盘检测流程图4.3实现算法1、算法设计本计算器支持两个操作数最基本的运算,加法、减法、乘法、除法、平方、立方、开根号的计算,计算结果小数点后保留4位数字。

设计的算法如下:①每输入数字,对数字进行转化,支持小数点;②当输入运算符,说明第一个数输入结束,保存第一个数;i、如果是二元运算符,则返回①,输入第二数后,保存;ii、如果是一元操作符,则等待对第一个数进行计算。

iii、如果是等号,对两个数进行计算,对计算结果保留小数点后4位。

7.原理图8.PCB9.仿真图10.程序代码#include<reg52.h>#include<math.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit K1=P3^0;sbit EN=P2^7;//1602使能控制线sbit RS=P2^6;//1602数据/指令选择控制线sbit RW=P2^5;//1602读写控制线sbit mul_k=P3^0;//按键“*”sbit div_k=P3^1;//按键“/”sbit equ=P3^2;//按键“=”sbit poin_k=P3^3;//按键“.”sbit squre_k=P3^4;//按键平方sbit cube_k=P3^5;//按键立方sbit root_k=P3^6;//按键开根号sbit clear_k=P3^7;//按键清空uchar table[]="0123456789+-*/=.SCRD";//存放字符表uint num=21,d=-1,j=0;long int b=0,e=1,n,c=1;long double k=0,a=0,i=0;void delay(uint z)/*延时子程序。

主要用于系统需要延时的时候*/{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/**1602忙状态检测**/void lcdbusy(){do{EN=0;RS=0;RW=1;P0=0xff;EN=1;_nop_();}while(P0&0x80);EN=0;}void write_com(uchar com)/*LCD1602显示模式控制子程序*/{lcdbusy();RS=0;RW=0;EN=1;P0=com;EN=0;}void write_date(uchar date)/*LCD1602显示子程序*/{lcdbusy();RS=1;RW=0;EN=1;P0=date;EN=0;}uchar keyscan()/*键盘检测子程序。

判断键盘按键,并对每个按键赋予一个相应的键值*/{uchar temp;P1=0xfd;//11111101P1.1=0temp=P1;temp=temp&0xf0;if(temp!=0xf0)//有键被按下{delay(5);P1=0xfd;temp=P1;temp=temp&0xf0;if(temp!=0xf0){switch(temp)//检测按键(0,1,2,3){case0xe0:num=0;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;/*当有小数点键按下时(即C=0,i=1),将原来+数字键*0.1,比如原来时10,则运算完后为10.1,若该键又按下,则可以显示10.11,当小数点没按下时,则将原来的数*10,然后加上该按键数,比如原来是9,当该按键按下时,则在液晶上显示91*/break;case0xd0:num=1;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0xb0:num=2;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0x70:num=3;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;}while(temp!=0xf0)//按键释放temp=P1;temp=temp&0xf0;}}}P1=0xfb;//11111011P1.2=0temp=P1;temp=temp&0xf0;if(temp!=0xf0)//有键被按下{delay(5);P1=0xfb;temp=P1;temp=temp&0xf0;if(temp!=0xf0){switch(temp)//检测按键(4,5,6,7){case0xe0:num=4;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0xd0:num=5;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0xb0:num=6;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0x70:num=7;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;while(temp!=0xf0){temp=P1;temp=temp&0xf0;}}}P1=0xf7;//11110111P1.3=0temp=P1;temp=temp&0xf0;if(temp!=0xf0)//有键被按下{delay(5);P1=0xf7;temp=P1;temp=temp&0xf0;if(temp!=0xf0){switch(temp)//检测按键(8,9,+,-){case0xe0:num=8;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0xd0:num=9;d++;i=i*0.1;k=k*(1+9*c)+num*c+num*i;break;case0xb0:num=10;j=1;c=1;i=0;a=k;k=0;d++;break;case0x70:num=11;j=2;c=1;i=0;a=k;k=0;d++;break;}while(temp!=0xf0){temp=P1;temp=temp&0xf0;}}}return num;}void DLkeyscane()//独立按键检测(*/=.){uchar f,m,g;if(!mul_k)//按键“*”{num=12;j=3;c=1;i=0;a=k;k=0;d++;while(mul_k==0)//按键释放{;}}if(!div_k)//按键“/”{num=13;j=4;c=1;i=0;a=k;k=0;d++;while(div_k==0){;}}if(!squre_k)//按键“平方”{num=16;j=5;c=1;i=0;a=k;k=0;d++;while(squre_k==0){;}}if(!cube_k)//按键“立方”{num=17;j=6;c=1;i=0;a=k;k=0;d++;while(cube_k==0){;}}if(!root_k)//按键“开根号”{num=18;j=7;c=1;i=0;a=k;k=0;d++;while(root_k==0){;}}if(!equ)//按键“=”{num=14;{if(j==2)b=(a-k)*100000;/*做减法运算,由于只要显示小数点后面5位,b又定义为整形,故在此先*100000,这样也方便后面判断b位数和液晶显示*/else if(j==1)b=(a+k)*100000;else if(j==4&&k!=0)b=(a/k)*100000;else if(j==5)b=pow(a,2.0)*100000;else if(j==6)b=pow(a,3.0)*100000;else if(j==7)b=sqrt(a)*100000;elseb=(a*k)*100000;for(n=1,m=0;b/n>0;n=n*10)//判断b的位数{m++;}for(g=0;g<m-5;g++){for(f=1;f<m-g;f++)e=e*10;write_com(0x80+0x40+g);delay(10);write_date(table[b/e%10]);//分解数的小数点前面各个位上的数,并在显示器上显示e=1;delay(10);}write_com(0x80+0x40+m-5);delay(10);write_date(table[15]);//紧接前面显示一个小数点delay(10);e=1;for(g=m-4;g<m;g++)//显示小数后面5位{for(f=0;f<m-g;f++)e=e*10;write_com(0x80+0x40+g);delay(10);write_date(table[b/e%10]);e=1;delay(10);}d++;}while(equ==0){;}}if(!poin_k)//按键“小数点”{num=15;c=0;i=1;d=d+1;while(poin_k==0){;}}if(!clear_k)//按键“清空”{num=21;d=-1;j=0;b=0;e=1;c=1;k=0;a=0;i=0;write_com(0x01);//清除LCD的显示内容while(clear_k==0){;}}}/*Lcd初始化*/void init(){write_com(0x38);//设置LCD为16X2显示,5X7点阵,八位数据接口write_com(0x0c);//LCD显示光标移动设置(光标地址指针加1,整屏显示不移动) write_com(0x06);//LCD开显示及光标设置(光标不闪烁,不显示"_")write_com(0x01);//清除LCD的显示内容}/*LCD显示*/void display(){write_com(0x80+d);delay(10);write_date(table[num]);delay(20);}void main()/*主程序*/{init();while(1){//P3=0xff;keyscan();DLkeyscane();display();}}附1:参考资料[1]李晓林,单片机原理及接口技术(第二版).北京,电子工业出版社,2011[2]郭天祥,新概念51单片机c语言教程。

相关主题