找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 29162|回复: 14
收起左侧

基于51单片机计算器设计文档

  [复制链接]
ID:3721 发表于 2016-6-12 23:46 | 显示全部楼层 |阅读模式
电气工程项目综合设计
设计文档

1.1课题简介
1.2设计目的
1.3设计任务
1.4 章节安排说明
2.1 单片机发展现状
2.2 计算器系统现状
2.3 简易计算器系统简介
3.1  MCS-51系列单片机简介
3.2 其它器件简介
3.2.1数码管显示
3.2.2矩阵按键
4.1 计算器硬件电路设计
4.2计算器程序设计
4.2.1存储单元分配
4.2.2主程序设计
4.2.3数码管显示数据转换子程序
4.2.4数码管动态显示子程序
4-3图 系统总框图:
4.4程序源代码:
4.5硬件连线图:
心得
参考文献
附件:


1.1课题简介
单片机由于其微小的体积和极低的成本,广泛的应用于家用电器、工业控制等领域中。在工业生产中。单片机微型计算机是微型计算机的一个重要分支,也是颇具生命力的机种。单片机微型计算机简称单片机,特别适用于控制领域,故又称为微控制器。
本系统就是充分利用了8051芯片的I/O引脚。系统统采用MSC-51系列单片机Intel8051为中心器件来设计计算器控制器,实现了能根据实际输入值显示并存储,计算程序则是参照教材。至于位数和功能,如果有需要可以设计扩充原系统来实现 。
1.2设计目的
通过本次工程实践,运用《智能化测量控制仪表原理与设计》、《MCS-51系列单片微型计算机及其应用》所学知识及查阅相关资料,完成简易计算器的设计,达到理论知识与实践更好结合、提高综合运用所学知识和设计能力的目的。
通过本次设计训练,可以使我们在基本思路和基本方法上对基于MCS-51单片机的嵌入式系统设计有一个比较感性的认识,并具备一定程度的设计能力。
1.3设计任务
在本次工程实践中,主要完成如下方面的设计任务:
1)简要综述单片机技术发展的国内外现状及数码管动态显示和矩阵键盘基本原理;
2)掌握MCS-51系列某种产品(例如8051)的最小电路及外围扩展电路的设计方法;
3)了解单片机数据转换功能及工作过程;
4)完成主要功能模块的硬件电路设计及必要的参数确定;
5)用protues软件完成原理电路的绘制;
6)完成系统设计说明书。
1.4 章节安排说
整个设计总共分为四个章节,第一章是前言部分,主要介绍了设计基于单片机简易计算器的意义、目的及主要内容;第二章简要介绍了单片机发展的国内外现状及键盘扫描,数据转换,和动态显示原理进行了简要的说明。第三章是器件简介,这一部分主要介绍了系统的所用主要器件的选择。第四章是系统详细设计阶段,分为硬件设计和程序设计。按照程序设计的各部分实现的功能不同,将整个软件系统分成了三个块,并对每一个功能块所采用的元器件进行了详细介绍。此外还编写了主要功能模块的基本程序,详尽阐述了各模块的工作过程。还有总流程图,源代码,硬器件铺线图。

2.1 单片机发展现状
单片机的发展趋势:低功耗CMOS化;微型单片化;主流与多品种共存;单片机从8位、16位到32位,数不胜数,应有尽有,有与主流C51系列兼容的,也有不兼容的,但它们各具特色,互成互补,为单片机的应用提供广阔的天地。
纵观单片机的发展过程,可以预示单片机的发展趋势,大致有:
1)低功耗CMOS化
    MCS-51系列的8051推出时的功耗达630mW,而现在的单片机普遍都在100mW左右,随着对单片机功耗要求越来越低,现在的各个单片机制造商基本都采用了CMOS(互补金属氧化物半导体工艺)。象80C51就采用了HMOS(即高密度金属氧化物半导体工艺)和CHMOS(互补高密度金属氧化物半导体工艺)。CMOS虽然功耗较低,但由于其物理特征决定其工作速度不够高,而CHMOS则具备了高速和低功耗的特点,这些特征,更适合于在要求低功耗象电池供电的应用场合。所以这种工艺将是今后一段时期单片机发展的主要途径。
