单片机计算器设计.docx
《单片机计算器设计.docx》由会员分享,可在线阅读,更多相关《单片机计算器设计.docx(21页珍藏版)》请在冰点文库上搜索。
单片机计算器设计
目录
第1章绪论2
§1.1设计的意义2
§1.2要解决的问题2
§1.3计算器发展概况2
第2章需求分析3
§2.1计算器设计要求3
§2.2程序开发环境3
§2.3计算器原理图3
§2.3.1键盘系统分析4
§2.3.2LED显示灯系统分析5
第3章计算器程序设计7
§3.1总体设计7
§3.2硬件设计7
§3.3软件设计8
§3.3.1软件模块划分8
§3.3.2软件流程设计9
第4章测试分析10
第5章总结12
参考文献13
附录14
第1章绪论
§1.1设计的意义
随着科学技术的飞速发展,单片机具有集成度高、功能强、结构简单、易于掌握、应用灵活、可靠性高、价格低廉等优点,在工业控制、机电一体化、通信终端、智能仪表、家用电器等诸多领域得到了广泛的应用,已成为传统机电设备向智能化机电设备转变的重要手段。
单片机的应用正在不断加深,同时带动传统控制检测技术日益跟新。
在实时检测和自动控制的单片机系统中,单片机往往作为一个核心部件来使用,仅单片机方面的知识是不够的,还应根据具体硬件结构软硬结合,加以完善。
本任务是简易的一位数的四则运算,程序是根据教材内容参考编写而成的,在功能上还不完善,限制也比较多。
§1.2要解决的问题
计算器以AT89S52单片机为核心芯片,通过扫描键盘来得到数据,将得到数据按要求进行运算并将结果送到显示电路进行显示。
§1.3计算器发展概况
提起计算器,值得我们骄傲的是最早的计算工具诞生在中国。
中国古代最早采用的一种计算工具叫筹策,又叫做算筹,这种算筹多用竹子制成,也有用木头、兽骨充当材料的,约270,枚一束,放在布袋里克随身携带。
17世纪初,西方国家的计算工具有了较大的发展,英国数学家纳皮尔发明的“纳皮尔算筹”,英国牧师奥却德法发明了圆柱形对数计算尺,这种计算尺不仅能做加减乘除、乘方、开方运算,甚至可以计算三角函数、指数函数和对数函数,这些计算工具不仅带动了计算机的发展,也为现代计算器的发展奠定了良好的基础,计算器已经成为现代社会应用广泛的计算工具。
第2章需求分析
§2.1计算器设计要求
基于AT89S52单片机的简易计算器,采用22.1184MHZ晶振。
设计要求如下:
(1)计算器能正常显示输入数据和得到的结果
(2)计算器能对1位整数进行简单的加、减、乘、除四则运算,在做除法时能自动舍去小数部分。
§2.2程序开发环境
1.硬件:
PC机一台,实验开发板CS-1。
2.软件Windows98/XP系统,KEIL集成开发环境,ISP下载软件。
§2.3计算器原理图
基于AT89S52单片机的简易计算器由电源电路、单片机主控电路、按键电路、显示电路和复位电路几部分组成,框图组成如图2-1所示。
图2-1基于AT89S52单片机的简易计算器系统框图
由实验板CS-1电路原理图可知AT89S52的P0端口连接的数码管显示,P2端口连接的是键盘,于是在计算器程序的设计中,我们可以通过定时器调用中断,不断的向P0端口输出电平,来显示我们所要显示的数字。
然后通过P2端口来获得键盘的输入。
图2-2基于AT89S52单片机简易计算器电路原理图
§2.3.1键盘系统分析
图3.3.1键盘结构图
实验板上是一个4*4的键盘矩阵,可以采用逐行扫描或全扫描的方式实现按键的读取,行线和列线加驱动后空载时为高电平,逐行扫描的方法为逐行使行线的每位为低,再判断列线的返回信号,如果没有键按下,返回的信号全为高;如果返回的信号中有列线为低,那么肯定是有按键按下,根据列线和行线的交点可以判断按键的具体位置。
全扫描的方法为先行线全为低,判断列线,如果列线有为低的,则可以判断有键按下,此时还不能判断某列的具体的键和行,还需反过来将列线全为低,再判断具体的行,根据行列即确定具体的按键。
§2.3.2LED显示灯系统分析
LED数码管也称半导体数码管,是目前数字电路中最常用的显示器件。
它是以发光二极管作笔段并按共阴极方式或共阳极方式连接后封装而成的。
图5-41所示是两种LED数码管的外形与内部结构,+、-分别表示公共阳极和公共阴极,a~g是7个笔段电极,DP为小数点。
LED数码管型号较多,规格尺寸也各异,显示颜色有红、绿、橙等。
从上图可以看出,要使数码管显示数字,有两个条件:
1、是要在VT端(3.8脚)加正电源;2、要使(a,b,c,d,e,f,g,dp)端接高电平或“1”电平,这样才能显示的。
数码管内部为8个发光二极管,并排列为8字形,同时加一个位表示小数点,通过这8个发光二极管的合理组合,可以构成不同的数字字型和简单的字母字型,同时数码管还有一个位选信号。
即8个数码管的公共端,数码管分为共阳和共阴两种,也就是说高电平选中或低电平选中。
每个数码管都有a、b、c、d、e、f、g七个笔划和一个小数点dp,这八个点对应二极管阳极,阴极都联在一起(称共阴极)。
以四位数码管矩阵为例,四个数码管的a、b、c、d、e、f、g七个笔划和一个小数点DP电极分别并联在一起。
当c行高电平,3列低电平,其他行列都为高阻态时,第三个数码管的c笔划亮,通过扫描方式在短时间内八个数码管的笔划该亮的都亮一次,由于视觉暂留,就会看到结果。
第3章计算器程序设计
§3.1总体设计
主要用到的硬件:
AT89S52LED数码管显示器编码键盘
硬件分配:
1、P0、P1口:
作为输出口,控制LED数码管显示数据的结果。
2、P2口:
作为输入口,与键盘连接,实现数据的输入。
§3.2硬件设计
LED数码管显示模块:
图3.2-1实验板LED灯模块
单片机AT89S52P1口接LED的位码,P0口段码,通过计数器0调用中断来显示当前数据,计数时间为20ms。
LED显示器由七段发光二极管组成,排列成8字形状,因此也成为七段显示器。
为了显示数字或符号,要为LED显示器提供代码,即字形代码。
七段发光二极管,再加上一个小数点位,共计8段,因此提供的字形代码的长度正好是一个字节。
简易计算器用到的数字0~9的共阴极字形代码如下表:
显示字型
h
g
f
e
d
c
b
a
段码
0
0
1
1
1
1
1
1
1
7EH
1
1
0
1
1
1
1
1
0
BEH
2
1
1
0
1
1
1
1
0
DEH
3
1
1
1
0
1
1
1
0
EEH
4
0
1
1
1
1
1
0
1
7DH
5
1
0
1
1
1
1
0
1
BDH
6
1
1
0
1
1
1
0
1
DDH
7
0
1
1
1
1
1
0
1
EDH
8
0
1
1
1
1
0
1
1
7BH
9
1
0
1
1
1
0
1
1
BBH
表3.2-10~9共阳极字形代码表
键盘模块设计:
图3.2-1键盘模块
单片机P2口连接键盘,通过P2口读取键盘信息。
首先利用P2口低字节读取键盘行信息,判断是否有按键被按下,若有则利用P2继续读取高字节信息,然后和低字节的信息相异或得到按键码。
获取按键码的程序由单片机主程序循环调用。
§3.3软件设计
由于本设计主要是算法问题,所以程序采用汇编语言编写。
主函数对单片机进行初始化,并不断调用扫描函数和运算函数。
显示函数采用20ms定时中断来对显示数据进行实时跟新。
§3.3.1软件模块划分
程序主要分成显示模块、按键扫描模块、计算模块。
基于AT89S52单片机简易计算器程序模块划分及简要流程图如3-3所示。
图3.3-1程序模块划分
§3.3.2软件流程设计
图3.3.2-1计算器程序流程图
第4章测试分析
一、对一位数加减乘除四则运算法则的测试:
测试发现问题:
测试1:
输入运算符时,LED数码管没有显示出输入的运算符,而是出现的乱码。
错误代码如下:
cjnea,#0x79,next2;判断控制键类型
mova,buffer;如果是等号键,将两数相加
adda,buffer_num
movbuffer,#0x00;清楚第一个操作数
movdptr,#dis_number;查找当前运算结果对应的字符码
movca,@a+dptr
movbuffer_dis,a;将当前运算结果的字符码送显示缓冲区
分析源代码后可知,代码中没有判断运算符号的部分,此时也没有有将输入的运算符号送入显示缓存区。
于是我们对代码进行修改,加入运算符判断类型的代码,判断之后对执行相应的运算操作。
测试2:
计算器无法实现连加现象。
例如:
顺序输入1+2=之后会显示结果为4,然后继续输入+1,结果并不为5。
错误原因分析,在获得结果4之后没有将数据4放入操作数缓存。
于是我在等号运算执行后的代码下面加上将计算机结果放入操作书缓存的代码,以此来实现计算器连加的功能。
测试3:
无法识别按键9。
错误代码如下:
;在数码管上显示按下的键
search:
movtemp,r5;保存扫描码
movdptr,#key;取键盘码数组的地址
movr6,#0x00
nextone:
clra
movca,@a+dptr;取键盘码
incdptr
incr6
cjner6,#0x0A,num_key;判断是数字还是控制键
分析代码可知,在判断按键是控制键还是数字键的时候,我对按键进行匹配时,将r6会小于0X0A的数字认为是数字键,但是r6的初始值并不为0。
所以,应该是r6小于0x0B的都为数字键。
这里将#0x0A改为#0x0B即可
测试4:
对正常一位数的加、减、乘、除进行测试。
若除数为0则出现错误结果,错用一个小数区减大数,仍会出错误结果。
除以上两种情况外,其余测试均正常通过。
第5章总结
课程设计是培养学生运用综合运用所学知识,发现、提出、分析和解决实际问题,锻炼实际能力的重要环节,是对我们实际工作能力的具体训练和考察过程。
随着科学技术发展的日新月异,单片机已经成为当今计算机应用中空前活跃的领域,在生活中无处在。
作为计算机专业的学生来说单片机的开发技术十分重要。
我做的题目是基于AT89S52单片机的简易计算器设计,对于我们这些实践中的新手来说,这是一次考验。
怎样才能找到课堂所学与实践运用的最佳结合点。
这都是我们要考虑和努力的。
在此次课程设计中,通过老师的精心指导和在网上找的资料,主要掌握了数码管显示的编程,数据在内部运算的编程方法。
调试也是此次的重点,这其中最重要的就是软件的调试了,也是我此次问题出现最多的地方。
这要求我们对每个模块在整个程序中的作用的了如指掌。
通过此次课程设计,我发现我对程序的掌握还不够,尤其是单片机汇编语言掌握的不牢固。
这次课程设计使我懂得实践的重要性,只有理论知识远远不够,只有把所学的理论知识与实践相结合才能算是掌握了所学的知识。
随着就业形势的日趋严峻,大学生的动手能力、实际能力和综合素质越来越受到学校和用人单位的重视。
此次设计单片机十分简易,只实现1位数的加减乘除,并且还有结果不能得到负数和除数不能为0的Bug,所以这次我们设计的计算器是并不实用的,但是同过本次课程设计,使我了解到了如何使用单片机来进行计算器的设计,学会了如何对LED灯进行控制,也学会了如何使用键盘来获得输入的数据,同时提高了我的编码能力。
在设计计算器的过程中运动了很多问题,解决了这些问题之后,提高了我们自己动手解决问题的能力。
这次单片机设计中使我对步进机有了更深的了解,对单片机也有了更高层次的了解。
单片机编程需要对电路进行认真的分析,然后画出流程图,善于查阅相关资料才能编出好的程序。
这次单片机应用系统设计中遇到到很大的困难,主要原因是平时的知识掌握的不够,通过查阅很多资料和类似的论文,才做成的。
由于时间仓促,经验少,知识局限,设计有一定的不足。
但通过此次设计自己的能力提高了不少,我会认真总结设计中的经验教训,为以后更多的设计做好铺垫。
参考文献
[1]冯育长主编.单片机系统设计与实例分析.西安:
西安电子科技大学出版社,2007[2]谢维成,杨加国主编.单片机原理与应用及C51程序设计.北京:
清华大学出版社,2006.[3]王思明,张金敏主编.单片机原理及应用.兰州大学出版社,2001年[4]宋晖,余张国主编。
单片机原理与应用。
电子科技大学出版社,2008年
附录
程序清单如下:
tempequ0x10;自定义变量temp,指向片内ram的10h地址
buffer_disequ0x11;显示字符缓冲区
buffer_conequ0x12;控制键缓冲区
buffer_numequ0x13;按键值缓冲区
bufferequ0x14;首个操作数16进制值
buffer_oprequ0x15;记录操作运算符
org0x00;程序入口
sjmpstart;跳到主程序执行
org0x000b;定时器/计数器0中断入口
ljmptimer0_over
org0x30;程序代码部分
/*******************************************************
名称:
主程序
功能:
应用程序入口
*******************************************************/
start:
movsp,#0x30;初始化堆栈
movTL0,#0xD8;置定时器初值(中断时间为25ms)
movTH0,#0xF0
movTMOD,#0x01;设定定时器/计数器0工作方式为1
setbEA;允许中断
setbET0;允许定时器/计数器0溢出中断
setbTR0;启动定时器/计数器0
movbuffer_dis,#0x00
movP1,#0xDF;打开开?
65个数码管214365
loop:
acallsea_key
sjmploop、
/*******************************************************
名称:
字形码扫描模块
功能:
判断当前按键是数字还是字符,如果是字符;将当前按
键的字形码存入buffer_dis,并且当前按键的十六进制值
存入buffer_num,如果是控制键,将控制键存入buffer_con
如果控制键为不为等号,则将运算符存入buffer_opr
入口:
sea_key
*******************************************************/
sea_key:
acallscan;调用键盘扫描子程序
acalldelay
cjner5,#0xFF,search;有键按下转到search
sjmpsea_key;无键按下继续扫描
;在数码管上显示按下的键
search:
movtemp,r5;保存扫描码
movdptr,#key;取键盘码数组的地址
movr6,#0x00
nextone:
clra
movca,@a+dptr;取键盘码
incdptr
incr6
cjner6,#0x0B,num_key;判断是数字还是控制键
;控制键处理
con_key:
cjnea,temp,nextone;与扫描码比较,不等取下一个键盘码
mova,#0Fh
movca,@a+dptr;取对应的数码
movbuffer_con,a;控制键存入缓冲区
cjnea,#0x71,noequl
jmpequl
noequl:
movbuffer_opr,a
equl:
acallcontrol;调用控制键处理模块
ret
;数字键处理程序
num_key:
jnccon_key
cjnea,temp,nextone;与扫描码比较,不等取下一个键盘码
;相等
mova,#0Fh
movca,@a+dptr;取对应的数码
movbuffer_dis,a;送显示缓冲区
decr6
movbuffer_num,r6;当前按键的16进制值送缓冲区
ret
/*******************************************************
名称:
键盘码扫描模块
功能:
获取当前的按键
入口:
scan
返回值:
r5:
返回当前按键的键值,若无键按下,返回0xFF
*******************************************************/
scan:
movP2,#0xF0;扫描低字节
mova,P2;读出当前P2口值
cjnea,#0xF0,next_key;不等于输出状态,跳至有键按下状态
sjmpno_down;扫描结束,跳到无键按下状态
next_key:
movP2,#0x0F;扫描高字节
movr5,P2;读出当前P2口值
xrla,r5;两次读取的值相异或得当前按键的键值
movr5,a;当前键值送r5保存
ret
no_down:
movr5,#0xFF;返回无键按下状态
ret
/*******************************************************
名称:
基本延时模块
功能:
利用软件的方法实现延时
入口:
delay
返回值:
无
*******************************************************/
delay:
movr3,#0xFF;传送数据,1t
dl2:
movr4,#0xFF;传送数据,1t
dl1:
nop;空指令,1t
nop;空指令,1t
djnzr4,dl1;不为0转,为0顺执,需要2t
djnzr3,dl2;不为0转,为0顺执,需要2t
ret;返回需2t
/*******************************************************
名称:
控制键处理模块
功能:
根据运算符实现两数的加减乘除
入口:
control
返回值:
无
*******************************************************/
control:
movbuffer_dis,buffer_con;当前控制键送显示缓冲区
mova,buffer_con
cjnea,#0x77,next1;判断控制键类型,加号77A+7CB-39C*5ED/71F=
movbuffer_dis,#0x77
next1:
cjnea,#0x7C,next2
movbuffer_dis,#0x7C
next2:
cjnea,#0x39,next3
movbuffer_dis,#0x39
next3:
cjnea,#0x5E,next4
movbuffer_dis,#0x5E
next4:
;movbuffer_dis,
cjnea,#0x71,ending
mova,buffer_opr
cjnea,#0x77,subex
mova,buffer;如果是等号键,将两数相加
adda,buffer_num
movbuffer_num,a
movbuffer,#0x00;清楚第一个操作数
movdptr,#dis_number;查找当前运算结果对应的字符码
movca,@a+dptr
movbuffer_dis,a;将当前运算结果的字符码送显示缓冲区
subex:
mova,buffer_opr
cjnea,#0x7C,mulex
mova,buffer;如果是等号键,将两数相加
subba,buffer_num
movbuffer_num,a
movbuffer,#0x00;清楚第一个操作数
movdptr,#dis_number;查找当前运算结果对应的字符码
movca,@a+dptr
movbuffer_dis,a;将当前运算结果的字符码送显示缓冲区
mulex:
mova,buffer_opr
cjnea,#0x39,divex
mova,buffer;如果是等号键,将两数相加
movb,buffer_num
mulab
movbuffer_num,a
movbuffer,#0x00;清楚第一个操作数
movdptr,#dis_number;查找当前运算结果对应的字符码
movca,@a+dptr
movbuffer_dis,a;将当前运算结果的字符码送显示缓冲区
divex:
mova,buffer_opr
cjnea,#0x5E,ending
mova,buffer;如果是等号键,将两数相加
movb,buffer_num
divab
movbuffer_num,a
movbuffer,#0x00;清楚第一个操作数
movdptr,#dis_number;查找当前运算结果对应的字符码
movca,@a+dptr
movbuffer_dis,a;将当前运算结果的字符码送显示缓冲区
ending:
movbuffer,buffer_num;如果不是等号键,保存当前输入的数字的十六进制值
ret
/*******************************************************
名称:
定时器0中断服务程序
功能:
显示显示缓冲区中的字符码
入口:
无
返回值:
无
*******************************************************/
timer0_over:
movP0,buffer_dis
movTL0,#0xD8;重新设定时器/计数器0初值
movTH0,#0xF0
reti;中断服务返回
;**********************************************************