基于单片机简易计算器的设计.docx
《基于单片机简易计算器的设计.docx》由会员分享,可在线阅读,更多相关《基于单片机简易计算器的设计.docx(20页珍藏版)》请在冰豆网上搜索。
基于单片机简易计算器的设计
《单片机课程设计》
课程设计报告书
课题名称
简易计算器的设计
姓名
周运鸿
学号
2010118010208
专业
电气工程及其自动化
指导教师
皮大能
机电与控制工程学院
年月日
摘要
近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。
在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,但仅单片机方面的知识是不够的,还应根据具体硬件结构、软硬件结合,来加以完善。
计算机在人们的日常生活中是比较常见的电子产品之一。
可是它还在发展之中,以后必将出现功能更加强大的计算机,基于这样的理念,本次设计是用AT89S51单片机、LCD显示器、控制按键为元件来设计的计算器。
利用此设计熟悉单片机微控制器及C语言编程,对其片资源及各个I/O端口的功能和基本用途的了解。
掌握keil应用程序开发环境,常用的LCD显示器的使用方法和一般键盘的使用方法。
关键词:
51单片机;LCD;控制按键
1课程设计内容………………………………………………………………………2
1.1任务内容………………………………………………………………………2
1.2任务分析………………………………………………………………………2
2计算器设计基本原理………………………………………………………………3
2.1AT89C51系列单片机简介……………………………………………………3
2.2LCD显示模块…………………………………………………………………6
2.3运算模块……………………………………………………………………8
2.4键盘接口电路………………………………………………………………9
3主程序设计………………………………………………………………………10
4结论…………………………………………………………………………………
4系统仿真图………………………………………………………………………22
通过本次课题设计,应用《单片机应用基础》、《计算机应用基础》等所学相关知识及查阅资料,完成简易计算器的设计,以达到理论与实践更好的结合、进一步提高综合运用所学知识和设计的能力的目的。
2.简易计算器设计基本原理
根据功能和指示要求,本系统选用以MCS-51单片机为主控机。
通过扩展必要的外围接口电路,实现对计算器的设计。
2.189c51系列单片机简介
89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—FalshProgrammableandErasableReadOnlyMemory)的低电压、高性能CMOS8位微处理器,俗称单片机。
单片机的可擦除只读存储器可以反复擦除100次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的89C51是一种高效微控制器,89C2051是它的一种精简版本。
89C单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
STC89c51的引脚说明:
MCS-51系列单片机中的8031、8051及8751均采用40Pin封装的双列直插DIP结构,下图是它们的引脚配置,40个引脚中,正电源和地线两根,外置石英振荡器的时钟线两根,4组8位共32个I/O口,中断口线与P3口线复用。
现在对这些引脚的功能加以说明:
如图2.3所示。
图2.1双列直插式封装引脚图
Pin9:
RESET/Vpc复位信号复用脚,当8051通电,时钟电路开始工作,在RESET引脚上出现24个时钟周期以上的高电平,系统即初始复位。
初始化后,程序计数器PC指向0000H,P0-P3输出口全部为高电平,堆栈指针写入07H,其它专用寄存器被清“0”。
RESET由高电平下降为低电平后,系统即从0000H地址开始执行程序。
然而,初始复位不改变RAM(包括工作寄存器R0-R7)的状态,8051的初始态。
8051的复位方式可以是自动复位,也可以是手动复位。
此外,RESET/Vpd还是一复用脚,Vcc掉电其间,此脚可接上备用电源,以保证单片机内部RAM的数据不丢失。
见下图2.4为两种复位方式和两种时钟方式:
上电自动复位手动复位电路
内部时钟方式外部时钟方式
图2.2复位方式和时钟方式图
硬件系统是指构成微机系统的实体和装置,通常由运算器、控制器、存储器、输入接口电路和输入设备、输出接口电路和输出设备等组成。
单片机实质上是一个硬件的芯片,在实际应用中,通常很难直接和被控对象进行电气连接,必须外加各种扩展接口电路、外部设备、被控对象等硬件和软件,才能构成一个单片机应用系统。
本设计选用以AT89S51单片机为主控单元。
显示部分:
采用LCD静态显示。
按键部分,采用4*4键盘。
硬件电路原理图如图3.1所示:
2.2LCD显示模块
本设计采用LCD液晶显示器来显示输出数据。
LCD的特性有:
1、+5V电压,对比可调度;2、内含复位电路;3、提供各种控制命令,如:
清屏、字符闪烁、光标闪烁、显示移位等多种功能;4、有80字节显示数据存储器DDRAM;5、内建有160个5X7点阵的字型的字符发生器CGROM;6、8个可由用户自定义的5X7的字符发生器CGRAM。
本设计通过D0-D7引脚向LCD写指令字或写数据以使LCD实现不同的功能或显示相应的数据。
其接口电路如图3.3所示。
图2.31602LCD引脚图
表2.4LCD的引脚说明
符号
引脚说明
符号
引脚说明
VSS
电源地
DB4
DataI/O
VDD
电源正极(+5V)
DB5
DataI/O
V0
液晶显示偏压输入
DB6
DataI/O
RS
数据/命令选择端(H/L)
DB7
DataI/O
R/W
读写控制信号(H/L)
E
使能信号
DB0
DataI/O
RST
复位端(H:
正常工作,L:
复位)
DB1
DataI/O
VEE
负电源输出(-10V)
DB2
DataI/O
BLA
背光源正极(+4.2)
DB3
DataI/O
BLK
背光源正极
2.3运算模块
MCS-51单片机是在一块芯片中集成了CPU、RAM、ROM、定时器/计数器和多功能I/O等计算机所需要的基本功能部件。
如果按功能划分,它由以下功能部件组成,即微处理器(CPU),数据存储器(RAM),程序存储器(ROM/EPROM),并行I/O口,串行口,定时器/计数器,中断系统及特殊功能寄存器(SFR)。
单片机是靠程序运行的,并且可以修改。
通过不同的程序实现不同的功能,尤其是特殊的一些功能,通过使用单片机编写的程序可以实现高智能、高效率以及高可靠性,因此采用单片机作为计算器的主要功能部件,可以很快的实现运算功能。
运算模块由键盘和显示屏组成。
单片机通过按键来实现输入数据和操作方式的控制,在运算过程中,对所设的数据进行四则运算时,要先确定选用的是哪一个运算符,若是+或*,则要判断结果是否会溢出,溢出则显示错误提示,没有溢出则显示运算结果,若是/,则要判断除数是否为零,为零时显示错误提示,不为零显示运算结果。
2.4键盘接口电路
计算器输入数字和其他功能按键要用到很多按键,如果采用独立按键的方式,在这种情况下,编程会很简单,但是会占用大量的I/O口资源,因此在很多情况下都不采用这种方式,而是采用矩阵键盘的方案。
矩阵键盘采用四条I/O线作为行线,四条I/O线作为列线组成键盘,在行线和列线的每个交叉点上设置一个按键。
这样键盘上按键的个数就为4×4个。
这种行列式键盘结构能有效地提高单片机系统中I/O口的利用率。
矩阵键盘的工作原理:
计算器的键盘布局如图2所示:
一般有16个键组成,在单片机中正好可以用一个P口实现16个按键功能,这种形式在单片机系统中也最常用。
图2.5矩阵键盘内部电路图
第三章主程序设计
KeilC51是美国KeilSoftware公司出品的51系列兼容单片机C语言软件开发系统,与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。
用过汇编语言后再使用C来开发,体会更加深刻。
KeilC51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到KeilC51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
下面详细介绍KeilC51开发系统各部分功能和使用。
KeilC51单片机软件开发系统的整体结构C51工具包的整体结构,如图3.1所示,其中uVision与Ishell分别是C51forWindows和forDOS的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。
然后分别由C51及A51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
普通计算器课程序设计:
//****************************************//
//通用计算器的编写,能够实现两位的加减计算+,-,*,/
//设计人:
周运鸿。
指导人:
皮大能
//2013-6-6
#include
#include
#include"LCD1602.h"
#include"keyboard.h"
#include"calculation.h"
#defineucharunsignedchar
#defineuintunsignedint
doublenum[2];
ucharsign[2];
ucharnumble1[10];
ucharnumble2[10];
voidmain()
{inti=0,j=0,k=0,flag=0,a=0,b,c=0,e=0,opNum=0;
longintsum1,sum0;
doublesum2;
init();
write_com(0x80);
while(!
mark)
{matrixkeyscan();}
mark=0;
while(expression[j]!
='=')
{
if(!
In(expression[j],OP))//如否不是运算符就入操作数栈
{
if(opNum==0)
{opNum=expression[j]-48;
++j;
if(In(expression[j],OP))
flag=1;
}
else
{
opNum=opNum*10+(expression[j]-48);
++j;
if(In(expression[j],OP))
flag=1;
}
if(flag==1)
{
num[i]=opNum;
opNum=0;
i++;
flag=0;
}
}
else
{sign[k]=expression[j];
++j;
k++;}
}
sum1=Operator(num[0],sign[0],num[1]);
sum2=Operator(num[0],sign[0],num[1]);
sum0=sum1;
while(sum1!
=0)
{numble1[a]=sum1%10+48;
sum1=sum1/10;
a++;
}
b=strlen(numble1);
write_com(0x80+0x40);
for(c=b-1;c>=0;c--)
{write_data(numble1[c]);
delayms(10);}
write_data('.');
sum2=sum2*1000;
sum0=sum2-sum0*1000;
numble2[0]=sum0/100+48;
numble2[2]=sum0%10+48;
numble2[1]=(sum0/10)%10+48;
if(numble2[2]>=(5+48))
numble2[1]=numble2[1]+1;
write_data(numble2[0]);
delayms(5);
write_data(numble2[1]);
delayms(5);
while
(1);
}
//**************************
//键盘扫描程序驱动
//文件名:
keyboard.h
//**************************
#ifndef__keyboard_H__
#define__keyboard_H__
#include
#include"LCD1602.h"
#defineucharunsignedchar
#defineuintunsignedint
uintmove=0;
ucharmark=0;
ucharcodetable[]={'0','1','2','3','4','5','6','7','8','9'};
ucharexpression[20];
ucharcodeOP[]={'+','-','*','/','=','\n'};
voidmatrixkeyscan()
{
uchartemp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{delayms(10);
temp=P3;
temp=P3&0xf0;
if(temp!
=0xf0)
{temp=P3;
switch(temp)
{
case0xee:
key=0;break;
case0xde:
key=1;break;
case0xbe:
key=2;break;
case0x7e:
key=3;break;
}
while(temp!
=0xf0)
{temp=P3;
temp=temp&0xf0;
}
write_data(table[key]);
delayms(5);
expression[move]=table[key];
move++;
}
}
P3=0xfd;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{delayms(10);
temp=P3;
temp=P3&0xf0;
if(temp!
=0xf0)
{temp=P3;
switch(temp)
{case0xed:
key=4;break;
case0xdd:
key=5;break;
case0xbd:
key=6;break;
case0x7d:
key=7;break;
}
while(temp!
=0xf0)
{temp=P3;
temp=temp&0xf0;
}
write_data(table[key]);
delayms(5);
expression[move]=table[key];
move++;
}
}
P3=0xfb;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{delayms(10);
temp=P3;
temp=P3&0xf0;
if(temp!
=0xf0)
{temp=P3;
switch(temp)
{case0xeb:
key=8;break;
case0xdb:
key=9;break;
case0xbb:
key=10;break;
case0x7b:
key=11;break;
}
while(temp!
=0xf0)
{temp=P3;
temp=temp&0xf0;
}
if(key<10)
{write_data(table[key]);
delayms(5);}
else
{write_data(OP[key-10]);
delayms(5);}
expression[move]=table[key];
move++;
}
}
P3=0xf7;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{delayms(10);
temp=P3;
temp=P3&0xf0;
if(temp!
=0xf0)
{temp=P3;
switch(temp)
{case0xe7:
key=12;break;
case0xd7:
key=13;break;
case0xb7:
key=14;break;
case0x77:
key=15;break;
}
while(temp!
=0xf0)
{temp=P3;
temp=temp&0xf0;
}
if(key==14)
mark=1;
write_data(OP[key-10]);
delayms(5);
expression[move]=table[key];
move++;
}
}
}
#endif
//***********************************************
//LCD1602驱动程序
//文件名:
LCD1602.h
//***********************************************
#ifndef__LCD1602_H__
#define__LCD1602_H__
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitlcden=P2^4;
sbitlcdrs=P2^5;
voiddelayms(uintxms)
{uinti,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
voidwrite_com(ucharcom)
{lcdrs=0;
P0=com;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
voidwrite_data(uchardate)
{lcdrs=1;
P0=date;
delayms(5);
lcden=1;
delayms(5);
lcden=0;
}
voidinit()
{
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}
#endif
//***************************************************
//数学计算程序
//文件名:
calculation.h
//****************************************************
#ifndef__calculation_H__
#define__calculation_H__
#defineucharunsignedchar
#defineuintunsignedint
doubleOperator(doublefirst,chartheta,doublesecond)
{
switch(theta)
{
case'+':
returnfirst+second;
break;
case'-':
returnfirst-second;
break;
case'*':
returnfirst*second;
break;
case'/':
returnfirst/second;
break;
default:
break;
}
}
charIn(charc,char*OP)
{
inti=0;
while(OP[i]!
='\0')
{
if(OP[i]==c)
{
return1;
}
i++;
}
return0;
}
#endif
附图1:
程序流程图
附图2:
总体仿真图
结论
通过这次对交通灯的简单设计,使我们增强了动手的能力,也拓宽了知识面,在图书馆查阅相关书籍,让我们增加了对单片机方面的了解,能把学到的知识用活,而不只局限于理论方面。
通过亲自设计,proteus仿真,对交通灯有了初步的了解,同时也加深了对单片机方面的软件应用的掌握,为以后的学习奠定了基础。
而且,这次课程设计是对以前学过的知识进行了巩固,加深了理解,提高了应用的能力,提高了我们的发现、分析、解决问题的能力。
经历了从最初的设计到最后仿真结果的出现,从根本上提高了对专业的认识及兴趣,对于我们工科来说,对以后就业有及其重大的影响。
很感谢学校和老师给我们提供了这样的平台,能使我们的动手能力增强。
感谢老师对我们提供的帮助。
参考文献
[1]徐爱钧.智能化测量控制仪表原理与设计(第二版).北京.北京航天航空大学出版社,2004
[2]孙育才等.MCS-51系列单片微型计算机及其应用(第4版).上海.东南大学出版社,2004
[3]李萍等.智能仪器实验指导书.大连.大连交通大学,2007
[4]单片机应用技术(C语言).北京.中国劳动社会保障出版社,2006
[5]武庆生,仇梅等著.单片机原理与应用.北京.电子科技大学出版,1998
[6]朱定华著.单片机原理与接口技术.西安.电子工业出版社,2001
[7]王威著.HCS12微控制器原理及应用.北京.北京航空航天大学出版社,2007
[8]龚运新著.单片机C语言开发技术.北京.北京清华大学出版社,2006
[9]周立功.单片机实验与实践.北京.北京航空航天大学出版社,2004
指导教师
评语
课程设计
成绩
指导教师
签字
年月日