2)微型单片化
    现在常规的单片机普遍都是将中央处理器(CPU)、随机存取数据存储(RAM)、只读程序存储器(ROM)、并行和串行通信接口,中断系统、定时电路、时钟电路集成在一块单一的芯片上,增强型的单片机集成了如A/D转换器、PMW(脉宽调制电路)、WDT(看门狗)、有些单片机将LCD(液晶)驱动电路都集成在单一的芯片上,这样单片机包含的单元电路就更多,功能就越强大。甚至单片机厂商还可以根据用户的要求量身定做,制造出具有自己特色的单片机芯片。
    此外,现在的产品普遍要求体积小、重量轻,这就要求单片机除了功能强和功耗低外,还要求其体积要小。现在的许多单片机都具有多种封装形式,其中SMD(表面封装)越来越受欢迎,使得由单片机构成的系统正朝微型化方向发展。
3)主流与多品种共存
    现在虽然单片机的品种繁多,各具特色,但仍以80C51为核心的单片机占主流,兼容其结构和指令系统的有PHILIPS公司的产品
2.2 计算器系统现状
计算器一般由运算器、控制器、存储器、键盘、显示器、电源和一些可选外围设备及电子配件通过人工或机器设备组成。低档计算器的运算器、控制器由数字逻辑电路实现简单的串行运算,其随机存储器只有一、二个单元,供累加存储用。高档计算器由微处理器和只读存储器实现各种复杂的运算程序,有较多的随机存储单元以存放输入程序和数据。键盘是计算器的输入部件,一般采用接触式或传感式。为减小计算器的尺寸,一键常常有多种功能。显示器是计算器的输出部件,有发光二极管显示器或液晶显示器等。除显示计算结果外,还常有溢出指示、错误指示等。计算器电源采用交流转换器或电池,电池可用交流转换器或太阳能转换器再充电。为节省电能,计算器都采用CMOS工艺制作的大规模集成电路(见互补金属-氧化物-半导体集成电路),并在内部装有定时不操作自动断电电路。计算器可选用的外围设备有微型打印机、盒式磁带机和磁卡机等。
2.3 简易计算器系统简介
本计算器是以MCS-51系列8051单片机为核心构成的简易计算器系统。该系统通过单片机控制,实现对4*4键盘扫描进行实时的按键检测,并把检测数据存储下来。整个计算器系统的工作过程为:首先存储单元初始化,显示初始值和键盘扫描,判断按键位置,查表得出按键值,单片机则对数据进行储存与相应处理转换,之后送入数码管动态显示。整个系统可分为三个主要功能模块:功能模块一,实时键盘扫描;功能模块二,数据转换为了数码管显示;功能模块三,数码管动态显示。
3.1  MCS-51系列单片机简介
8051是MCS-51系列单片机的典型产品,以这一代表性的机型进行系统的讲解。
   8051单片机包含中央处理器、程序存储器(ROM)、数据存储器(RAM)、定时/计数器、并行接口、串行接口和中断系统等几大单元及数据总线、地址总线和控制总线等三大总线,现在我们分别加以说明:
