目录
1绪论.............................................................................................................................. 1
1.1选题背景............................................................................................................. 1
1.2起源与发展.......................................................................................................... 1
1.3研究的目的和意义............................................................................................... 2
2项目总体设计框架......................................................................................................... 2
2.1芯片STC89C52.................................................................................................... 2
2.2采用矩阵式键盘作为输入模块.............................................................................. 2
2.3显示模块............................................................................................................. 3
2.4硬件资源分配...................................................................................................... 3
3计算器硬件设计............................................................................................................ 4
3.1系统组成及硬件框图............................................................................................ 4
3.2元器件简介.......................................................................................................... 4
3.2.1 STC89C52的特点........................................................................................ 4
3.2.2 LCD1602 液晶显示屏.................................................................................. 5
4系统电路设计................................................................................................................ 6
4.1键盘电路设计...................................................................................................... 7
4.2显示电路设计...................................................................................................... 8
4.3其他电路部分...................................................................................................... 8
4.3.1 蜂鸣器模块............................................................................................... 8
4.3.2 电源模块................................................................................................... 9
4.3.3 单片机最小系统........................................................................................ 9
5计算器软件设计........................................................................................................... 10
5.1整体设计结构..................................................................................................... 10
5.2液晶屏读写函数................................................................................................. 10
5.2.1 初始化函数.............................................................................................. 10
5.2.2 写命令函数.............................................................................................. 11
5.2.3 写数据函数.............................................................................................. 11
5.3接收矩阵键盘输入函数....................................................................................... 12
5.4调试和运行程序................................................................................................. 13
5.4.1 Proteus仿真运行程序................................................................................ 13
5.4.2 在实验箱上运行程序................................................................................ 13
6总结............................................................................................................................ 14
基于51单片机的简易计算器
摘要:近几年单片机技术的发展很快,其中,电子产品的更新速度迅猛。计算器是日常生活中比较常见的电子产品之一。如何才能使计算器技术更加的成熟,充分利用已有的硬件和软件条件,设计出更出色的计算器。
本设计是以STC89C52单片机为核心的计算器模拟系统设计,输入采用4*4矩阵键盘,可以进行加、减、乘、除带符号数字运算(六位整数或两位小数点点),并在液晶显示屏LCD1602上静态显示操作过程及结果。对字符液晶显示模块的工作原理,如初始化、清屏、显示、调用及外特性有较清楚的认识,并会使用LCD(液晶显示模块)实现计算结果的显示;掌握液晶显示模块的驱动和编程,设计LCD和单片机的接口电路,以及利用单片机对液晶显示模块的驱动和操作;在充分分析内部逻辑的概念,进行软件和调试,学会使用,并能够以其为平台设计出具有四则运算能力简易计算器的硬件电路和软件程序。
关键词:单片机;液晶显示器;计算器;矩阵键盘
1绪论
1.1选题背景
现如今,人们的日常生活中已经离不开计算器了,社会的各个角落都有它的身影,比如商店、办公室、学校……因此设计一款简单实用的计算器会有很大的实际意义[1]。本设计旨在进一步掌握单片机理论知识,理解单片机系统的硬软件设计,加强对实际应用系统设计的能力。通过本设计的学习,使我掌握单片机程序设计的基本方法,并能综合运用本科阶段所学软、硬件知识分析实际问题,提高解决毕业设计实际问题的能力,为单片机应用和开发打下良好的基础。
1.2起源与发展
计算器是最早的计算工具,例如:奇普(Quipu或khipu)是古代印加人的一种结绳记事的方法,用来计数或者记录历史。它是由许多颜色的绳结编成的。
还有古希腊人的安提凯希拉装置,中国的算盘等。中国古代最早采用的一种计算工具叫筹策,又被叫做算筹。这种算筹多用竹子制成,也有用木头,兽骨充当材料的。约二百七十枚一束,放在布袋里可随身携带。直到今天仍在使用的珠算盘,是中国古代计算工具领域中的另一项发明,明代时的珠算盘已经与现代的珠算盘几乎相同。
早期的计算器为纯手动式,如算盘、算筹等。算盘通常是以滑动的珠子制成。在西方,算盘在印度阿拉伯数字流行前使用了数个世纪,且在近代中国的记帐与商务上仍广泛使用。后来出现机械计算器。17世纪初,西方国家的计算工具有了较大的发展,英国数学家纳皮尔发明的"纳皮尔算筹",英国牧师奥却德发明了计圆柱型对数算尺,这种计算尺不仅能做加减乘除、乘方、开方运算,甚至可以计算三角函数,指数函数和对数函数,这些计算工具不仅带动了计算器的发展,也为现代计算器发展奠定了良好的基础,成为现代社会应用广泛的计算工具。
1.3研究的目的和意义
计算器使用的是固化的处理程序,只能完成特定的计算任务;而计算机借助操作系统平台和各类应用软硬件,可以无限扩展其应用领域。也就是说,是否具有扩展性是二者的本质区别[2]。
单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。概括的讲:一块芯片就成了一台计算机。在计算机应用与智能化控制的科学家、工程师手中,它和计算机的本质相同,可以开发出针对各类电子电气产品的应用,例如洗衣机。但对于用户来说,他们并不需要知道洗衣机里的单片机的接口和编程语言,只要能操作洗衣服就行,因此单片机用于某个具体的电子产品上就需要配合简洁方便的人机界面,用户只使用它的特定功能。
2项目总体设计框架
2.1芯片STC89C52
单片机是单片微型机的简称,故又称为微控制器MCU(Micro Control Unit)。通常由单块集成电路芯片组成,内部包含有计算机的基本功能部件:中央处理器CPU,存储器和I/O接口电路等。因此,单片机只要和适当的软件及外部设备相结合,便可成为一个单片机控制系统。单片机广泛应用于智能产品,智能仪表,测控技术,智能接口等,具有操作简单、实用方便、价格便宜等优点[3]。
而其中STC89C52是一种带8K字节闪烁可编程可擦除只读存储器(FPEROM-Flash Programable
and Erasable Read Only Memory)的低电压,高性能COMOS8的微处理器。该器件与工业标准的MCS-51指令集和输出管脚相兼容;且是单片机中最典型的代表,应用于各种控制领域[4]。
2.2采用矩阵式键盘作为输入模块
矩阵式按键输入模块,其特点是:电路和软件稍复杂,但相比之下,当键数越多时,越节约I/O口,比较节省资源。其原理图如图1所示。
图1 矩阵键盘输入
Fig.1 Matrix keyboard input
2.3显示模块
采用LED数码管的静态显示,其特点是:其亮度较高;这种显示方式接口,编程容易且管理简单;不足的是,占用的I/O的线资源较多。如果采用单片机或CPLD/FPGA来控制的话,势必存在浪费I/O口资源的问题[5]。采用LED数码管的动态显示,其特点是:其亮度比静态显示的亮度要差一些;但其电路比较简单,适合于显示位数较多的情况。采用LCD1602液晶显示,如图2所示,其特点是:可以调节其背光亮度,这种显示方式接口,编程虽然有些麻烦,但管理较方便,占用的I/O口资源线也不多。在计算器运算中,需显示的数字、符号较多,按很据个方面的特点,而后可以发现LCD液晶显示,虽然在价格上的确是稍贵于LED数码管;但数码管在硬件设计电路中,会因线太多、线路复杂而过于繁琐,则舍弃LED数码管,选择LCD液晶显示[6]。
图2 LCD 1602液晶显示屏
Fig.2 1602 liquid crystal display
2.4硬件资源分配
主要用到的硬件:单片机STC89C52 、液晶显示屏LCD1602 、4*4按键键盘
硬件分配:
P1口:作为输入口,与键盘连接,实现数据的输入。
P0、P2口:作为输出口(P2口为高位,P0口为低位),控制LCD液晶显示屏显示数据的结果。
液晶显示屏LCD1602显示输出。
3计算器硬件设计
3.1系统组成及硬件框图
显示模块
蜂鸣器电路
矩阵键盘输入模块
图3 系统组成及硬件框图
Fig.3
System composition and hardware block diagram
3.2元器件简介
3.2.1 STC89C52的特点
图4 STC89C52 单片机
Fig.4
Single chip microcomputer STC89C52
主要性能:
与MCS-51单片机产品兼容;8K字节在系统可编程Flash存储器;1000次擦写周期;全静态操作:0Hz-33Hz;三级加密程序存储器;32个可编程I/O口线、三个16位定时器/计数器、8个中断源;全双工UART串行通信;低功耗空闲和掉电模式,掉电后中断可唤醒;看门狗定时器;双数据指针;掉电标识符[7]。
STC89C52的功能特性概述
STC89C52是一种低功耗、高性能CMOS 8位微控制器,具有8K在系统可编程Flash存储器。使用高密度非易失性存储器技术制造,与工业80C51产品指令和引脚完全兼容。片上Flash允许程序存储器在系统可编程,亦适于常规编程器。
3.2.2 LCD1602 液晶显示屏
液晶显示原理
液晶显示的原理是利用液晶的物理特性,通过电压对其显示区域进行控制,有电就有显示,这样即可以显示出图形[8]。液晶显示器有厚度薄、适用于大规模集成电路直接驱动、易于实现全彩色显示的特点,目前已经被广泛应用在便携式计算机、数字摄像机、PDA移动通信工具等众多领域。
LCD1602的应用简介
LCD1602液晶显示器采用HD44780及其兼容芯片作为点阵式LCD的控制器驱动器,还采用HD44100进行LCD的时分割驱动。HD44780的内部结构主要包括显示数据RAM(DDRAM)、字符发生器ROM(CGROM)、字符发生器RAM(CGRAM)、指令寄存器IR、数据寄存器DR、地址计数器AC(Address Counter)和忙标志BF(Busy Flag)等逻辑电路[9]。
1602液晶模块内部的控制器共有11条控制指令,丰富的指令可以完成液晶的时序控制、工作方式设置和数据显示等。
采用的LCD1602液晶模块是标准16针插座,接口电路如图5所示,及各引脚说明如表1所示。
图5 LCD1602引脚接口电路图
Fig.5
Pin interface circuit diagram of LCD1602
表1 LCD1602 引脚说明
Table.1
LCD1602 pin description
第1脚
Vss为地电源
第2脚
VDD接5V正电源
第3脚
Vo为液晶显示器对比度调整端,接电源正极时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度。
第4脚
Rs为寄存器选择,高电平选择数据寄存器、低电平选择指令寄存器。
第5脚
Rw为读写信号线,高电平时进行读操作,低电平时选择指令寄存器。
第6脚
E端为使能端,当E端由高电平跳变成低电平时,液晶模块执行命令。
第7-14脚
D0-D7为8位双向数据线。
第15-16脚
背光阳极和背光阴极。
其他方面介绍
DDRAM用来暂存显示字符的代码,共80个字节,DDRAM的各个单元对应着显示屏上的各个字符位,如图6所示。因此,DDRAM的地址也就意味着显示字符的地址,显示字符时首先要向LCD传送显示字符地址。
LCD
16字*2行
00
01
02
03
04
05
06
07
08
09
0A
0B
0C
0D
OE
OF
10
……
27
40
41
42
43
44
45
46
47
48
49
4A
4B
4C
4D
4E
4F
50
……
67
图6 DDRAM单元地址与显示屏字符位的对应关系
Fig.6
Correspondence between DDRAM unit address and display character bits
4系统电路设计
为了更好地实现系统的功能,硬件电路的设计应该遵循以下原则:
优化硬件电路
采用软件设计与硬件设计相结合的方法。尽管采用软件来实现硬件系统的功能时,也许响应的时间会比单纯使用硬件时长,而且还要占用微处理器MCU的时间;但是,用软件实现硬件的功能可以简化硬件结构,提高电路的可靠性。所以,在设计本系统的时候,在满足可靠性和实时性的前提下,尽可能地通过软件来实现硬件功能。
可靠性及抗干扰设计
根据可靠性设计理论,系统所用芯片数量越少,系统的平均无故障时间越长。而且,所用芯片数量越少,地址和数据总线在电路板上受干扰的可能性也就越小。因此,系统的设计思想是在满足功能的情况下争取较少数量的芯片。
灵活的功能扩展
功能扩展是否灵活是衡量一个系统优劣的重要指标。一次设计往往不能完全考虑到系统的各个方面,系统需要不断完善以及进行功能升级。进行功能扩展时,应该在原有设计的基础上,通过修改软件程序和少量硬件完成。对于本系统而言,就是要求在系统硬件不变的情况下,能够通过修改软件程序,完成功能的升级和扩展[10]。
根据提出的系统设计方案,结合以上三条原则,确定了系统硬件的设计。计算器主要由以下一些功能模块组成:非编码键盘模块、运算模块(单片机内部)、LCD液晶显示模块等。
该系统的硬件设计采用了模块化的设计方法。STC89C52单片机与LCD液晶显示屏显示电路是整个电路的核心,它们能实现系统的功能要求。
简易计算器主要包括:键盘电路、运算电路、输出显示电路。
前面说明了该系统的设计,系统采用了比较简单的设计方案,所以该系统的硬件设计的总外围电路不会产生过多的干扰。下面对系统的外围电路分别作了说明。键盘部分采用4*4按键键盘,显示部分采用LCD液晶显示屏完全能够很好地实现显示方面的要求。
4.1键盘电路设计
键盘可分为两类:编码键盘和非编码键盘。编码键盘是较多按键(20个以上)和专用驱动芯片的组合;当按下某个按键时,它能够处理按键抖动、连击等问题,直接输出按键的编码,无需系统软件干预。
通用计算机使用的键盘就是编码键盘。在智能仪器中,使用并行接口芯片8279或串行接口HD7279均可以组成编码键盘,同时还可以兼顾数码管的显示驱动,其相关的接口电路和接口软件均可在芯片资料中得到。当系统功能比较复杂,按键数量很多时,采用编码键盘可以简化软件设计[11]。
非编码键盘成本低廉。从成本角度出发,本设计选用的是非编码键盘。如图7所示。
图7 键盘电路设计
Fig.7
Keyboard circuit design
4.2显示电路设计
当系统需要显示少量数据时,采用LCD液晶显示屏进行显示是一种经济实用的方法。P0口作为液晶显示的数据端口,P2.0-P2.2口作为其控制端口,控制LCD液晶显示屏显示输出数据。最终显示电路如图8所示
图8 液晶显示电路设计
Fig.8
Liquid crystal display circuit design
4.3其他电路部分
4.3.1 蜂鸣器模块
蜂鸣器在电路中主要用来每按下一次按键后,蜂鸣器就发出一次声响,以提示用户已经按下了按键,其电路部分如图9所示。
图9 蜂鸣器模块电路设计
Fig.9
Buzzer module circuit design
4.3.2 电源模块
图10 电源模块电路设计
Fig.10
Power module circuit design
4.3.3 单片机最小系统
图11单片机最小系统电路设计
Fig.11
Minimal system circuit design of single chip microcomputer
5计算器软件设计
5.1整体设计结构
在软件中主要定义了delay()延时函数、lcdwrc()写命令、lcdwrd()写数据、光标定位、lcdinit()初始化、keyscan()按键检测、main()等几个函数,其中最为复杂的就是按键检测函数,在主函数中只是调用是初始化函数,然后死循环keyscan()按键检测函数,具体如图12所示。
图12整体设计结构
Fig.12
Overall design structure
5.2液晶屏读写函数
5.2.1 初始化函数
使用lcd1602液晶显示模块前,需要对其显示模式,进行初始化设置,在初始化函数中,使用了lcd中的几条命令:
写入0x38:两行显示,5x7点阵,8位数据,执行空操作,给硬件反应时间。
写入0x0f:开整体显示,打开光标,打开光标闪烁,执行空操作,给硬件反应时间。
写入0x05:写入一个字符后,地址指针加一,光标左移,执行空操作,给硬件反应时间。
写入0x01:清屏。
具体实现的代码如图13所示。
图13初始化函数
Fig.13
Initialization function
5.2.2 写命令函数
按照规定,RS和E必须同时为0时,才可以写入命令,将命令写入P0口中,写命令时,E应为正脉冲,即正跳变,所以前面先置E=0,然后给一点延时,等待机器反应,E由高电平变为低电平,LCD开始执行命令;具体实现的代码如图14所示。
图14写命令函数
Fig.14
Write command function
5.2.3 写数据函数
写数据就是将要显示字符的ACSⅡ码写入LCD 1602液晶显示模块中的显示数据RAM(DDRAM);按照规定,写数据时,E应为正脉冲,首先先置E=0,其中RS=1和RW=0时,才可以写入数据,然后将数据从P0口输入,即写入LCD 1602液晶显示模块,当E有高电平变为低电平,写数据操作结束,具体实现代码如图15所示。
图15写数据函数
Fig.15
Write data function
5.3接收矩阵键盘输入函数
接收举证键盘输入函数是整个程序中最主要的函数,在此函数中,通过八根 I/O 口线组成一个 4×4=16 的矩阵键盘,单片机对其进行扫描,把按下键的键值显示在显示屏上。
查看实验箱上的电路图(见图16),可看到 16 个按键分别通过 4 根行线和 4 根列线交叉组成,其中 4 根行线分别接到了单片机的 P1.4~P1.7 口,4 根列线分别接到了单片机的 P1.0~P1.3 口,这样一个 P1 端口就接了 16 个按键。
图16矩阵键盘电路
Fig.16
Matrix keyboard circuit
矩阵式键盘的按键识别方法一般有三种,即:行扫描法、行列扫描法和行反转法。在实际应用中,由于行反转法速度较快,所以应用较为广泛,本例就采用这种方法;
行反转法的基本原理是:将行线接一个数据端口,让它先工作在输出模式,将列线也接到一个数据端口,让它先工作在输入模式;让 CPU 通过输出端口向行线上全部送出低电平,然后读入列线上的值,如果此时有键被按下,则必定会使某列线值为低电平;接着对两个端口进行模式改变,使接行线的端口改为输入模式,接列线的端口改为输出模式,并且将刚才读得的列值从列线所接端口输出,再读取行线的值, 那么闭合健所在的行线值必定为低电平;这样,当一个按键被按下时, 必定可以读得一对唯一的行值和列值;
这样我们就可以把得到的值通过写命令,把值写入到液晶显示屏中,并保存记录下这个值,当输入符号位时,进行清屏操作,并记录下所按下符号的键值,最后当用户按下等号时,根据所输入的数据和运算符,得出相应的结果,并把结果输出到显示屏中,这样就完成了一次运算;当按下清屏键时,lcd 1602执行清屏操作,又恢复到光标闪烁,初始化界面。
5.4调试和运行程序
5.4.1 Proteus仿真运行程序
首先在电脑上搭建Proteus仿真平台,在平台上绘制出本次设计的电路图,把程序生产的hex文件下载到C52单片机中,然后启动仿真,在仿真环境中就可以测试程序设计是否符合要求,其效果如图17所示。
图17 Proteus仿真
Fig.17
Proteus simulation
5.4.2 在实验箱上运行程序
首先将实验箱ME850通过数据线与电脑连接,打开实验箱开关,将实验箱上的JP15(蜂鸣器)和JP25(背光)跳线帽接上,JP24跳线帽改接到NO上,4x4矩阵键盘的8个跳线帽也接上,试验箱的主板电路布局如图18所示。
图18 ME850硬件布局
Fig.18
ME850 hardware layout
通过专用的烧写工具MEFlash,将hex文件烧写到ME850试验箱中,就可以运行程序了,烧写完成以后实现的效果如图19所示。
图19 在开发板上的实现效果
Fig.19
Implementation effect on the development board
6总结
我认为,学编程读别人的程序非常重要,每个人都有不同的思维,相同的任务却有很多不同的方法,在每个程序里都能找到些经典的段子,让人回味。从中可以学到很多的方法,并且有些可以直接的引用。一个出色的程序员在编程时,并不是从零开始,而应该是先找出类似的例子进行分析,参考,看看有没有值得引用和借鉴的地方,加以修改,为自己所用。实践证明,这样做是对的。
基本功要杂实,要有一定的数模电基础。学单片机首先要搞清楚它的基本结构和存储单元的分配。
多读有代表性的程序,读得多了自然就会学到很多的好方法。可买本单片机子程序集看看,也可网上下载程序分析。
我觉得以上几点相当重要,因为它对我帮助很大,算是将我领进了单片机的大门,以至于我学起来不那么吃力,没有感觉到 像大家说的那样的难。我看过很多的程序,也调试过很多的程序,每一次收获都不小。我的实验室就是KEIL和PROTEUS。这使我做实验很方便。虽是虚拟的,但调试程序还是可以的,省去了很多的时间提高了效率。最近我在学C51,因为学单片机掌握C语言是非常重要的,C语言的通用性对学习其它类型的单片机有很大的帮助。今后,我想做嵌入式系统工程师,想学ARM,想搞操作系统。所以我现在必须打好基础,这样才能进步。
通过这种途径的实践教学活动,我们将前几年所学的知识综合起来了,将所学的知识应用于实践中去了。这样,到了社会上我们就更有竞争力了。
实践证明,通过该课程设计,不仅提高了学生学习的兴趣,加深了对专业知识的理解,开阔了视野,也为以后毕业设计打下良好的基础。单片机课程设计这一实践教学环节的有效开展,有助于学生有效地掌握所学知识,缩短从理论知识到实际应用的过程,很好地培养了学生的专业兴趣,增强了学生的创新意识,提高了学生的动手能力和实际应用能力。
结语
经过了两个多星期的学习和工作,我终于完成了《基于51单片机的简易计算器》的课程设计。从开始接到课程设计题目到系统的实现,再到课程设计文章的完成,每走一步对我来说都是新的尝试与挑战,这也是我在大学期间独立完成的最大的项目。在这段时间里,我学到了很多知识也有很多感受,从对C52单片机的一无所知,对动态扫描,矩阵键盘等相关技术很不了解的状态,我开始了独立的学习和试验,查看相关的资料和书籍,让自己头脑中模糊的概念逐渐清晰,使自己非常稚嫩作品一步步完善起来,每一次改进都是我学习的收获,每一次试验的成功都会让我兴奋好一段时间。从中我也充分认识到了单片机给我们生活带来的乐趣,在属于自己的编程器件上,尽情宣泄自己的情感,表达自己的感受,并且把自己的想法与他人分享,我也有了一个属于自己可控制的单片机。
虽然我的课程设计作品不是很成熟,还有很多不足之处,但我可以自豪的说,这里面的每一段代码,都有我的劳动。当看着自己的程序,自己成天相伴的系统能够健康的运行,真是莫大的幸福和欣慰。我相信其中的酸甜苦辣最终都会化为甜美的甘泉。
这次做课程设计的经历也会使我终身受益,我感受到做课程设计是要真真正正用心去做的一件事情,是真正的自己学习的过程和研究的过程,没有学习就不可能有研究的能力,没有自己的研究,就不会有所突破,那也就不叫课程设计了。希望这次的经历能让我在以后学习中激励我继续进步。
先上仿真图
实测效果图
源代码:
#includetypedef unsignedcharuint8;
typedef unsignedintuint16;
unsignedchardataw;
sbit BEEP=P3^7;
sbit rw=P2^1;
sbit rs=P2^0;
sbit e=P2^2;//sbit rw=P2^5;//sbit rs=P2^6;//sbit e=P2^7;//sbit BEEP=P1^5;
uint8 key,num;
uint8 fuhao;//定义具体的那个符号,是加减还是乘除。
uint8 flag; //定义有没有按下符号键
long a,b,c,d; //定义运算数据的第一个和第二个及等于的数变量
uint8 k; //定义小数点后面显示的位数
uint8 biao;int bz=0;
uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存显示的数据
const unsigned char str0[] = {"NUM INPUT"};const unsigned char str1[] = {"NUM INPUT NEXT"};const unsigned char str2[] = {"RESULT SHOW"};//const unsigned char str3[] = {" "};
void delay(uint16 i)//延时
{while(i--);
}void buzzer()//蜂鸣器
{for(bz=490;bz>0;bz--){
BEEP=~BEEP;
delay(10);
}
BEEP=1;
}void lcdwrc(uint8 c)//写入命令
{
delay(1000);
rs=0;
rw=0;
e=0;
P0=c;
e=1;
delay(1000);
e=0;
}void lcdwrd(unsigned char dataw)//写入数据
{
delay(1000);
rs=1;
rw=0;
e=0;
P0=dataw;
e=1;
delay(1000);
e=0;
rs=0;
}void ePutstr(unsigned char const *ptr)
{
unsignedchar i,j = 0;
lcdwrc(0x01);while(ptr[j] > 31)
j++; //ptr[j]>31 时为 ASCII 码,j 累加,计算出字符串长度
for(i = 0; i < j; i++)
{
lcdwrd(ptr[i]);//显示单个字符,同时x坐标递增
}//lcdwrc(0x4f+0x80);
}void lcdinit()//初始化,复位过程
{
delay(1500);
lcdwrc(0x38);//不检测忙信号
delay(500);
lcdwrc(0x38);//不检测忙信号
delay(500);
lcdwrc(0x38);//不检测忙信号
delay(500);
lcdwrc(0x38);//不检测忙信号
lcdwrc(0x08);//显示关闭
lcdwrc(0x01);//显示清屏
lcdwrc(0x06);//显示光标移动设置
ePutstr(str0);
lcdwrc(0x4f+0x80);
lcdwrc(0x0f);//显示开及光标设置
key=0;
num=0;
flag=0;
fuhao=0;
a=0;
b=0;
c=0;
d=0;
biao=0;
}voidqingpin(){
lcdwrc(0x01);
ePutstr(str1);
lcdwrc(0x4f+0x80);
lcdwrc(0x0f);
}void zhongduan(void) interrupt 0 using 0 //外部中断0中断函数
{
lcdwrc(0x01);
a=0;
b=0;
flag=0;
fuhao=0;
ePutstr(str0);
lcdwrc(0x4f+0x80);
lcdwrc(0x0f);
}void keyscan()//按键检测
{
P1=0xfe; //令第一行为0,然后判断是哪一列按下
if(P1!=0xfe)
{
buzzer();
delay(1000);if(P1!=0xfe)
{
key=P1&0xf0;switch(key)
{case 0xe0: num=0;break; //1
case 0xd0: num=1;break; //2
case 0xb0: num=2;break; //3
case 0x70: num=3;break; //加
}
}while(P1!=0xfe);if(num==0||num==1||num==2) //确认第一行的数1,2,3
{if(flag==0) //没有按下符号键
{
a=a*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30+dat1[num]);//lcdwrc(0x1c);//ePutstr(str0);
}else{
b=b*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30+dat1[num]);//lcdwrc(0x1c);//ePutstr(str0);//lcdwrc(0x4f+0x80);
}
}if(num==3)
{
flag=1;//有符号键按下
fuhao=1;//加号+//ePutstr(0,1,str3);//lcdwrc(0x0c);
qingpin();
}
}
P1=0xfd; //令第二行为0,判断是哪一列按下
if(P1!=0xfd)
{
buzzer();
delay(1000);if(P1!=0xfd)
{
key=P1&0xf0;switch(key)
{case 0xe0: num=4;break; //4
case 0xd0: num=5;break; //5
case 0xb0: num=6;break; //6
case 0x70: num=7;break; //减—
}
}while(P1!=0xfd);if(num==4||num==5||num==6)
{if(flag==0) //没有按下符号键
{
a=a*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30+dat1[num]);
}else{
b=b*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30+dat1[num]);
}
}else{
flag=1;//有符号键按下
fuhao=2;//带表减号//ePutstr(0,1,str3);//lcdwrc(0xc);
qingpin();
}
}
P1=0xfb; //令第三行为0,判断哪一列按下
if(P1!=0xfb)
{
buzzer();
delay(1000);if(P1!=0xfb)
{
key=P1&0xf0;switch(key)
{case 0xe0: num=8;break; //7
case 0xd0: num=9;break; //8
case 0xb0: num=10;break; //9
case 0x70: num=11;break; //乘*
}
}while(P1!=0xfb);if(num==8||num==9||num==10)
{if(flag==0) //没有按下符号键
{
a=a*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30+dat1[num]);
}else{
b=b*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30+dat1[num]);
}
}else{
flag=1;
fuhao=3;//带表乘号*//ePutstr(0,1,str3);//lcdwrc(0xc);
qingpin();
}
}
P1=0xf7; //令第四行为0,判断哪一列按下
if(P1!=0xf7)
{
buzzer();
delay(1000);if(P1!=0xf7)
{
key=P1&0xf0;switch(key)
{case 0xe0: num=12;break; //0
case 0xd0: num=13;break; //清除rst
case 0xb0: num=14;break; //等号=
case 0x70: num=15;break; //除/
}
}while(P1!=0xf7);switch(num)
{case 12:if(flag==0) //没有按下符号键
{
a=a*10+dat1[num];
lcdwrd(0x30);
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
buzzer();
}else{
b=b*10+dat1[num];
lcdwrc(0x0f);//光标闪烁
lcdwrc(0x04);//设置光标左移,屏幕不移动
lcdwrd(0x30);
}break;case 13:
lcdwrc(0x01); //清屏指令
a=0;
b=0;
flag=0;
fuhao=0;
ePutstr(str0);
lcdwrc(0x4f+0x80);
lcdwrc(0x0f);//光标闪烁
break;case 15:
flag=1;
fuhao=4;//ePutstr(0,1,str3);//除号///lcdwrc(0xc);
qingpin();break;case 14:
lcdwrc(0xc);
ePutstr(str2);
lcdwrc(0x04);//设置光标左移,屏幕不移动
if(fuhao==1)//加
{
lcdwrc(0x4f+0x80);
c=a+b;while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}if(fuhao==2) //减
{
lcdwrc(0x4f+0x80);if(a>b)
c=a-b;elsec=b-a;while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}if(a
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}if(fuhao==3)//乘法
{
lcdwrc(0x4f+0x80);
c=a*b;while(c!=0) //一位一位显示
{
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
}
lcdwrd(0x3d); //显示等于号=
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}if(fuhao==4)//除法
{
lcdwrc(0x4f+0x80);
k=0;
c=(long)(((float)a/b)*1000);//强制转换为long。
while(c!=0) //一位一位显示
{
k++;
lcdwrd(0x30+c%10);//显示结果的最后一位在0x4f的位置
c=c/10;//取前面的结果数据
if(k==3)
{
lcdwrd(0x2e);//显示点
k=0;
}
}if(a/b<1) //如果a比b小的话那么除的结果最高位是0
{
lcdwrd(0x30);
}
lcdwrd(0x3d); //显示等号
a=0;
b=0;
flag=0;
fuhao=0;//全部清除为0
}break;
}
}
}voidmain()
{
EA=1;//总中断允许
EX0=1;//允许外部中断0中断
IT0=1;//选择外部中断0为触发方式
lcdinit();while(1)
{
keyscan();
}
}