基于51单片机的简易计算器2.docx

上传人:b****1 文档编号:23142459 上传时间:2023-05-08 格式:DOCX 页数:21 大小:404.97KB
下载 相关 举报
基于51单片机的简易计算器2.docx_第1页
第1页 / 共21页
基于51单片机的简易计算器2.docx_第2页
第2页 / 共21页
基于51单片机的简易计算器2.docx_第3页
第3页 / 共21页
基于51单片机的简易计算器2.docx_第4页
第4页 / 共21页
基于51单片机的简易计算器2.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

基于51单片机的简易计算器2.docx

《基于51单片机的简易计算器2.docx》由会员分享,可在线阅读,更多相关《基于51单片机的简易计算器2.docx(21页珍藏版)》请在冰豆网上搜索。

基于51单片机的简易计算器2.docx

基于51单片机的简易计算器2

 

基于51单片机的

计算器设计

 

2015年5月1日

 

 

 

摘要

电子计算器是日常生活中常用的电子计算仪器,他广泛应用于超市、大中型商场、大小企业与学校中。

具有精度高。

体积小、应用范围广泛、易于操作等优点。

本作品以MCS-51系列中的AT89C51单片机为核心,能够实现单步加、减、乘、除运算。

该系统通过检测矩阵键盘扫描,判断是否按键,实现对4*4键盘扫描进行实时的按键检测,并把检测数据存储下来。

经数据转换把数值送入lcd1602液晶屏显示。

整个计算器系统的工作过程为:

首先存储单元初始化,显示初始值和键盘扫描,判断按键位置,查表得出按键值,单片机则对数据进行储存与相应处理转换,之后送入lcd1602显示。

整个系统可分为三个主要功能模块:

功能模块一,实时键盘扫描;功能模块二,数据转换为了数码管显示;功能模块三,lcd1602显示。

能实现6位或6位以内的精确运算,若输出数据超过6位则会以科学计数法显示。

关键词:

AT89C51单片机;计算器;加减乘除;矩阵键盘;液晶屏

 

1、前言

本设计是基于51系列单片机来进行的数字计算器系统设计,可以完成计算器的键盘输入,进行加、减、乘、除基本四则运算,并在LCD上显示相应的结果;设计电路采用STC89C51单片机为主要控制电路,显示采用1602LCD显示;软件方面使用C语言编程。

最后用PROSE99画PCB,焊接万用板,进行硬件调试。

1)主要的问题及目标:

●键盘输入

●数值显示

●能实现加、减、乘、除四则运算;

●可计算小数,负数;

●当计算器执行过程中有错误时,会在液晶屏上做出相应的提示。

当除数为0时,程序运算出错,液晶屏会显示+INF。

2)针对上述目标,做出以下的设计:

●以STC89C51位主控芯片,P0口连接1602液晶屏,P1口连接4*4矩阵键盘。

●将所有输入数据已浮点型进行运算,故最大输入数据为16位。

●为了更好的显示效果使用采用1602液晶屏作为显示模块。

●由于按键包含数字键“0~9”与“+”“-”“*”“/”“.”“=”这16个按键。

故以4*4矩阵键盘作为输入模块。

●以3节串联的5号电池作为电源。

3)系统设计依据:

●实用性

●可靠性

●美观性

 

2、

系统方案设计

 

1.方案一

显示模块采用数码管,数值只能显示一行,且无法显示“+”“*”“/”“=”等符号。

使用效果欠佳。

电源模块采用USB,电压为5.0V,符合单片机的要求。

但使计算器不方便使用,必须通过USB通电,实用性不强。

功能设计中添加复位键,可以使电路恢复到起始状态,确保微机系统中稳定可靠,避免计算器出现“死机”“程序走飞”等现象。

但添加复位键会使计算器显得繁琐。

双精度型(double),占用64位的存储空间。

在操作值很大的数字时,双精度型是最好的选择。

2.方案二

以1602lcd作为显示器,可显示双行数据,还可以显示多种运算符号。

实用性强,便于计算器的升级。

将独立电源盒作为电源,以3节5号电池串联,电压可达4.5V,可以使

单片机正常工作。

并且易于携带,给使用者带来很大便利。

采用上电复位,将复位电路与电源开关结合。

既可以确保微机系统中稳定可靠的运行,又使计算器更为精简。

单精度浮点型(float)专指占用32位存储空间的单精度值。

单精度在一些处理器上比双精度更快而且只占用双精度一半的空间,但是当值很大或很小的时候,它将变得不精确。

当你需要小数部分并且对精度的要求不高时,单精度浮点型的变量是有用的。

结合上述考虑论证,小组采用方案二作为计算器系统的设计方案。

3、理论分析与计算

本作品为了要实现键盘输入,液晶显示屏输出,加、减、乘、除计算,上电复位等功能。

小组做出以下的分析与计算:

将4*4矩阵键盘连接到单片机的P1口上,液晶显示屏连接到P0口上。

并在软件中用矩阵键盘扫描程序对其实时检测,将键盘输入的数据显示到液晶屏上,并通过运算程序计算,最终将计算结果输出到液晶屏上。