·中央处理器
中央处理器(CPU)是整个单片机的核心部件,是8位数据宽度的处理器,能处理8位二进制数据或代码,CPU负责控制、指挥和调度整个单元系统协调的工作,完成运算和控制输入输出功能等操作。
·数据存储器(RAM)
8051内部有128个8位用户数据存储单元和128个专用寄存器单元,它们是统一编址的,专用寄存器只能用于存放控制指令数据,用户只能访问,而不能用于存放用户数据,所以,用户能使用的RAM只有128个,可存放读写的数据,运算的中间结果或用户定义的字型表。            
1.001.jpg
图3-1 8051内部结构图
·程序存储器(ROM)
8051共有4096个8位掩膜ROM,用于存放用户程序,原始数据或表格。
·定时/计数器(ROM)
8051有两个16位的可编程定时/计数器,以实现定时或计数产生中断用于控制程序转向。
·并行输入输出(I/O)口:
8051共有4组8位I/O口(P0、 P1、P2或P3),用于对外部数据的传输。
·全双工串行口
8051内置一个全双工串行通信口,用于与其它设备间的串行数据传送,该串行口既可以用作异步通信收发器,也可以当同步移位器使用。
·中断系统:
8051具备较完善的中断功能,有两个外中断、两个定时/计数器中断和一个串行中断,可满足不同的控制要求,并具有2级的优先级别选择。
·时钟电路:
8051内置最高频率达12MHz的时钟电路,用于产生整个单片机运行的脉冲时序,但8051单片机需外置振荡电容。
单片机的结构有两种类型,一种是程序存储器和数据存储器分开的形式,即哈佛(Harvard)结构,另一种是采用通用计算机广泛使用的程序存储器与数据存储器合二为一的结构,即普林斯顿(Princeton)结构。INTEL的MCS-51系列单片机采用的是哈佛结构的形式,而后续产品16位的MCS-96系列单片机则采用普林斯顿结构。
下图是MCS-51系列单片机的内部结构示意图3-2。
1.002.jpg

图3-2 MCS-51结构图
MCS-51的引脚说明:
MCS-51系列单片机中的8031、8051及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明:
MCS-51的引脚说明:
MCS-51系列单片机中的8031、8051及8751均采用40Pin封装的双列直接DIP结构,右图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。现在我们对这些引脚的功能加以说明:如图3-3
1.003.jpg                                              
图3-3双列直插式封装引脚图
Pin9:RESET/Vpd复位信号复用脚,当8051通电,时钟电路开始工作,在RESET引脚上出现24个时钟周期以上的高电平,系统即初始复位。初始化后,程序计数器PC指向0000H,P0-P3输出口全部为高电平,堆栈指针写入07H,其它专用寄存器被清“0”。RESET由高电平下降为低电平后,系统即从0000H地址开始执行程序。然而,初始复位不改变RAM(包括工作寄存器R0-R7)的状态,8051的初始态。
8051的复位方式可以是自动复位,也可以是手动复位。此外,RESET/Vpd还是一复用脚,Vcc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。见下图3-4为两种复位方式和两种时钟方式:
1.004.jpg 1.005.jpg

