基于51单片机的计算器设计.docx
《基于51单片机的计算器设计.docx》由会员分享,可在线阅读,更多相关《基于51单片机的计算器设计.docx(18页珍藏版)》请在冰豆网上搜索。
![基于51单片机的计算器设计.docx](https://file1.bdocx.com/fileroot1/2023-1/3/59429ed9-143b-4e55-86bc-8ed41bb8d893/59429ed9-143b-4e55-86bc-8ed41bb8d8931.gif)
基于51单片机的计算器设计
第一章引言……………………………………………………………3
1、1简述简易计算器、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、3
1、2本设计主要任务、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、3
1、3系统主要功能、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、4
第二章系统主要硬件电路设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、4
2、1系统的硬件构成及功能、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、4
2、2键盘电路设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、5
2、3显示电路设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、6
第三章系统软件设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、7
3、1计算器的软件规划、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、7
3、2键盘扫描的程序设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、7
3、3显示模块的程序设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、8
3、4主程序的设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、9
3、5软件的可靠性设计、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、9
第四章调试、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、9
第五章结束语、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、10
参考文献、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、11
附录源程序、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、11
第一章引言
1、1简述简易计算器
近几年单片机技术的发展很快,其中电子产品的更新速度迅猛。
计算器就是日常生活中比较的常见的电子产品之一。
如何才能使计算器技术更加的成熟,充分利用已有的软件与硬件条件,设计出更出色的计算器呢?
本设计就是以AT89S52单片机为核心的计算器模拟系统设计,输入采用4×6矩阵键盘,可以进行加、减、乘、除9位带符号数字运算,并在LCD1602上显示操作过程。
科技的进步告别了以前复杂的模拟电路,一块几厘米平方的单片机可以省去很多繁琐的电路。
现在应用较广泛的就是科学计算器,与我们日常所用的简单计算器有较大差别,除了能进行加减乘除,科学计算器还可以进行正数的四则运算与乘方、开方运算,具有指数、对数、三角函数、反三角函数及存储等计算功能。
计算器的未来就是小型化与轻便化,现在市面上出现的使用太阳能电池的计算器,使用ASIC设计的计算器,如使用纯软件实现的计算器等,未来的智能化计算器将就是我们的发展方向,更希望成为应用广泛的计算工具。
1、2本设计主要任务
以下就是初步设定的矩阵键盘简易计算器的功能:
1、扩展4*6键盘,其中10个数字,5个功能键,1个清零
2、强化对于电路的焊接
3、使用五位数码管接口电路
4、 完成十进制的四则运算(加、减、乘、除);
5、 实现结果低于五位的连续运算;
6、 使用keil软件编写程序,使用汇编语言;
7、 最后用ptoteus模拟仿真;
8、学会对电路的调试
1、3系统主要功能
本设计就是一个实现加减乘除的计算器,它的硬件主要由四部分构成,一个8051单片机芯片,两个八段共阴极数码管,一个4*4键盘,它可以实现一位数的加减乘除运算。
显示部分:
采用LED动态显示。
按键部分:
采用4*4键盘。
采用软件识别键值,并执行相应的操作。
第二章系统主要硬件电路设计
2.1系统的硬件构成及功能
主要用到的硬件:
AT89S52LCD液晶显示屏编码键盘
硬件分配:
1、P0、P3口:
做为输出口,控制LCD液晶显示屏显示数据的结果。
2、P1口:
做为输入口,与键盘连接,实现数据的输入。
3、LCD液晶显示屏显示输出。
为了更好的实现系统得功能,硬件电路的设计应该遵循以下原则:
1、优化硬件电路
采用软件设计与硬件设计相结合的方法;尽管采用软件来实现硬件系统的功能时,也许响应时间会比单纯使用硬件时长,而且还要占用微处理器(MCU)的时间;但就是,用软件实现硬件的功能可以简化硬件结构,提高电路的可靠性。
所以,在设计本系统得时候,在满足可靠性与实时性的前提下,尽可能的通过软件来实现硬件功能。
2、可靠性及抗干扰设计
根据可靠性设计理论,系统所用芯片数量越少,系统的平均无故障时间越长。
而且,所用芯片数量越少,地址与数据总线在电路板上受干扰的可能性也就越小。
因此,系统的设计思想就是在满足功能的情况下力争使用较少数量的芯片。
3、灵活的功能扩展
功能扩展就是否灵活就是衡量一个系统优劣的重要指标。
一次设计往往不能完全考虑到系统的各个方面,系统需要不断完善以及进行功能升级。
进行功能扩展时,应该在原有设计的基础上,通过修改软件程序与少量硬件完成。
对于本系统而言,就就是要求在系统硬件不变的情况下,能够通过修改软件程序,完成功能的升级与扩展。
根据第提出的系统设计方案,结合以上三条原则,确定了系统硬件的设计。
计算器主要由以下一些功能模块构成:
非编码键盘模块、LCD液晶显示屏模块等。
该系统的硬件设计采用了模块化的设计方法。
AT89S52单片机与LCD液晶显示屏显示电路就是整个电路的核心,它们实现系统的功能要求。
简易计算器主要包括:
键盘电路,显示电路。
下图为总体硬件结构。
(如图2-1所示为整个系统的原理图)
图2-1计算器原理图
前面叙述了该系统的设计说明,系统采用了比较简单的设计方案,所以该系统的硬件设计的总外围电路不会产生过多的干扰。
在下面的阐述中,对系统的外围电路分别予以介绍。
键盘部分采用编码键盘,显示部分采用LCD液晶显示屏完全能够很好的实现显示方面的要求。
2、2键盘电路的设计
键盘可分为两类:
编码键盘与非编码键盘。
编码键盘就是较多按键(20个以上)与专用驱动芯片的组合,当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。
通用计算机使用的标准键盘就就是编码键盘。
在智能仪器中,使用并行接口芯片8279或串行接口芯片HD7279均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路与接口软件均可在芯片资料中得到。
当系统功能比较复杂,按键数量很多时,采用编码键盘可以简化软件设计。
非编码键盘成本低廉。
从成本角度出发,本设计选用的就是非编码键盘。
如图2-2
图2-2编码键盘电路
2、3显示电路的设计
当系统需要显示少量数据时,采用LCD液晶显示屏进行显示就是一种经济实用的方法。
P0口作为液晶显示的数据端口,P3、5-P3、7口作为其控制端口,控制LCD液晶显示屏显示输出数据。
最终电路如图2、3所示:
图2、3LCD液晶显示屏显示
第三章系统软件设计
3、1计算器的软件规划
简易计算器的程序主要包括以下功能模块:
1、定时查键模块,分为读键程序、判键程序段、运算操作子程序等部分;
2、基于LCD液晶显示屏的显示模块;
3、主模块,为系统的初始化。
3、2键盘扫描的程序设计
键盘扫描子程序,首先读出P1的低四位,然后读出P1口的高四位。
然后键值并显示缓存。
然后将键如的值转换为ASCII码然后就可以软件来设置硬件按键各个键代表的内容。
读键程序使用的就是反转法读键,不管键盘矩阵的规模大小,均进行两次读键。
第一次所有行线均输出低电平,从所有读入键盘信息(列信息);第二次所有列线均输出低电平,从所有行线读入键盘信息(行信息)。
数字键按下则将相应的数字送入缓存区,功能键按下则执行相应的程序。
3、3显示模块的程序设计
显示模块程序首先要对显示模块进行初始化;然后控制光标的位置;定义液晶显示的控制端口,用SBIT指令完成;然后设置清屏、关闭显示、归位、开显示、显示位置的首地址等等。
显示模块的流程图如图3、3所示:
3、4主程序的设计
主程序主要就是用来对LCD液晶显示屏进行初始化的。
3、5软件的可靠性设计
提高本仪器其可靠性措施主要有:
1、为防止程序跑飞,软件中设置了软件陷阱。
2、为防止程序死循环,软件中使用了瞧门狗技术。
第四章调试
Keil调试与仿真
KEILC51标准C编译器就是众多单片机应用开发的优秀软件之一,它集编辑、编译、仿真于一体,支持汇编、PLM语言与C语言的程序设计。
1、启动KEILC51进入编辑界面建立一个新工程:
单击Project菜单,在弹出的下拉菜单中选中NewProject选项。
选择保存路径,输入工程文件名。
2、工程文件保存完毕之后,提示选择单片机的型号。
KEIL支持近乎所有51核的单片机。
单击File菜单,选择New。
3、文件保存:
使用汇编编写,文件后缀名为、asm或a51。
完成后,单击“保存”按钮保存文件。
4、在SourceGroup上单击右键,找到刚才保存的源文件,然后添加ADD
5、在编辑完成之后,需要进行程序的编译。
点开Project选项,单击Buildtarget;或就是利用快捷键F7。
6、在程序调试的时候,点击Debug选项,选择Start/StopDebugSession。
7、以上就是使用KEIL建立一个完整工程文件的过程。
下载到单片机之中,则需要生成HEX文件。
单击“Project”菜单,再在下拉菜单中单击出现选项对话框。
在选项对话框的“Output”页面对话框中,单击“CreateHEXFile”选项,使程序编译后产生HEX代码,供下载器软件使用。
4、2、调试过程
在Debug调试下,如有错误时,下面窗口将有提示说明错误个数与具体哪一行有错,还有对于错误的说明,大多数格式使用不当,此时在那一行前后仔细检查,要考虑格式,语法等基本性错误。
即使调试没错时,程序也不就是代表完全正确,需要结合硬件来确定改程序的功能就是否完全实现了。
图4-1keil调试图
图4-1keil调试图
第五章结束语
选择这个课题的时候,完全就是由于兴趣,因为觉得这个课题比较的有意思,比较贴近生活。
参考了一些范文与参考书后,作出了这篇设计报告。
在期间,感觉自己的视野与对于单片机的应用都有了新的认识与拓展。
在硬件的制作过程中我走了好多的弯路,主要就是在系统还没有设计很有把握就开始动手制作了。
后来发现与设计的要求还有偏差,反复的改过了几次,浪费了大量的时间与体力。
感受到设计人员要有耐心,要认真的从要求开始研究。
软件的编写过程中费了很大的力气,因为软件的编写要求很高,要很细心,一不小心就会调用错误,很深刻的体会到作为软件编程人员就是绝不能粗心大意的。
一个程序的完成的速度与质量高低与细心与否有着很大联系。
编程时,我充分使用了结构化的思想。
这样因为语句较少,程序调试比较方便,功能模块可以逐一的调试,充分体现了结构化编程的优势。
当每个模块都完成时,将其功能加到一起就完成了整体的设计。
参考文献
【1】张靖武,周灵杉、单片机系统的PROTEUS设计与仿真[M]、北京:
北京电子工业出版社
【2】靳达、求就是科技、单片机应用系统开发实例导航[M]、:
人民邮电出版社,2006
【3】刘守义、单片机应用技术[M]、:
西安电子科技大学出版社,2001
【4】林志琦、基于PROTEUS的单片机可视化软硬件仿真[M]、北京:
北京航空航天大学出版社,2006
【5】胡汉才、单片机原理及接口技术、清华大学出版社,1996
【6】徐江海、单片机实用教程[M]、北京:
机械工业出版社,2007、
【7】肖洪兵、跟我学用单片机、北京:
北京航空航天大学出版社,2002、8
【8】夏继强、单片机实验与实践教程、北京:
北京航空航天大学出版社,2001
【9】谭浩强、C语言程序设计[M]、北京:
清华大学出版社,2000、
【11】张磊、C语言程序设计[M]、北京:
高等教育出版社,2005、
【12】严桂兰、C语言程序设计[M]、厦门:
厦门大学出版社,2006
附录源程序
/*-----------------------------------------------
名称:
液晶显示计算器
日期:
2012、11、30
内容:
整数之间运算,没有小数所有除法得出的结果不正确,有负号运算,
------------------------------------------------*/
#include//包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include
#defineKeyPortP1
#defineDataPortP0//定义数据端口程序中遇到DataPort则用P0替换
sbitLATCH1=P2^2;//定义锁存使能端口段锁存
sbitLATCH2=P2^3;//位锁存
unsignedcharcodedofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//显示段码值0~9
unsignedcharcodedofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
unsignedcharTempData[8];//存储显示值的全局变量
externunsignedcharTempData[8];//存储显示值的全局变量
externunsignedcharcodedofly_DuanMa[10];
/*------------------------------------------------
显示函数,用于动态扫描数码管
输入参数FirstBit表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
如输入0表示从第一个显示。
Num表示需要显示的位数,如需要显示99两位数值则该值输入2
------------------------------------------------*/
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsignedcharKeyScan(void);//键盘扫描函数,使用行列反转扫描法
/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsignedcharKeyPro(void);
voidDisplay(unsignedcharFirstBit,unsignedcharNum);
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
voidInit_Timer0(void);
/*------------------------------------------------
uS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar就是定义无符号字符变量,其值的范围就是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5uS
------------------------------------------------*/
voidDelayUs2x(unsignedchart);
/*------------------------------------------------
mS延时函数,含有输入参数unsignedchart,无返回值
unsignedchar就是定义无符号字符变量,其值的范围就是
0~255这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
voidDelayMs(unsignedchart);
/*------------------------------------------------
主程序
------------------------------------------------*/
main()
{
unsignedcharnum,i,sign;
unsignedchartemp[8];//最大输入8个
bitfirstflag;
inta=0,b=0;
unsignedchars;
Init_Timer0();//初始化定时器0
while
(1)//主循环
{
num=KeyPro();//扫描键盘
if(num!
=0xff)//如果扫描就是按键有效值则进行处理
{
if(i==0)//输入就是第一个字符的时候需要把改行清空,方便观瞧
{
for(s=0;s<8;s++)//赋值完成后把缓冲区清零,防止下次输入影响结果
TempData[s]=0;
}
if(('+'==num)||(i==8)||('-'==num)||('x'==num)||('/'==num)||('='==num))//输入数字最大值8,输入符号表示输入结束
{
i=0;//计数器复位
if(firstflag==0)//如果就是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b
{
sscanf(temp,"%d",&a);//从一个字符串输入到变量
firstflag=1;
}
else
sscanf(temp,"%d",&b);
for(s=0;s<8;s++)//赋值完成后把缓冲区清零,防止下次输入影响结果
temp[s]=0;
if(num!
='=')//判断当前符号位并做相应处理
sign=num;//如果不就是等号记下标志位
else
{
firstflag=0;//检测到输入=号,判断上次读入的符合
switch(sign)
{
case'+':
a=a+b;
break;
case'-':
a=a-b;
break;
case'x':
a=a*b;
break;
case'/':
a=a/b;
break;
default:
break;
}
sprintf(temp,"%d",a);//打印十进制到临时缓冲区
for(s=0;s<8;s++)//由于打印的就是ASCII码值
{
if(temp[s]==0)//所以需要转换,如果为0表示null数码管上则不能显示,所以赋值0
TempData[s]=0;
elseif(temp[s]==0x2d)//表示负号,数码管显示负号0x40
TempData[s]=0x40;
else
TempData[s]=dofly_DuanMa[temp[s]-'0'];//其她0-9负号则进行ASCII到数字处理,如当前就是'3',用'3'-'0'=3
//'3'的16进制就是0x33,'0'的16进制就是0x30
}
sign=0;a=b=0;//用完后所有数据清零
for(s=0;s<8;s++)
temp[s]=0;
}
}
elseif(i<16)
{
temp[i]=num+'0';
TempData[i]=dofly_DuanMa[num];//输出数据
i++;//输入数值累加
}
}
}
}
/*------------------------------------------------
按键扫描函数,返回扫描键值
------------------------------------------------*/
unsignedcharKeyScan(void)//键盘扫描函数,使用行列反转扫描法
{
unsignedcharcord_h,cord_l;//行列值中间变量
KeyPort=0x0f;//行线输出全为0
cord_h=KeyPort&0x0f;//读入列线值
if(cord_h!
=0x0f)//先检测有无按键按下
{
DelayMs(10);//去抖
if((KeyPort&0x0f)!
=0x0f)
{
cord_h=KeyPort&0x0f;//读入列线值
KeyPort=cord_h|0xf0;//输出当前列线值
cord_l=KeyPort&0xf0;//读入行线值
while((KeyPort&0xf0)!
=0xf0);//等待松开并输出
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff);//返回该值
}
/*------------------------------------------------
按键值处理函数,返回扫键值
可以根据需要改变返回值
|1|2|3|+|
|4|5|6|-|
|7|8|9|*|
|0|、|=|/|
------------------------------------------------*/
unsignedcharKeyPro(void)
{
switch(KeyScan())
{
case0x7e:
return1;break;//0按下相应的键显示相对应的码值
case0x7d:
return2;break;//1
case0x7b:
return3;break;//2
case0x77:
return'+';break;//3
case0xbe:
return4;break;//4
case0xbd:
return5;break;//5
case0xbb:
return6;break;//6
case0xb7:
return'-';break;//7
case