单片机计算器的设计与实现课程设计(共19页).doc
精选优质文档-倾情为你奉上 摘 要近几年单片机技术的发展很快,其中,电子产品的更新速度迅猛。计算器是日常生活中比较常见的电子产品之一。如何才能使计算器技术更加的成熟,充分利用已有的硬件和软件条件,设计出更出色的计算器。本设计是以STC89C52单片机为核心的计算器模拟系统设计,输入采用4*4矩阵键盘,可以进行加、减、乘、除带符号数字运算,并在液晶显示屏LCD1602上静态显示操作过程及结果。关键词: 单片机; 液晶显示屏; 计算器; 矩阵键盘专心-专注-专业 目 录 1 背景与意义随着社会的发展,科学的进步,人们的生活水平在逐步地提高,尤其是微电子技术的发展犹如雨后春笋般的变化。电子产品的更新速度快就不足惊奇了。计算器在人们的日常中是比较常见的电子产品之一,如何使计算器技术更加的成熟,充分利用已有的软件和硬件条件,设计出更出色的计算器,使其更好地为各个行业服务,成了如今电子领域重要的研究课题。现如今,人们的日常生活中已经离不开计算器了,社会的各个角落都有它的身影,比如商店、办公室、学校因此设计一款简单实用的计算器会有很大的实际意义。本设计旨在进一步掌握单片机理论知识,理解嵌入式单片机系统的硬软件设计,加强对实际应用系统设计的能力。通过本设计的学习,使我掌握单片机程序设计和微机接口应用的基本方法,并能综合运用本科阶段所学软、硬件知识分析实际问题,提高解决毕业设计实际问题的能力,为单片机应用和开发打下良好的基础。对字符液晶显示模块的工作原理,如初始化、清屏、显示、调用及外特性有较清楚的认识,并会使用LCD(液晶显示模块)实现计算结果的显示;掌握液晶显示模块的驱动和编程,设计LCD和单片机的接口电路,以及利用单片机对液晶显示模块的驱动和操作;在充分分析内部逻辑的概念,进行软件和调试,学会使用,并能够以其为平台设计出具有四则运算能力简易计算器的硬件电路和软件程序。2 设计要求 实现普通十进制计算器的功能,按键采用实验箱上的4×4键盘,显示采用LCD1602显示器,键盘按键包括0-9、+、-、*、%和清除按键“C”按C后清除LCD屏幕上的显示。 LCD的第一行显示运算式,第二行显示运算结果。比如要计算机12+34,在键盘上按下相应键后,LCD的第一行显示“12+34”,按下“=”号后,LCD的第二行末尾显示“=46”。其 他功能同普通计算器相同。 3 方案设计与选择3.1 输入模块 方案一:采用独立式按键作为输入模块独立式按键输入模块,其特点是:直接用I/O口构成单个按键电路,接口电路配置灵活、按键识别和软件结构简单;但是当键数较多时,占用I/O口较多,比较浪费资源。其原理图如图3-1所示。图 3-1 独立的功能按键 方案二:采用矩阵式键盘作为输入模块矩阵式按键输入模块,其特点是:电路和软件稍复杂,但相比之下,当键数越多时,越节约I/O口,比较节省资源。其原理图如图3-2所示。图 3-2 矩阵键盘输入本设计中的输入模块使用的是矩阵键盘输入。键盘输入预置用于计算,按键较多。若是采用独立按键,需频繁按键,为软件设计增加负担,且操作界面不友好;若是采用矩阵式按键,可以方便地输入一个数值,使操作界面更具有人性化,且节约了宝贵的I/O口资源。通过对比,故采用方案二作为系统输入模块。3.2 显示模块 方案一:采用LED数码管静态显示采用LED数码管的静态显示,其特点是:其亮度较高;这种显示方式接口,编程容易且管理简单;不足的是,占用的I/O的线资源较多。如果采用单片机或CPLD/FPGA来控制的话,势必存在浪费I/O口资源的问题。如图3-3所示。图 3-3 4位数码管静态显示 方案二:采用LED数码管动态显示采用LED数码管的动态显示,其特点是:其亮度比静态显示的亮度要差一些;但其电路比较简单,适合于显示位数较多的情况。如图3-4所示。图 3-4 4位数码管的动态显示 方案三:采用LCD1602液晶显示采用LCD1602液晶显示,其特点是:可以调节其背光亮度,这种显示方式接口,编程虽然有些麻烦,但管理较方便,占用的I/O口资源线也不多。本设计中的显示模块使用的是LCD1602液晶显示。在计算器运算中,需显示的数字、符号较多,按很据个方面的特点,而后可以发现LCD液晶显示,虽然在价格上的确是稍贵于LED数码管;但数码管在硬件设计电路中,会因线太多、线路复杂而过于繁琐,则舍弃LED数码管,选择LCD液晶显示。通过对比,故采用方案三作为系统显示模块。4 硬件电路设计4.1 系统组成及硬件框图 图4-1 系统组成及硬件框图4.2 计算器硬件方案及硬件资源分配主要用到的硬件:单片机STC89C52 、液晶显示屏LCD1602 、4*4按键键盘。硬件分配:1、P3口:作为输入口,与键盘连接,实现数据的输入;2、P0、P2口:作为输出口(P2口为高位,P0口为低位),控制LCD液晶显示屏显示数据的结果;3、液晶显示屏LCD1602显示输出。4.3 键盘电路的设计键盘可分为两类:编码键盘和非编码键盘。编码键盘是较多按键(20个以上)和专用驱动芯片的组合;当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。通用计算机使用的键盘就是编码键盘。在智能仪器中,使用并行接口芯片8279或串行接口HD7279均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路和接口软件均可在芯片资料中得到。当系统功能比较复杂,按键数量很多时,采用编码键盘可以简化软件设计。非编码键盘成本低廉。从成本角度出发,本设计选用的是非编码键盘。如图4-2所示。图 4-2 键盘电路4.3 显示电路的设计当系统需要显示少量数据时,采用LCD液晶显示屏进行显示是一种经济实用的方法。P0口作为液晶显示的数据端口。最终显示电路如图4-3所示。 图4-3 LCD液晶显示屏显示4.4 电路原理图 图4-4所示为简易计算器的电路原理图。P3口用于键盘输入,接4*4矩阵键盘,键值与键盘的对应表如表-所示,p0口和p2口用于显示,p2口用于显示数值的高位,po口用于显示数值的低位。图4-4 简易计算器电路原理图5 软件设计5.1 计算器的软件规划 简易计算器的程序主要包括以下功能模块:1、读键程序、判键程序段、运算操作子程序等部分;2、基于LCD液晶显示屏的显示模块;3、主模块,为系统的初始化。5.2 主模块的程序设计主程序主要用来对LCD液晶显示屏进行初始化的。计算器流程图(如图5-1)。图 5-1 主程序框图void main() uchar i,j; init(); write_cmd(0x80); /将液晶指针定位在第一行第一个单元 key=15; i=flag1=0; while(1) write_cmd(0x80+0x40); /将液晶指针定位在第二行第一个单元 jscl(); flag1=0;在以上的程序中“write_cmd(0x80);”,被赋值为“0x80”,则是根据图 2-2-6 DDRAM单元地址与显示屏字符位的对应关系中便能找到,第一行第一个单元的值为80H,则第二行第一个单元的值就为80H+40H,即得出“write_cmd(0x80+0x40);”。5.3 显示模块的程序设计显示模块程序首先要对显示模块进行初始化;然后控制光标的位置;定义液晶显示的控制端口,用SBIT指令完成;然后设置清屏、关闭显示、归位、开显示、显示位置的首地址等等。显示模块的流程图如图5-2所示。 图 5-2 显示程序框图void jscl() /计算并显示函数 uchar i,j,n; for(j=0;j<k1+1;j+) /存放第一操作数 for(i=0;i<k1-j;i+) for(j=k1+1;j<k2+1;j+)/存放第二操作数 if(js=10)/判断是什么运算,并执行运算 s=s1+s2; if(js=13) s=(s1*0.1)/(s2*0.1); temp1=(long int)(s); /以下部分处理结果 temp2=s-temp1; for(i=n;i>0;i-) /在液晶上显示结果 write_data(tablebi-1); 通过其显示子程序,发现要显示其最终结果,就必须先存放第一操作数、第二操作数,之后来判定使用四则运算中的哪一种运算,其后进行运算处理,最后便能在LCD液晶显示屏上显示其最终结果。5.4 键盘模块的程序设计键盘扫描子程序,首先读出P3口的低四位,然后读出P3口的高四位。然后键值并显示缓存。而后,将键盘上的值转换为ASCII码,最后就可以用软件来设置硬件按键各个键所代表的内容。系统中连接的是4*4行列式按键键盘,其中“0-9”为数字键;“+、-、*、/、=”为符号键;“C”为功能键(清屏键),在程序中会加入一个记忆功能键,而与其搭配的硬件按键为符号键中的“=”,以为求方便。数字键按下则将相应的数字送入数字缓冲区;符号键按下则将送入符号缓冲区;功能键按下则执行相应的程序;最终进行运算后,综合结果将送入结果缓冲区,并在LCD液晶显示屏上显示出来。键盘模块程序也可相当于一个中断服务子程序,如图5-3所示。图 5-3 中断服务程序框图void keyscan() /键盘扫描程序 uchar temp,uu=0xf7; uint i; for(i=0;i<4;i+) uu=_crol_(uu,1); /_crol_为左移函数 case 0xee: key=0; break; case 0xde: key=1; break; case 0x77: key=15; break; 在以上的程序中,其中的“key=0key=15”是按键“0-9、+、-、*、/、=、C”16个键。而“case 0xee: key=0; break;”中,被赋值为“0xee”,则是因为行信息是P3口的低四位,若是按键按下为“0”,则P3.0为“0”,P3.1-P3.3为“1”;同时,列信息是P3口的高四位,若是按键按下为“0”,则P3.4为“0”,P3.5-P3.7为“1”;由此可得,其被赋值为“0xee”。以此类推,之后一直到“case 0x77: key=15; break;”为止,都是采用相同的方法去赋值的。6 总结 按照原理图进行元件焊接后可以进行简单的+、-、*、%运算,实现了课程设计的要求,但还有缺陷,如不能进行连续的运算,进行一次运算后不能对结果进行二次运算,有待改进。另外,只能进行简单的四则运算,不能进行复杂的科学计算,有进一步改进的空间。下图为最终完成实物图及运算结果。 图 6-1 最终实物图参考文献1 胡辉.单片机原理与应用.北京水利水电出版社,2007.2 郭天祥.新概念51单片机c语言教程.电子工业出版社,2009.3 阎石.数字电子技术基础.高等教育出版社,2006.4 傅丰林.陈健.低频电子线路.高等教育出版社,2008.5 李建忠.单片机原理及应用.西安电子科技大学出版社,2010.附录 软件程序#include<reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned intsbit lcden=P22;/这是LCD使能端sbit lcdrw=P21;/这是LCD读写选择端sbit lcdrs=P20;/这是LCD数据命令选择端uchar code table='0','1','2','3','4','5','6','7','8','9', '+','-','*','/','=','.'uchar key,flag1,js,k1,k2;uchar a20,b20;float jieguo=0;void delay(uchar z)/延时函数 uchar x,y; for(x=z;x>0;x-) for(y=110;y>0;y-);void write_cmd(uchar cmd)/LCD写命令函数 lcdrs=0;/写指令控制端为低 P0=cmd; delay(5); lcden=1;/给个高脉冲结束 delay(4); lcden=0;void write_data(uchar date)/写数据函数 lcdrs=1;/写数据控制端高电平 P0=date; delay(5); lcden=1;/给个高脉冲结束 delay(5); lcden=0; void init()/液晶初始化函数lcdrw=0; lcden=0; write_cmd(0x38);/设置16*2显示,8位数据接口 write_cmd(0x0c);/设置开显示,不显示光标 (关显示是0x08) write_cmd(0x06);/写一个字符后地址指针加1 write_cmd(0x01);/清屏void keyscan()/键盘扫描程序 uchar temp,uu=0xf7; uint i; for(i=0;i<4;i+) uu=_crol_(uu,1);/_crol_为左移函数 P3=uu; temp=P3; temp=temp&0x0f; if(temp!=0x0f) delay(10); temp=P3;temp=temp&0x0f;if(temp!=0x0f) temp=P3; switch(temp) case 0xee: key=0; break; case 0xde: key=1; break; case 0xbe: key=2; break; case 0x7e: key=3; break; case 0xed: key=4; break; case 0xdd: key=5; break; case 0xbd: key=6; break; case 0x7d: key=7; break; case 0xeb: key=8; break; case 0xdb: key=9; break; case 0xbb: key=10; break; case 0x7b: key=11; break; case 0xe7: key=12; break; case 0xd7: key=13; break; case 0xb7: key=14; break; case 0x77: key=15; break; while(temp!=0x0f) temp=P3; temp=temp&0x0f; flag1=1; void jscl()/计算并显示函数 uchar i,j,n; float s,temp2; long int s1,s2,a1,b1,c1,temp1; a1=b1=1; s1=s2=0; s=0; if(k2!=0) for(j=0;j<k1+1;j+)/存放第一操作数 for(i=0;i<k1-j;i+) a1=a1*10; s1=s1+aj*a1; a1=1; for(j=k1+1;j<k2+1;j+)/存放第二操作数 for(i=0;i<k2-j;i+) b1=b1*10; s2=s2+aj*b1; b1=1; if(js=10)/判断是什么运算,并执行运算 s=s1+s2; if(js=11) s=s1-s2; if(js=12) s=s1*s2; if(js=13) s=(s1*0.1)/(s2*0.1); jieguo=s; else s=jieguo; c1=(long int)(s*1000)%10; if(c1>5 | c1=5) s=s+0.01; temp1=(long int)(s);/以下部分处理结果 temp2=s-temp1; n=0; while(temp1) bn=temp1%10; temp1=temp1/10; n+; bn=temp2*10; bn+1=(uchar)(temp2*100)%10; for(i=n;i>0;i-)/在液晶上显示结果 write_data(tablebi-1); write_data(table15); write_data(tablebn); write_data(tablebn+1);void main() uchar i,j; init(); write_cmd(0x80);/将液晶指针定位在第一行第一个单元 key=15; i=flag1=0; while(1) keyscan(); if(flag1=1) if(key=15) write_cmd(0x01); i=0; for(j=0;j<20;j+) aj=bj=0; k1=k2=0;else if(key<10) write_data(tablekey); ai=key; i+;else if(key<14) write_data(tablekey); k1=i-1; js=key;else write_data(tablekey); if(i=0) k2=0; else k2=i-1; write_cmd(0x80+0x40);/将液晶指针定位在第二行第一个单元 jscl(); flag1=0;