·Pin30:ALE/ 1.006.jpg 当访问外部程序器时,ALE(地址锁存)的输出用于锁存地址的低位字节。而访问内部程序存储器时,ALE端将有一个1/6时钟频率的正脉冲信号,这个信号可以用于识别单片机是否工作,也可以当作一个时钟向外输出。更有一个特点,当访问外部程序存储器,ALE会跳过一个脉冲。
如果单片机是EPROM,在编程其间,将用于输入编程脉冲。            
·Pin29: 1.007.jpg 当访问外部程序存储器时,此脚输出负脉冲选通信号,PC的16位地址数据将出现在P0和P2口上,外部程序存储器则把指令数据放到P0口上,由CPU读入并执行。
·Pin31:EA/Vpp程序存储器的内外部选通线,8051和8751单片机,内置有4kB的程序存储器,当EA为高电平并且程序地址小于4kB时,读取内部程序存储器指令数据,而超过4kB地址则读取外部指令数据。如EA为低电平,则不管地址大小,一律读取外部程序存储器指令。显然,对内部无程序存储器的8031,EA端必须接地。
在编程时,EA/Vpp脚还需加上21V的编程电压。
3.2 其它器件简介3.2.1数码管显示
在本任务中用4位数码管显示当前数值的千,百,十,个,由于数码管个数多,如采用静态显示方式,则占用单片机的I/O口线太多,如果用定时器/计数器的串行移位寄存器工作方式及外接串入并出移位寄存器74LS164的方式,则电路复杂。所以,在数码管个数较多时,常采用动态显示方式。
4位数码管的相同段并联在一起,由一个8位I/O(P1口)输出字形码控制显示某一字形,每个数码管的公共端由另外一个I/O口(P0口)输出的字位码控制,即数码管显示的字形是由单片机I/O口输出的字形码确定,而哪个数码管点亮是由单片机I/O口输出的字位码确定的。4个数码管分时轮流循环点亮,在同一时刻只有1个数码管点亮,但由于数码管具有余辉特性及人眼具有视觉暂留特性,所以适当地选取循环扫描频率,看上去所有数码管是同时点亮的,察觉不出闪烁现象。动态显示方式所接数码管不能太多,否则会因每个数码管所分配的实际导通时间太少,使得数码管的亮度不足。在本任务中,为了简便,字形码和字位码都没由加驱动电路,在实际应用中应加驱动电路。数码管有共阴极和共阳极两种,对于共阳数码管,字形驱动输出0有效,字位驱动输出1有效;而对于共阴数码管则相反,即:字形驱动输出1有效,字位驱动输出0有效。
3.2.2矩阵按键
键盘是单片机系统中最常用的人机对话输入设备,用户通过键盘向单片机输入数据或指令。键盘控制程序需完成的任务有:监测是否有键按下,有键按下时,在无硬件去抖的动电路时,应用软件延时方法消除按键抖动影响;当有多个键同时按下时,只处理一个按键,不管一次按键持续多长时间,仅执行一次按键功能程序。
矩阵按键扫描程序是一种节省IO口的方法,按键数目越多节省IO口就越可观,思路:先判断某一列(行)是否有按键按下,再判断该行(列)是那一只键按下。但是,在程序的写法上,采用了最简单的方法,使得程序效率最高。本程序中,如果检测到某键按下了,就不再检测其它的按键,这完全能满足绝大多数需要,又能节省大量的CPU时间。
本键盘扫描程序的优点在于:不用专门的按键延时程序,提高了CPU效率,也不用中断来扫描键盘,节省了硬件资源。另外,本键盘扫描程序,每次扫描占用CPU时最短,不论有键按下或者无键按下都可以在很短的时间完成一次扫描。
本键盘扫描子程序名叫key,每次要扫描时用lcall key调用即可.

4.1 计算器硬件电路设计
8051单片机一片,4*4键盘一个,4位共阳极的七段数码管一个,连线和电阻和开关若干。8051单片机的P2口作键盘口,其中P2.4-P2.7为键盘扫描输出线,P2.0-P2.3为键盘扫描输入线。键盘由4*4共16个按键组成,10个数字键(由0-9组成)5个运算符号(加减乘除等于)组成,1个清除键(作用相当于整体复位)。4个数码管用于显示当前数值的千,百,十,个,采用动态显示方式,P1口接4个数码管的七段,P0口分别接4个数码管的公共端,P1口输出数码管的字形码,P0口输出数码管的字位码。
4.2计算器程序设计4.2.1存储单元分配
30H单元:数值个位显示单元;31H单元:数值十位显示单元;32H单元:数值百位显示单元;33H单元:数值千位显示单元;23H单元:第一操作数存储单元;24H单元:第二操作数存储单元;25H单元:键值暂存单元;27H单元:清除键状态;34H-37H单元:结果数据转换暂存单元;38H-39H单元:结果高低8位暂存单元;R5单元:操作数计数单元;R4单元:操作数数值位数计数单元;R3单元:运算符号存储单元。
4.2.2主程序设计
主程序进行程序中用到的一些存储单元的初始化,数值显示和4*4键盘扫描。首先,进行存储单元初始化,给数码管显示单元30H-33H赋予“0000”字形数据,将数值计数单元,存储单元,23H-25H,34H-37H,38H,39H,3AH,3BH,3CH,赋予初值零。之后,调用键盘扫描子程序,和数码管显示数据转换程序,数码管动态显示子程序。主程序不断进行键盘扫描,数码管显示数据转换子程序和动态显示子程序。
4.2.3数码管显示数据转换子程序
由于数值单元存放的是二进制数,而用户熟悉的是十进制数,所以应将数值单元中的二进制转换为十进制数,即BCD码。要通过数码管显示出当前数值,还必须将BCD码进一步转换为七段码,转换的最终结果数据存放于显示缓冲区30H-33H单元中,其中30H单元存放数值的个位七段码,31H单元存放数值的十位七段码,32H单元存放数值的百位七段码,33H单元存放数值的千位七段码。
4.2.4数码管动态显示子程序
本任务由P1口输出字形码,P0口输出字位码。先将存放于30H单元的数值个位七段码由P1口输出,同时P0口输出使数值个位显示数码管点亮的字位码。由于采用的是共阳数码管,所以只有该位数码管对应的P0.0为1,其他位P0.1-P0.3位0,点亮延时10MS。然后P1口输出数值十位七段码,P0.1位1,数值十位数码管点亮,延时10MS。接着P1口输出数值百位七段码,P0.2为1,数值百位数码管点亮,延时10MS。最后P1口输出数值千位七段码,P0.3为1,数值千位数码管点亮,延时10MS。
1.008.jpg
                                  4-3系统总框图:
