基于51单片机的计算器论文.docx
《基于51单片机的计算器论文.docx》由会员分享,可在线阅读,更多相关《基于51单片机的计算器论文.docx(40页珍藏版)》请在冰点文库上搜索。
基于51单片机的计算器论文
摘要
近几年单片机技术的发展很快,其中电子产品的更新速度迅猛。
计算器是日常生活中比较的常见的电子产品之一。
如何才能使计算器技术更加的成熟,充分利用已有的软件和硬件条件,设计出更出色的计算器呢。
本设计是以AT89S52单片机为核心的计算器模拟系统设计,输入采用4×4矩阵键盘,可以进行加、减、乘、除4位带符号数字运算,并在LCD1602上显示操作过程。
科技的进步告别了以前复杂的模拟电路,一块几厘米平方的单片机可以省去很多繁琐的电路。
现在应用较广泛的是科学计算器,与我们日常所用的简单计算器有较大差别,除了能进行加减乘除,科学计算器还可以进行正数的四则运算和乘方、开方运算,具有指数、对数、三角函数、反三角函数及存储等计算功能。
计算器的未来是小型化和轻便化,现在市面上出现的使用太阳能电池的计算器,使用ASIC设计的计算器,如使用纯软件实现的计算器等,未来的智能化计算器将是我们的发展方向,更希望成为应用广泛的计算工具。
关键词:
计算器;LCD1602;89c51单片机
第一章设计要求与方案论证
1.1设计要求:
1.显示上,相加结果显示要考虑进位的输出显示;输入加数和被加数(减数和被减数、乘数和被乘数、除数和被除数)时,显示器上显示的数字要像平时用的计算器输入一样。
2.注意对“0”-“9”、“+”、“-”、“*”、“/”、“=”以外按键输入的处理。
1.2系统基本方案选择和论证
1.2.1单片机芯片的选择方案和论证
采用STC89C51芯片作为硬件核心,采用FlashROM,内部具有4KBROM存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于拔插会对芯片造成一定的损坏。
片内ROM全都采用FlashROM;能以3V的超底压工作;同时也与MCS-51系列单片机完全该芯片内部存储器为8KBROM存储空间,同样具有STC89C51的功能,且具有在线编程可擦除技术,对所下载的程序能够加密,比较安全。
当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要对芯片多次拔插,所以不会对芯片造成损坏。
所以选择采用STC89C51作为主控制系统。
1.2.2显示模块选择方案和论证
采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字,图形,显示多样,清晰可见,与普通数码管相比功耗较小,硬件连接简单。
所以显示部分采用1602液晶显示。
1.3电路设计最终方案决定
综上各方案所述,对此次作品的方案选定:
采用STC89C51作为主控制系统;LCD1602液晶作为显示
第二章系统的硬件设计与实现
2.1电路设计流程图
图2-1电路设计流程图
2.2系统硬件概述
本电路是由STC89C51单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作;采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据;显示部分由1602构成。
其实排阻就是由8个电阻组成的,其中一端全部接在一起,103为8个10K电阻,102为8个1K电阻,他们在电路中起到“上拉”的作用,又称上拉电阻。
上拉就是将不确定的信号通过一个电阻嵌位在高电平,电阻同时起限流作用,下拉同理.上拉是对器件注入电流,下拉是输出电流,弱强只是上拉电阻的阻值不同,没有什么严格区分,对于非集电极(或漏极)开路输出型电路(如普通门电路)提升电流和电压的能力是有限的,上拉电阻的功能主要是为集电极开路输出型电路输出电流通道。
2.3主要单元电路的设计
2.3.1单片机主控制模块的设计
STC89C51单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3,MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。
单片机的最小系统如图2-2所示,18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出.第9引脚为复位输入端,接上电容,电阻及开关后够上电复位电路,如图2-2
图2-2主控制系统
2.3.2显示模块的设计
1.1602介绍
字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式LCD,目前常用16*1,16*2,20*2和40*2行等的模块。
下面以长沙太阳人电子有限公司的1602字符型液晶显示器为例,介绍其用法。
一般1602字符型液晶显示器实物如图2-3:
图2-31602字符型液晶显示器实物图
2.1602LCD的基本参数及引脚功能
1602LCD分为背光和不带背光两种,基控制大部分为HD44780,带背光的比不带背光的厚,是否带背光在应用中并无差别,引脚功能说明
1602LCD采用标准的14脚(无背光)或16脚(带背光)接口,各引脚接口说明如表2-1所示:
表2-1引脚接口说明表
编号
符号
引脚说明
编号
符号
引脚说明
1
VSS
电源地
9
D2
数据
2
VDD
电源正极
10
D3
数据
3
VL
液晶显示偏压
11
D4
数据
4
RS
数据/命令选择
12
D5
数据
5
R/W
读/写选择
13
D6
数据
6
E
使能信号
14
D7
数据
7
D0
数据
15
BLA
背光源正极
8
D1
数据
16
BLK
背光源负极
第1脚:
VSS为地电源。
第2脚:
VDD接5V正电源。
第3脚:
VL为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚:
RS为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄器。
第5脚:
R/W为读写信号线,高电平时进行读操作,低电平时进行写操作。
当RS和R/W共同为低电平时可以写入指令或者显示地址,当RS为低电平R/W高电平时可以读忙信号,当RS为高电平R/W为低电平时可以写入数据。
第6脚:
E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7~14脚:
D0~D7为8位双向数据线。
第15脚:
背光源正极。
第16脚:
背光源负极。
1602LCD的一般初始化(复位)过程
延时15mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
延时5mS
写指令38H(不检测忙信号)
以后每次写指令、读/写数据操作均需要检测忙信号
写指令38H:
显示模式设置
写指令08H:
显示关闭
写指令01H:
显示清屏
写指令06H:
显示光标移动设置
写指令0CH:
显示开及光标设置
3.LCD1602液晶原理如图2-4所示:
图2-4LCD液晶原理图
2.3.3按键模块的设计
根据设计要求需要选择四个独立按键分别为选择、加、减、确定,
按键模块如图2-5所示:
图2-5按键模块设计
2.3.4上拉电阻内容
1、当TTL电路驱动COMS电路时,如果TTL电路输出的高电平低于COMS电路的最低高电平(一般为3.5V),这时就需要在TTL的输出端接上拉电阻,以提高输出高电平的值。
2、OC门电路必须加上拉电阻,才能使用。
3、为加大输出引脚的驱动能力,有的单片机管脚上也常使用上拉电阻。
4、在COMS芯片上,为了防止静电造成损坏,不用的管脚不能悬空,一般接上拉电阻产生降低输入阻抗,提供泄荷通路。
5、芯片的管脚加上拉电阻来提高输出电平,从而提高芯片输入信号的噪声容限增强抗干扰能力。
6、提高总线的抗电磁干扰能力。
管脚悬空就比较容易接受外界的电磁干扰。
7、长线传输中电阻不匹配容易引起反射波干扰,加上下拉电阻是电阻匹配,有效的抑制反射波干扰。
图2-6上拉电阻原理图
2.3.5自锁开关应用
图2-7自锁开关硬件图
图2-8自锁开关原理图
第三章系统的软件设计
3.1主程序:
#include
#defineuintunsignedint
#defineucharunsignedchar
//--------LCD1602-------------------
//P10-17====D0-7
sbitrs=P3^0;//指令or数据
sbitwela=P3^1;//读or写
sbitlcden=P3^2;//使能信号
//--------LCD1602-------------------
//--------KEY-----------------------
//P2口
//--------KEY-----------------------
ucharcodetable[]="";
longintdata_a,data_b;//第一个数和第二个数
longintdata_c;//计算结果
uchardispaly[10];//显示缓冲
//************************************************************************/
//描述:
延时tus函数
//************************************************************************/
voidLCD_Delay_us(unsignedintt)
{
while(t--);//t=0,退出
}
//************************************************************************/
//描述:
延时tms函数
//************************************************************************/
voidLCD_Delay_ms(unsignedintt)
{
unsignedinti,j;
for(i=0;ifor(j=0;j<113;j++)//执行113次循环
;
}
//************************************************************************/
//描述:
1602液晶写指令
//************************************************************************/
voidwrite_com(ucharcom)//1602液晶写指令
{
rs=0;//写指令
lcden=0;//使能1602
P1=com;//写入指令com
LCD_Delay_ms
(1);//延时1ms
lcden=1;//使能1602
LCD_Delay_ms
(2);//延时2ms
lcden=0;//使能1602
}
//************************************************************************/
//描述:
1602液晶写数据
//************************************************************************/
voidwrite_date(uchardate)//1602液晶写数据
{
rs=1;//写数据
lcden=0;//使能1602
P1=date;//写入数据date
LCD_Delay_ms
(1);//延时1ms
lcden=1;//使能1602
LCD_Delay_ms
(2);//延时2ms
lcden=0;//使能1602
}
//************************************************************************/
//描述:
指定x,y写入字符函数
//************************************************************************/
voidW_lcd(unsignedcharx,unsignedchary,unsignedcharData)
{
if(y==0){write_com(0x80+x);}//第一行
else{write_com(0xc0+x);}//第二行
write_date(Data);//写入数据
}
//指定x,y写入字符串函数
voidLCD_Write_String(unsignedcharx,unsignedchary,unsignedchar*s)
{
if(y==0){write_com(0x80+x);}//第一行
else{write_com(0xC0+x);}//第二行
while(*s)//
{write_date(*s);s++;}//写入数据
}
//************************************************************************/
//描述:
初始化液晶,及画面初始化
//************************************************************************/
voidinit_lcd(void)//初始化液晶,及画面初始化
{
wela=0;//写液晶
lcden=0;//使能1602
write_com(0x38);//8位总线,双行显示,5X7的点阵字符
LCD_Delay_us(100);//延时100us
write_com(0x0c);//开显示,无光标,光标不闪烁
write_com(0x06);//光标右移动
write_com(0x01);//清屏
write_com(0x80);//DDRAM地址归0
}
//************************************************************************/
//描述:
反转法键盘扫描
//************************************************************************/
shortkeycheckdown()/*反转法键盘扫描*/
{
shorttemp1,temp2,temp,a=0xff;
P2=0xf0;/*输入行值(或列值)*/
LCD_Delay_ms(20);/*延时*/
temp1=P2;/*读列值(或行值)*/
P2=0xff;
LCD_Delay_ms(20);/*延时*/
P2=0x0f;/*输入列值(或行值)*/
LCD_Delay_ms(20);/*延时*/
temp2=P2;/*读行值(或列值)*/
P2=0xff;
temp=(temp1&0xf0)|(temp2&0xf);/*将两次读入数据组合*/
switch(temp)/*通过读入数据组合判断按键位置*/
{
case0x77:
a=0x0d;break;//按键/
case0x7b:
a=0x0e;break;//按键=
case0x7d:
a=0;break;//按键0
case0x7e:
a=0x0f;break;//按键CE
case0xb7:
a=0x0c;break;//按键*
case0xbb:
a=0x9;break;//按键9
case0xbd:
a=0x8;break;//按键8
case0xbe:
a=0x7;break;//按键7
case0xd7:
a=0x0b;break;//按键-
case0xdb:
a=0x6;break;//按键6
case0xdd:
a=0x5;break;//按键5
case0xde:
a=0x4;break;//按键4
case0xe7:
a=0x0a;break;//按键+
case0xeb:
a=3;break;//按键3
case0xed:
a=2;break;//按键2
case0xee:
a=1;break;//按键1
default:
a=0xff;
}
returna;/*返回按键值*/
}
voiddisplay_a()//显示数据a
{
dispaly[3]=data_a%10000/1000;//千
dispaly[2]=data_a%1000/100;//百
dispaly[1]=data_a%100/10;//十
dispaly[0]=data_a%10;//个
write_com(0x80+0);//显示数据a
if(data_a>999){write_date('0'+dispaly[3]);}//显示千位
if(data_a>99){write_date('0'+dispaly[2]);}//显示百位
if(data_a>9){write_date('0'+dispaly[1]);}//显示十位
write_date('0'+dispaly[0]);//显示个位
}
voiddisplay_b()//显示数据b
{
write_com(0x80+7);//第一行
dispaly[3]=data_b%10000/1000;//千
dispaly[2]=data_b%1000/100;//百
dispaly[1]=data_b%100/10;//十
dispaly[0]=data_b%10;//个
if(data_b>999){write_date('0'+dispaly[3]);}//显示千位
if(data_b>99){write_date('0'+dispaly[2]);}//显示百位
if(data_b>9){write_date('0'+dispaly[1]);}//显示十位
write_date('0'+dispaly[0]);//显示个位
}
//计算结果
voiddisplay_c(x)
{
if(data_c<100000000&&data_c>-1)//溢出时显示错误
{
dispaly[8]=data_c%1000000000/100000000;//万万
dispaly[7]=data_c%100000000/10000000;//千万
dispaly[6]=data_c%10000000/1000000;//百万
dispaly[5]=data_c%1000000/100000;//十万
dispaly[4]=data_c%100000/10000;//万
dispaly[3]=data_c%10000/1000;//千
dispaly[2]=data_c%1000/100;//百
dispaly[1]=data_c%100/10;//十
dispaly[0]=data_c%10;//个
write_com(0x80+6+0x40);//第一行
if(x==4)
{
if(data_c>99999999){write_date('0'+dispaly[8]);}//显示万万
if(data_c>9999999){write_date('0'+dispaly[7]);}//千万
if(data_c>999999){write_date('0'+dispaly[6]);}//百万
if(data_c>99999){write_date('0'+dispaly[5]);}//十万
write_date('0'+dispaly[4]);//万
write_date('.');
write_date('0'+dispaly[3]);//千
write_date('0'+dispaly[2]);//百
write_date('0'+dispaly[1]);//十
write_date('0'+dispaly[0]);//个
}
else{
if(data_c>99999999){write_date('0'+dispaly[8]);}//显示万万
if(data_c>9999999){write_date('0'+dispaly[7]);}//千万
if(data_c>999999){write_date('0'+dispaly[6]);}//百万
if(data_c>99999){write_date('0'+dispaly[5]);}//十万
if(data_c>9999){write_date('0'+dispaly[4]);}//万
if(data_c>999){write_date('0'+dispaly[3]);}//千
if(data_c>99){write_date('0'+dispaly[2]);}//百
if(data_c>9){write_date('0'+dispaly[1]);}//十
write_date('0'+dispaly[0]);//个
}
}
else//溢出时显示错误
{
write_com(0x80+11+0x40);//第一行
write_date('E');//显示E
write_date('r');//显示R
write_date('r');//显示R
write_date('o');//显示O
write_date('r');//显示E
}
}
voideql(ucharx)//加减乘除运算
{
switch(x)/*功能键选择*/
{
case1:
data_c=data_a+data_b;break;//加/*+S=1*//*数值转换函数*/
c