基于单片机的多功能计算器设计完整程序注释版.docx
《基于单片机的多功能计算器设计完整程序注释版.docx》由会员分享,可在线阅读,更多相关《基于单片机的多功能计算器设计完整程序注释版.docx(55页珍藏版)》请在冰点文库上搜索。
![基于单片机的多功能计算器设计完整程序注释版.docx](https://file1.bingdoc.com/fileroot1/2023-7/3/0df36f29-7bdc-4697-8d27-2ed548d9597b/0df36f29-7bdc-4697-8d27-2ed548d9597b1.gif)
基于单片机的多功能计算器设计完整程序注释版
电子信息工程专业综合课程设计任务书
设计
题目
基于单片机的多功能计算器设计
设计类型
应用型
导师姓名
林泽坤
史俊
主要内容及目标
使用AT89C51单片机设计一个多功能计算器,主要用到矩阵键盘,LED数码管显示数据。
要求进行硬件、软件系统设计。
该计算器可以实现基本的计算还可以实现计时和倒计时的功能。
要求:
(1)6位数范围内的计算显示
(2)要有错误提示
具有的设计条件
需要购买单片机、数据缓冲器、开关等电子元件一批。
大约20元。
计划学生数及任务
计划需要3人
计划设计进程
1、从接题开始收集资料、准备设计
2、第1周画出设计框图,制定设计方案
3、第2周画出电路原理图,编写软件程序;
进行实验、电路调试和完善,同时编写设计报告
参考文献
(1)《跟我学用单片机》肖洪兵第2版北京:
北京航空航天大学出版社,2008.8
(2)《单片机高级教程》何立民第1版.北京:
北京航空航天大学出版社,2006.6
(3)《单片机基础》李广第第1版.北京:
北京航空航天大学出版社,1999.8
摘要:
单片机的出现是计算机制造技术高速发展的产物,它是嵌入式控制系统的核心,如今,它已广泛的应用到我们生活中的各个领域,电子、科技、通信、汽车、工业等。
我们这次设计的多功能科学计算器也是利用AT89C51单片机制作而成。
该计算器设计是采用C语言编写,实现了六位数范围内的加、减、乘、除基本的四则运算,此外该计算器除了具备基本的计算功能以外还具有计时和倒计时的功能,也就是说该计算器具有两个工作模式,计算模式和计时模式,而计时模式里又包含正计时和倒计时的功能,这样一个简易的计算器实现了多功能,比较实用和方便。
该设计电路是采用AT89C51单片机为主要控制电路,然后使用74LS245缓冲驱动电路驱动六位LED数码管显示数据,利用加上4×4矩阵键盘完成电路的实际操作。
电路比较简单,但是很实用方便。
关键字:
AT89C51多功能74LS245LED矩阵键盘
基于单片机的多功能计算器设计
1.方案论证与选择
1.1输入模块
方案一:
采用独立式按键作为输入模块,其特点:
直接用I/O口构成单个按键电路,接口电路配置灵活、按键识别和软件结构简单,但是当键数较多时,占用I/O口较多,比较浪费资源;其原理图如图1所示:
图1独立的功能按键
方案二:
采用矩阵式键盘作为输入电路,其特点:
电路和软件稍复杂,但相比之下,当键数越多时越节约I/O口,比较节省资源。
其原理图如图2所示:
图2矩阵键盘输入
本设计使用键盘输入预置用于计算或计时,按键较多。
若采用独立按键,需频繁按键,为软件设计增加负担,且操作界面不友好。
若采用矩阵式按键,可以方便地输入一个数值,使操作界面更具人性化,节约了宝贵的I/O口资源。
通过对比,故采用方案二作为系统输入模块。
1.2显示模块:
方案一:
用LCD显示,要用LCD显示,需要学习其专用的驱动控制芯片,比如HD61203,软件实现较为复杂,且LCD的价格昂贵。
方案二:
采用LED数码管串行静态显示,虽然其显示亮度高,但是如果显示器的位数较多,需要增加锁存器,故而静态显示占用I/O口线较多,CPU的开销较大。
方案三:
采用LED数码管并行动态显示,显示亮度不及静态显示,但电路简单,适合于显示位数较多的情况。
表1用LED显示器显示十六位进制数的字形代码在下图表示:
字型
共阳极代码
共阴极代码
字型
共阳极代码
共阴极代码
0
COH
3FH
9
90H
6FH
1
F9H
06H
A
88H
77H
2
A4H
5BH
B
83H
7CH
3
B0H
4FH
C
C6H
39H
4
99H
66H
D
A1H
5EH
5
92H
6DH
E
86H
79H
6
82H
7DH
F
8EH
71H
7
F8H
07H
灭
FFH
00H
8
80H
7FH
综上所述,采用方案三并行动态显示是本设计最佳显示方案。
LED数码管显示器由6个发光二极管组成,因此也称之为6段LED显示器,其排列形状如上。
注:
该设计电路中的6段LED数码显示器是共阳极的。
2.其他硬件电路模块功能介绍:
2.1驱动模块
该设计的驱动电路是由74LS245来驱动的。
74LS245是我们常用的芯片,用来驱动LED或者其他的设备,它是8路同相三态双向总线收发器,可双向传输数据。
74LS245还具有双向三态功能,既可以输出,也可以输入数据。
当8051单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。
当片选端/CE低电平有效时,AB/BA=“0”,信号由B向A传输;(接收)
AB/BA=“1”,信号由A向B传输;(发送)当/CE为高电平时,A、B均为高阻态。
由于P2口始终输出地址的高8位,接口时74LS245的三态控制端/1G和/2G接地,P2口与驱动器输入线对应相连。
P0口与74LS245输入端相连,/CE端接地,保证数据现畅通。
8051的/RD和/PSEN相与后接DIR,使得/RD或/PSEN有效时,74LS245输入(P0.i←Di),其它时间处于输出(P0.i→Di)。
2.2主控制模块
该设计的核心控制电路是AT89C51单片机。
AT89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—FalshProgrammableandErasableReadOnlyMemory)的低电压,高性能CMOS8位微处理器,俗称单片机。
其引脚图以及工作原理如下:
现简要介绍各引脚的功能。
⑴.主电源引脚:
Vss-(20脚):
地线
Vcc-(40脚):
+5V电源
⑵.外接晶振或外部振荡器引脚:
XTAL1-(19脚):
当采用芯片内部时钟信号时,接外部晶振的一个引脚;当采用外部时钟信号时,此脚应接地。
XTAL1-(18脚):
当采用芯片内部时钟信号时,接外部晶振的一个引脚;当采用外部时钟信号时,外部信号由此脚输入。
⑶.控制、选通或电源复用引脚:
RST/Vp0-(9脚):
复位信号输入;Vcc掉电后,此脚可接上备用电源,在低功耗条件下保持内部RAM中的数据。
ALE/PROG-(30脚):
ALE即允许地址锁存信号输出,当单片机访问外部存储器时该脚的输出信号用于锁存P0的低8位地址,其输出的频率为时钟振荡频率的1/6。
PROG为编程脉冲输入端,
当选用8751单片机时,由此脚输入编程脉冲。
/PSEN-(29脚):
访问外部程序存储器选通信号,低电平有效,用于实现外部程序存储器的
读操作。
/EA-(31脚):
EA为访问内部或外部程序存储器选择信号,EA=0,单片机只访问外部程
序存储器,故对8031此脚只能接地;EA=1,单片机访问内部程序存储器,固对8051和8751此脚应接高电平,但若程序指针PC值超过4KB(OFFFH)范围,单片机将自动访问外部程序存储器。
⑷.多功能I/O引:
P0口-(32~39脚):
P0数据/地址复用总线端口。
P1口-(1~8脚):
P1静态通用端口。
P2口-(21~28脚):
P2动态端口。
P3口-(10~17脚):
P3双功能静态端口。
除作I/O端口外,它还提供特殊的第二功能,其具体含义为:
P3.0-(10脚)RXD:
串行数据接收端。
P3.1-(11脚)TXD:
串行数据发送端。
P3.2-(12脚)INT0:
外部中断0请求端,低电平有效。
P3.3-(13脚)INT1:
外部中断1请求端,低电平有效。
P3.4-(14脚)T0:
定时器/计数器0计数输入端。
P3.5-(15脚)T1:
定时器/计数器1计数输入端。
P3.6-(16脚)WR:
外部数据存储器写选通,低电平有效。
P3.7-(17脚)RD:
外部数据存储器读选通,低电平有效
2.3操作模块
该计算器的实际操作模块如下图所示:
3.软件设计
本作品实现的功能全部是由C语言程序编写实现。
通过程序的编写使简单的器件实现丰富的功能。
3.1主功能计算器部分
使用双精度类型来存放计算器的两个输入数值和最后的计算结果,最大接收的输入位数为6位,超出6位显示报错,并且需要清屏,然后重新输入。
该计算器只能实现正整数范围内的四则运算。
3.2计时和倒计时部分
出于学习的目的,计时和倒计时采用定时器来实现的。
虽然有点误差但误差不大基本达到要求。
此外,该计算器还设有四个功能按键,可以输入相应的按键对应的键值,进行模式转换或数据更改。
3.3功能按键
一开始默认的模式是计算模式即矩阵键盘执行计算模式下的功能。
按功能键“ON/C”切换到计时模式;在计时模式下按“=”功能键又可切换到计算模式;在计时模式下按“=”功能键后再按功能键“ON/C”又可切换到倒计时模式。
3.4软件流程图
4硬件设计
4.1电路工作框图
4.2硬件电路图
4.3引脚锁定
P0口接驱动器74LS245;
P1口接显示器LED的段选;
P2口接4*4矩阵键盘;
P3口接外部中断0;
5.电路测试结果
5.1代码提示信息
由于该电路可以实现计算、计时以及倒计时三种功能,因此,会有相应的模式转换提示代码信息;此外,由于该设计电路存在设计功能有限,所以会有相应的错误提示信息,主要如下:
相关显示代码:
报告代号显示含义
1:
-EOR-1被除数等于0;
2:
-EOR-2被减数小于减数;
3:
CHAG-1表明从计算器模式切换到计时模式;
4:
CHAG-0表明从计时器模式切换到计算器模式;
5:
-PAUSE暂停;
7:
-StoP-停止;
8:
OPPOSE切换到倒计时模式;
9:
-EOR-9超出可显示的最大值。
5.2模式转换电路图
5.3错误提示电路图
5.4正常计算结果显示图
6.该设计电路的改进思想
出于我们水平有限,虽然我们设计的这个计算器具有计算和计时的多功能,但是还有很多不足,例如,该计算器只能实现正整数的加减乘除运算,无法实现小数以及负数的运算。
所以可以将该设计电路进行扩展,真正设计为一个多功能的科学计算器。
7.小结
不知不觉,两个星期的单片机实践课程学习就结束了,在一开始看这本书时,只对这门课程有了大致的了解,但只是理论上的理解,对如何应用却很是模糊,有些东西还是模棱两可,不是很明白,所以一开始进入实验室进行设计操作时,我是一头雾水,不知道到底该怎么办好,尤其是在程序编译时,程序经常有错误,让我们很是头疼郁闷,可没办法只好耐心慢慢找错误,有时真得都快失去耐心了,可是还是不能放弃,于是我们小组就在一起慢慢讨论,边看书边做,或者请教老师和同学,上课没完成,课后我们还是会重新再做,直到得出正确结论,虽然花了不少时间,但至少让我们学会了很多。
这是在软件中遇到的问题,此外在买器材时也遇到一些问题。
如,本来是要去买我们原先设定的标准型号的器材,但是在买器材的过程中发现,有些器材买不到,此时我们只好重新查阅资料,找具有相应功能的元器件代替,但必须要严格相近,否则,会影响电路的功能。
在焊接电路的时候,由于有些器件太小了如:
贴片电容、贴片电阻等,所以难免会焊接错误,此时我们必须不停的调试找出错误,否则会导致整个电路的损坏。
虽然,在一开始接到这个设计任务时,我们感觉挺有压力的,担心做不好,但是团队的力量是不可小觑的,我们小组三人互相鼓励学习,所以我们在讨论中一步步进步,最终完成了任务。
当然,我们学到的只是一些最为基础的东西,还有很多东西还得深入学习,进一步加强。
总之在这次单片机学习中我们受益匪浅。
这不仅增强了我们对单片机设计的兴趣,更增强了自己的动手能力,这要感谢老师的指导和同学的帮助!
电子行业是一门发展相当迅速的行业,每天都会有新的产品和应用需求,所以,在学好书本知识的同时还要时时关注相关领域的最新动态,学会自主分析解决目前技术中存在的问题。
作为一名电子信息类专业的学生,我们目前学习最好的方法就是多实践,多设计,为将来的工作作好准备。
8.参考文献
(1)《跟我学用单片机》肖洪兵第2版北京:
北京航空航天大学出版社,2008.8
(2)《单片机高级教程》何立民第1版.北京:
北京航空航天大学出版社,2006.6
(3)《单片机基础》李广第第1版.北京:
北京航空航天大学出版社,1999.8
附录(程序清单)
//**<程序名>:
计算器处理主程序,根据计算器的输入状态分派不同的函数对按键进行处理。
//**<功能>:
当b_WorkMode=0是,若有键按下则调用此函数对键码进行处理。
头文件及宏定义
#include"CalReady.h"
*全局变量*
externunsignedlongul_Number;//LCE显示数据,LCD实时显示该数字。
//<<<<<<<<<<<<工作模式(默认为计算器模式)>>>>>>>>>>>>>>>>>>>>>>>>>//
externbitb_WorkMode;//0--计算器模式;
//1--计时模式。
//定义在KeyProcess.c中。
unsignedcharuc_ModeChange=0;
externbitb_LCDClean;
externunsignedcharuc_ReportSymbol;
unsignedlongul_NumberOne=0;//第一个数
unsignedlongul_NumberTwo=0;//第二个数
unsignedcharuc_Operator=0;//运算符
unsignedlongul_Result=0;//运算结果
unsignedcharuc_NumPointer=1;//计算状态
//*********************计算器处理主函数*********************//
voidvCalculator(unsignedcharucKeyCode)
{
if(ucKeyCode==41)//判断按键是不是'NO/C'。
{
if(uc_NumPointer==1)//如果是‘NO/C’键则判断手机否是状态一。
{
if(uc_ModeChange==2)//如果是状态一则看uc_ModeChange是不是2。
{
uc_ModeChange=0;//如果是2则计时器模式。
b_WorkMode=1;
uc_ReportSymbol=3;//闪烁显示:
-CHAG-1。
表明正在切换状态。
b_LCDClean=1;
}
else
{
uc_ModeChange++;//如果uc_ModeChange不是2则加一。
ul_NumberOne=0;//清除所有数据,将所有数据恢复到状态一。
ul_NumberTwo=0;
ul_Number=0;
uc_NumPointer=1;
}
}
else
{
ul_NumberOne=0;//清除所有数据,将所有数据恢复到状态一。
ul_NumberTwo=0;
ul_Number=0;
uc_NumPointer=1;
}
}
else
{//如果不是“NO/C”键,首先将uc_ModeChange清零。
uc_ModeChange=0;
//<<<<<<<<<<<<<<根据不同状态分派不同的键处理函数>>>>>>>>>//
switch(uc_NumPointer)
{
case1:
vCalReadyOne(ucKeyCode);//进入状态一。
break;
case2:
vCalReadyTwo(ucKeyCode);//进入状态二。
break;
case3:
vCalReadyThree(ucKeyCode);//进入状态三。
break;
default:
break;
}
}
}
<程序名>:
计算器案件初始处理及运算。
//<功能>:
在计算器模式下,对按键进行响应,如清零,计算结果等//
//<错误代码>:
-EOR-1:
被除数等于0;//
//-EOR-2:
被减数小于减数;//
//-EOR-9:
超出可显示的最大值。
//
//*********************头文件及宏定义*********************//
//*************************全局变量***********************//
externunsignedlongul_Number;
externunsignedlongul_NumberOne;
externunsignedlongul_NumberTwo;
externunsignedcharuc_Operator;
externunsignedlongul_Result;
externunsignedcharuc_NumPointer;
externbitb_LCDClean;
externunsignedcharuc_ReportSymbol;
bitb_Zero=0;//状态一0输入检测,若有0输入则置一。
//*************************计算结果*****************************//
voidvGetResult()
{
switch(uc_Operator)
{
//*************************除法运算*****************************//case14:
if(ul_NumberTwo!
=0)
ul_Result=ul_NumberOne/ul_NumberTwo;
else
{
ul_Result=0;
uc_ReportSymbol=1;//当被除数等于0时显示错误代码EOR-1//
b_LCDClean=1;
}
break;
//*************************乘法运算*****************************//case24:
if((ul_NumberOne*ul_NumberTwo)>999999)
{
ul_Result=0;
uc_ReportSymbol=9;
b_LCDClean=1;//当结果超出显示范围时显示错误代码EOR-9//
}
else
ul_Result=ul_NumberOne*ul_NumberTwo;
break;
//*************************减法运算*****************************//case34:
if(ul_NumberOne>ul_NumberTwo)
ul_Result=ul_NumberOne-ul_NumberTwo;
else
{
ul_Result=0;
uc_ReportSymbol=2;//当被减数小于减数时显示错误代码EOR-2//
b_LCDClean=1;
}
break;
//*************************加法运算*****************************//case44:
if((ul_NumberOne+ul_NumberTwo)>999999)
{
ul_Result=0;
uc_ReportSymbol=9;
b_LCDClean=1;//当结果超出显示范围时显示错误代码EOR-9//
}
elseul_Result=ul_NumberOne+ul_NumberTwo;
break;
default:
break;
}
ul_Number=ul_Result;
ul_NumberOne=0;//恢复计算前初始状态。
ul_NumberTwo=0;
uc_NumPointer=1;
b_Zero=0;
}
//**************************状态一预处理*********************//
//*************将1位数字压入第一个数字中*********************//
voidvPushOne(unsignedcharucPushNum)
{
if(ul_NumberOne<100000)//如果数字小于6位则压入数字,否则不执行。
{
ul_NumberOne=ul_NumberOne*10+ucPushNum;
ul_Number=ul_NumberOne;
}
}
//*************状态一按键处理函数*****************************//
voidvCalReadyOne(unsignedcharucKeyCode)
{
switch(ucKeyCode)
{//如果由数字输入,则压入数字一。
case11:
vPushOne(7);break;//'7'
case12:
vPushOne(8);break;//'8'
case13:
vPushOne(9);break;//'9'
case21:
vPushOne(4);break;//'4'
case22:
vPushOne(5);break;//'5'
case23:
vPushOne(6);break;//'6'
case31:
vPushOne
(1);break;//'1'
case32:
vPushOne
(2);break;//'2'
case33:
vPushOne(3);break;//'3'