4.4程序源代码
1.009.jpg
                                            图4-4 程序输入导出hex文件


4.5硬件连线图
1.010.jpg
心得
设计是培养学生综合运用所学知识,发现,提出,分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际工作能力的具体训练和考察过程.随着科学技术发展的日新日异,单片机已经成为当今计算机应用中空前活跃的领域, 在生活中可以说得是无处不在。因此作为二十一世纪的大学来说掌握单片机的开发技术是十分重要的。
回顾起此次单片机设计,我仍感慨颇多,的确,从选题到定稿,从理论到实践,可以说得是苦多于甜,但是可以学到很多很多的的东西。通过这次设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。通过这次设计使我得到了一次用专业知识、专业技能分析和解决问题全面系统的锻炼。使我们在单片机的基本原理、单片机应用系统开发过程,以及在常用编程设计思路技巧的掌握方面都能向前迈了一大步,为日后成为合格的应用型人才打下良好的基础。
参考文献
[1] 徐爱钧 .智能化测量控制仪表原理与设计(第二版).北京航天航空大学出版社,2004.9
[2] 孙育才等.MCS-51系列单片微型计算机及其应用(第4版).东南大学出版社,2004,3
[3] 李萍 等.智能仪器实验指导书.大连交通大学,2007.9

[4]王明亮等. 广播.电视调频发送技术,上、下册. 北京: 中国广播电视出版社,1993

[5]梁延贵. 遥控电路可控硅触发电路语音电路分册 北京: 科学技术文献出版社,2002

[6] 李华. MCS-51系列单片机实用接口技术. 北京: 航天航空大学出版社,1999

[7] 邱关源.电路.高等教育出版社.1989.第三版.

[8] 焦李成.电流模式信号处理的进展与展望.电子学报.1992.20(7):87-92

[9] 张肃文,陆兆文. 高频电子电路.高等教育出版社.1993.第三版.

[10] 康光华,陈大钦. 电子技术基础(模拟部分).高等教育出版社.1999.6.第四版.

[11] 陈汝全.  电子技术常用器件手册.北京:机械工业出版社,1994

[12] 鲁兵,杨楚民. 基于单片机系统的显示接口.机械与电子出版社,1992