将输入与输出数据以单精度浮点型定义,以%g或%f显示输出数据,可显示精确数字或以科学计数法表示。

4、系统电路设计

1.显示模块

液晶显示器(LCD)的主要原理是一电流刺激液晶分子产生点、线、面并配合背部灯管构成画面。

本系统采用的1602液晶为5V电压驱动,带背光,可显示两行,每行16个字符,能显示汉字,内置128个字符的ASCII字符集字库,只有并行接口,无串行接口。

2.输入模块

4*4矩阵键盘将16个按键排成4行4列,第一行将每个按键的一端连在一起构成行线,第一列将每个按键的另一端连接在一起构成列线,共有4行4列8根线,将这八根线接到单片机的8个I/O口上,通过程序扫描键盘就可检

测16个键。

3.控制模块

AT89C51是一种带4K字节FLASH存储器(FPEROM—FlashProgrammableandErasableReadOnlyMemory)的低电压、高性能CMOS8位微处理器,俗称单片机。

AT89C51是一种带2K字节闪存可编程可擦除只读存储器的单片机。

单片机的可擦除只读存储器可以反复擦除1000次。

该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。

由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,AT89C51是它的一种精简版本。

AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。

4.元器件的选择

1602LCD、4*4矩阵键盘、10千欧排阻、自锁开关、20pF电容、12MHZ晶振、103千欧电位器。

5.特殊器件的简介

自锁开关是指开关自带机械锁定功能,按下去,松手后按钮是不会完全跳起来的,处于锁定状态,需要再按一次,才解锁完全跳起来。

按下后接通,弹起来后断开。

6.各单元模块的连接

 

如图所示:

液晶接PO口,键盘接P1口。

液晶使能端P2.5,液晶数据命令选择端P2.6,液晶读写选择端P2.7。

电源正负极分别接到VCC和GND。

5、系统软件设计

1.设计原理

以keilV4.0设计。

采用大循环嵌套的设计思想。

程序主要由“液晶显示模块”“矩阵键盘扫描模块”“运算模块”构成。

大循环一直进行,是计算器一直处于工作状态。

不停地调用键盘扫描函数,将键盘输入的数据送给液晶显示与运算模块,经运算模块计算出结果后,只需调用液晶显示的子函数就可将答案显示到液晶屏上。

 

2.程序结构框图

定义变量,便于后面程序的使用。

位定义:

液晶使能端P2.5,液晶数据命令选择端P2.6,液晶读写选择端P2.7。

初始化:

液晶开显示,清屏。

矩阵键盘扫描程序:

包含软件去逗,在大循环中不断调用键盘扫描程序当检测到有键按下后,如果是有效值就进行处理,否则继续扫描键盘。

3.程序流程框图

 

 

否是

 

 

否是

 

 

 

 

 

6、系统测试

1.测试方法

将计算器断电,把万用表调到蜂鸣器档上,把万用表两表笔放在待测的两个端子上,若短路蜂鸣器就会响。

经测得开关处电路存在短路,经修复后电路焊接正常。

2.计算器功能测试

加法测试:

减法测试:

乘法测试:

除法测试:

错误处理:

3.测试结果分析

经测试,各项功能均已达成。

对于一般的整形运算,计算器能准确无误的计算出来。

由于使用浮点型数据,计算器只能进行6~7位以内的精确运算。

7、结束语

1.心得感悟

经过两个星期的设计与制作,本小组完成了基于51单片机的计算器的设计。

期间我们遇到许多困难和问题都一一解决,最终完全达到了预期的目标,体会到团体合作与成功的喜悦。

我感到只有亲手实践才能更深刻,更全面的学好知识,并且要在设计制作中多加入自己的想法,力求创新而不要模仿前人做过的作品。

在设计的每一小步都要尽自己最大努力做到最好,这样才能做出出色的作品。

2.改进的设想

1)使计算器能完成多步混合运算的功能。

2)添加一个功能键,当按下功能键后改变矩阵键盘的键值。

将第四列改为平方,开根号,求模,求余。

再次按下此键后第四列改回加,减,乘,除。

并设计一个led灯来显示键值是否被改变。

8、附录

1.系统设计图

2.设计程序

#include

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

#definecheck_busy

sbitrs=P2^7;

sbitrw=P2^6;

sbiten=P2^5;

voiddelay(intz)

{

intx,y;

for(x=z;x>0;x--)

for(y=110;y>0;y--);

}

/***********判忙函数***********/

bitLCD_check_busy()//当LCD“忙”时,LCD的DATA.7位输出为高电平信号,当LCD“不忙”时,LCD的DATA.7位输出为低电平信号

{

P0=0xFF;//为便于检测

rs=0;//rs=0,rw=1,en=1忙

rw=1;//voidbusy(void){P1=0xff;RS=0;RW=1;E=1;while((P1&0x80)==0x80);E=0;}

en=0;

_nop_();

en=1;

return(bit)(P0&0x80);

//else

/*lcd1602判忙函数

bitLCD_Check_Busy(void)

{

bitresult;//修改了判忙函数

DataPort=0xFF;

RS=0;

RW=1;

EN=1;

_nop_();

result=(bit)(DataPort&0x80);

EN=0;

returnresult;*/

return0;

}