评阅人:
   年   月   日


  1. #include   //头文件
  2. #define uint unsigned int //
  3. #define uchar unsigned char

  4. sbit lcden=P2^3; //定义引脚
  5. sbit rs=P2^4;
  6. sbit rw=P2^0;
  7. sbit busy=P0^7;

  8. char i,j,temp,num,num_1;
  9. long a,b,c;     //a,第一个数 b,第二个数 c,得数
  10. float a_c,b_c;
  11. uchar flag,fuhao;//flag表示是否有符号键按下,fuhao表征按下的是哪个符号

  12. uchar code table[]={
  13. 7,8,9,0,
  14. 4,5,6,0,
  15. 1,2,3,0,
  16. 0,0,0,0};
  17. uchar code table1[]={
  18. 7,8,9,0x2f-0x30,
  19. 4,5,6,0x2a-0x30,
  20. 1,2,3,0x2d-0x30,
  21. 0x01-0x30,0,0x3d-0x30,0x2b-0x30};

  22. void delay(uchar z) // 延迟函数
  23. {
  24. uchar y;
  25. for(z;z>0;z--)
  26.    for(y=0;y<110;y++);
  27. }

  28. void check() // 判断忙或空闲
  29. {
  30. do{
  31.     P0=0xFF;
  32.     rs=0;     //指令
  33.     rw=1;     //读
  34.     lcden=0;     //禁止读写
  35.     delay(1); //等待,液晶显示器处理数据
  36.     lcden=1;     //允许读写
  37.     }while(busy==1); //判断是否为空闲,1为忙,0为空闲
  38. }
  39. void write_com(uchar com) // 写指令函数
  40. {
  41. P0=com;    //com指令付给P0口
  42. rs=0;
  43. rw=0;
  44. lcden=0;
  45. check();
  46. lcden=1;
  47. }

  48. void write_date(uchar date) // 写数据函数
  49. {
  50.     P0=date;
  51. rs=1;
  52. rw=0;
  53. lcden=0;
  54. check();
  55. lcden=1;
  56. }

  57. void init() //初始化
  58. {
  59.     num=-1;
  60. lcden=1; //使能信号为高电平
  61. write_com(0x38); //8位,2行
  62. write_com(0x0c); //显示开,光标关,不闪烁*/
  63. write_com(0x06); //增量方式不移位 显竟獗暌贫 柚?
  64. write_com(0x80); //检测忙信号
  65. write_com(0x01); //显示开,光标关,不闪烁
  66. num_1=0;
  67. i=0;
  68. j=0;
  69. a=0;     //第一个参与运算的数
  70. b=0;     //第二个参与运算的数
  71. c=0;
  72. flag=0; //flag表示是否有符号键按下,
  73. fuhao=0; // fuhao表征按下的是哪个符号
  74. }
  75. void keyscan() // 键盘扫描程序
  76. {

  77. P3=0xfe;
  78. if(P3!=0xfe)
  79. {
  80.    delay(20); 延迟20ms
  81.    if(P3!=0xfe)
  82.    {
  83.     temp=P3&0xf0;
  84.     switch(temp)
  85.     {
  86.      case 0xe0:num=0;
  87.        break;
  88.      case 0xd0:num=1;
  89.        break;
  90.      case 0xb0:num=2;
  91.        break;
  92.      case 0x70:num=3;
  93.        break;
  94.     }
  95.    }
  96.    while(P3!=0xfe);
  97.    if(num==0||num==1||num==2)//如果按下的是'7','8'或'9
  98.    {
  99.        if(j!=0)
  100.         {
  101.           write_com(0x01);
  102.           j=0;
  103.          }
  104.        if(flag==0)//没有按过符号键
  105.     {
  106.      a=a*10+table[num];
  107.     }
  108.     else//如果按过符号键
  109.     {
  110.      b=b*10+table[num];
  111.     }
  112.    }
  113.    else//如果按下的是'/'
  114.    {
  115.     flag=1;
  116.     fuhao=4;//4表示除号已按
  117.    }
  118.    i=table1[num];
  119.    write_date(0x30+i);
  120. }

  121. P3=0xfd;
  122. if(P3!=0xfd)
  123. {
  124.    delay(5);
  125.    if(P3!=0xfd)
  126.    {
  127.     temp=P3&0xf0;
  128.     switch(temp)
  129.     {
  130.      case 0xe0:num=4;
  131.          break;
  132.       
  133.      case 0xd0:num=5;
  134.          break;
  135.       
  136.      case 0xb0:num=6;
  137.          break;
  138.       
  139.      case 0x70:num=7;
  140.          break;
  141.     }
  142.    }
  143.    while(P3!=0xfd);
  144.    if(num==4||num==5||num==6&&num!=7)//如果按下的是'4','5'或'6'
  145.    {
  146.     if(j!=0)
  147.         {
  148.           write_com(0x01);
  149.           j=0;
  150.          }
  151.        if(flag==0)//没有按过符号键
  152.     {
  153.      a=a*10+table[num];
  154.     }
  155.     else//如果按过符号键
  156.     {
  157.      b=b*10+table[num];
  158.     }
  159.    }
  160.    else//如果按下的是'/'
  161.    {
  162.     flag=1;
  163.     fuhao=3;//3表示乘号已按
  164.    }
  165.    i=table1[num];
  166.    write_date(0x30+i);
  167. }

  168. P3=0xfb;
  169. if(P3!=0xfb)
  170. {
  171.    delay(5);
  172.    if(P3!=0xfb)
  173.    {
  174.     temp=P3&0xf0;
  175.     switch(temp)
  176.     {
  177.      case 0xe0:num=8;
  178.          break;
  179.       
  180.      case 0xd0:num=9;
  181.          break;
  182.       
  183.      case 0xb0:num=10;
  184.          break;
  185.       
  186.      case 0x70:num=11;
  187.          break;
  188.     }
  189.    }
  190.    while(P3!=0xfb);
  191.    if(num==8||num==9||num==10)//如果按下的是'1','2'或'3'
  192.    {
  193.     if(j!=0)
  194.         {
  195.           write_com(0x01);
  196.           j=0;
  197.          }
  198.       if(flag==0)//没有按过符号键
  199.     {
  200.      a=a*10+table[num];
  201.     }
  202.     else//如果按过符号键
  203.     {
  204.      b=b*10+table[num];
  205.     }
  206.    }
  207.    else if(num==11)//如果按下的是'-'
  208.    {
  209.     flag=1;
  210.     fuhao=2;//2表示减号已按
  211.    }
  212.    i=table1[num];
  213.    write_date(0x30+i);
  214. }

  215. P3=0xf7;
  216. if(P3!=0xf7)
  217. {
  218.    delay(5);
  219.    if(P3!=0xf7)
  220.    {
  221.     temp=P3&0xf0;
  222.     switch(temp)
  223.     {
  224.      case 0xe0:num=12;
  225.          break;
  226.       
  227.      case 0xd0:num=13;
  228.          break;
  229.       
  230.      case 0xb0:num=14;
  231.          break;
  232.       
  233.      case 0x70:num=15;
  234.          break;
  235.     }
  236.    }
  237.    while(P3!=0xf7);
  238.    switch(num)
  239.    {
  240.     case 12:{write_com(0x01);a=0;b=0;flag=0;fuhao=0;}//按下的是"清零"
  241.      break;
  242.     case 13:{                //按下的是"0"
  243.        if(flag==0)//没有按过符号键
  244.        {
  245.         a=a*10;
  246.         write_date(0x30);
  247.         P1=0;
  248.        }
  249.        else if(flag==1)//如果按过符号键
  250.        {
  251.         b=b*10;
  252.         write_date(0x30);
  253.         }
  254.       }
  255.      break;
  256.     case 14:{j=1;
  257.            if(fuhao==1){write_com(0x80+0x4f);//按下等于键,光标前进至第二行最后一个显示处
  258.            write_com(0x04);     //设置从后住前写数据,每写完一个数据,光标后退一格
  259.            c=a+b;
  260.            while(c!=0)
  261.            {
  262.              write_date(0x30+c%10);
  263.              c=c/10;
  264.            }
  265.            write_date(0x3d);     //再写"="
  266.            a=0;b=0;flag=0;fuhao=0;
  267.            }
  268.       else if(fuhao==2){write_com(0x80+0x4f);//光标前进至第二行最后一个显示处
  269.             write_com(0x04);     //设置从后住前写数据,每写完一个数据,光标后退一格(这个照理说顺序不对,可显示和上段一样)
  270.            if(a-b>0)
  271.              c=a-b;
  272.            else
  273.              c=b-a;
  274.            while(c!=0)
  275.            {
  276.              write_date(0x30+c%10);
  277.              c=c/10;
  278.            }
  279.            if(a-b<0)
  280.              write_date(0x2d);
  281.            write_date(0x3d);     //再写"="           
  282.            a=0;b=0;flag=0;fuhao=0;
  283.           }
  284.       else if(fuhao==3){write_com(0x80+0x4f);
  285.             write_com(0x04);
  286.              c=a*b;
  287.              while(c!=0)
  288.              {
  289.              write_date(0x30+c%10);
  290.              c=c/10;
  291.              }
  292.              write_date(0x3d);     
  293.           a=0;b=0;flag=0;fuhao=0;
  294.              }
  295.       else if(fuhao==4){write_com(0x80+0x4f);
  296.             write_com(0x04);
  297.             i=0;
  298.             c=(long)(((float)a/b)*1000);
  299.             while(c!=0)
  300.              {
  301.                write_date(0x30+c%10);
  302.                c=c/10;
  303.            i++;
  304.            if(i==3)
  305.                write_date(0x2e);
  306.              }
  307.             if(a/b<=0)
  308.               write_date(0x30);
  309.             write_date(0x3d);                              
  310.             a=0;b=0;flag=0;fuhao=0;
  311.                     }
  312.       }
  313.      break;
  314.      case 15:{write_date(0x30+table1[num]);flag=1;fuhao=1;}
  315.      break;
  316.    }
  317. }
  318. }

  319. main()
  320. {
  321. init();
  322. while(1)
  323. {
  324.    keyscan();
  325. }
  326. }
复制代码

word格式下载: 基于51单片机计算器设计.docx (191.92 KB, 下载次数: 115)
回复

使用道具 举报

ID:126449 发表于 2016-6-13 00:48 来自手机 | 显示全部楼层
好棒,顶一个
回复

使用道具 举报

ID:126696 发表于 2016-6-14 16:20 来自手机 | 显示全部楼层
真是大好人啊 论文都给了
回复

使用道具 举报

ID:128087 发表于 2016-6-25 15:25 来自手机 | 显示全部楼层
感谢楼主 !!!
回复

使用道具 举报

ID:145691 发表于 2016-11-2 13:59 | 显示全部楼层
能不能进行负数计算
回复

使用道具 举报

ID:145691 发表于 2016-11-2 14:27 | 显示全部楼层
程序为啥会出错呢
回复

使用道具 举报

ID:200060 发表于 2017-6-7 22:22 | 显示全部楼层
为什么我的电路图出不来
回复

使用道具 举报

ID:219259 发表于 2017-7-12 23:02 | 显示全部楼层
led不显示怎么办啊
回复

使用道具 举报

ID:219418 发表于 2017-7-13 22:28 | 显示全部楼层
棒棒棒,顶顶顶
回复

使用道具 举报

ID:244546 发表于 2017-11-1 11:24 | 显示全部楼层
仿真用的数码管 怎么看源码用的液晶
回复

使用道具 举报

ID:247636 发表于 2017-11-10 09:24 来自手机 | 显示全部楼层
谢谢楼主分享
回复

使用道具 举报

ID:361498 发表于 2018-6-29 10:26 | 显示全部楼层
为什么显示不出来
回复

使用道具 举报

ID:777318 发表于 2020-6-12 16:10 | 显示全部楼层
明天你好LJN 发表于 2017-6-7 22:22
**** 作者被禁止或删除 内容自动屏蔽 ****

我的P0也是灰色的
回复

使用道具 举报

ID:777318 发表于 2020-6-12 16:49 | 显示全部楼层
这个P0是悬空的啊,怎么亮起来的啊?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表