/***********写入命令函数***********/

voidwrite_com(ucharcom)

{

while(LCD_check_busy());//忙则等待

rs=0;

rw=0;

en=1;

P0=com;

_nop_();

en=0;

}

/**********写入数据函数**********/

voidwrite_dat(uchardat)

{

while(LCD_check_busy());//忙则等待

rs=1;

rw=0;

en=1;

P0=dat;

_nop_();

en=0;

}

/*******写入字符函数***********/

voidLCD_write_char(ucharx,uchary,uchardat)

{

if(y==0)

{

write_com(0x80+x);

}

else

{

write_com(0xC0+x);

}

write_dat(dat);

}

/******写入字符串函数***********///?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

voidwrite_string(ucharx,uchary,uchar*s)

{

while(*s)

{

LCD_write_char(x,y,*s);

s++;

x++;

}

}

/*****初始化函数******/

voidLCD_init()

{

write_com(0x38);/*显示模式设置*/

delay(5);

write_com(0x06);/*显示光标移动设置*/

delay(5);

write_com(0x0C);/*显示开及光标设置*/

write_com(0x01);/*显示清屏*/

}

/*按键扫描函数,返回扫描键值*/

ucharkeyscan()//键盘扫描函数,使用行列反转扫描法

{

unsignedcharcord_h,cord_l;//行列值中间变量

P1=0x0f;//行线输出全为0

cord_h=P1&0x0f;//读入列线值

if(cord_h!

=0x0f)//先检测有无按键按下

{

delay(10);//去抖

if((P1&0x0f)!

=0x0f)

{

cord_h=P1&0x0f;//读入列线值

P1=cord_h|0xf0;//输出当前列线值

cord_l=P1&0xf0;//读入行线值

while((P1&0xf0)!

=0xf0);//等待松开并输出

return(cord_h+cord_l);//键盘最后组合码值

}

}

return(0xff);//返回该值

}

unsignedcharkeypro()

{

switch(keyscan())

{

case0x7e:

return'+';break;

case0x7d:

return'-';break;

case0x7b:

return'x';break;

case0x77:

return'/';break;

case0xbe:

return'3';break;

case0xbd:

return'6';break;

case0xbb:

return'9';break;

case0xb7:

return'=';break;

case0xde:

return'2';break;

case0xdd:

return'5';break;

case0xdb:

return'8';break;

case0xd7:

return'0';break;

case0xee:

return'1';break;

case0xed:

return'4';break;

case0xeb:

return'7';break;

case0xe7:

return'.';break;

default:

return0xff;break;

}

}

/***************主函数***********/

voidmain()

{

unsignedcharnum,i,sign;

unsignedchartemp[16];//最大输入16个

bitfirstflag;

floata=0,b=0;

unsignedchars;

LCD_init();//初始化液晶屏

delay(10);//延时用于稳定,可以去掉

write_com(0x01);//清屏

while

(1)//主循环

{

num=keypro();//扫描键盘

if(num!

=0xff)//如果扫描是按键有效值则进行处理

{

if(i==0)//输入是第一个字符的时候需要把该行清空,方便观看

write_com(0x01);

if(('+'==num)||(i==16)||('-'==num)||('x'==num)||('/'==num)||('='==num))//输入数字最大值16,输入符号表示输入结束

{

i=0;//计数器复位

if(firstflag==0)//如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b

{

sscanf(temp,"%f",&a);

firstflag=1;

}

else

sscanf(temp,"%f",&b);

for(s=0;s<16;s++)//赋值完成后把缓冲区清零,防止下次输入影响结果

temp[s]=0;

LCD_write_char(0,1,num);

if(num!

='=')//判断当前符号位并做相应处理

sign=num;//如果不是等号记下标志位

else

{

firstflag=0;//检测到输入=号,判断上次读入的符合

switch(sign)

{

case'+':

a=a+b;

break;

case'-':

a=a-b;

break;

case'x':

a=a*b;

break;

case'/':

a=a/b;

break;

default:

break;

}

sprintf(temp,"%g",a);//输出浮点型,无用的0不输出

write_string(1,1,temp);//显示到液晶屏

sign=0;a=b=0;//用完后所有数据清零

for(s=0;s<16;s++)

temp[s]=0;

}

}

elseif(i<16)//?

{

if((0==i)&&(temp[0]=='0'))//如果第一个字符是0,判读第二个字符

{

if(num=='0')//如果是小数点则正常输入,光标位置加1

{

write_com(0x01);

}

else

{

temp[0]=num;

i++;//如果是1-9数字,说明0没有用,则直接替换第一位0

LCD_write_char(0,0,num);//输出数据

}

}

else

{

temp[i]=num;

LCD_write_char(i,0,num);//输出数据

i++;

}

}

}

}

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > IT计算机 > 电脑基础知识

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1