电子秒表课程设计报告

电子信息工程专业10级学生单片机原理课程设计任务书

电子秒表的设计

一、设计要求

设计一个电子秒表,与通用秒表功能类似,有启动,暂停、复位等键。计时长长度为300秒,需显示百分秒。

二、设计方案分析

1.方案设计

数字电子秒表具有显示直观、读取方便、精度高等优点,在计时中广泛使用。本设计用单片机组成数字电子秒表,力求结构简单、精度高为目标。

本系统采用C51系列单片机为中心器件,利用其定时器/计数器定时和记数的原理,结合硬件电路如电源电路,晶振电路,复位电路,显示电路,以及一些按键电路等来设计计时器,将软、硬件有机地结合起来。其中软件系统采用汇编语言编写程序,硬件系统利用PROTEUS强大的功能来实现,简单切易于观察,在仿真中就可以观察到实际的工作状态。

本设计利用STC89C52单片机的定时器/计数器定时和计数的原理,使其能精确计时。利用中断系统使其能实现开始暂停的功能。根据要求知道秒表设计主要实现的功能是计时和显示。因此设置了两个按键和LCD显示时间,两个按键分别是开始、停止和复位按键。利用这两个建来实现秒表的全部功能,而LCD则能显示最多4.59.99秒的计时。电路原理图设计最基本的要求是正确性,其次是布局合理,最后在正确性和布局合理的前提下力求美观。硬件电路图按照图1.1进行设计。

图1.1 数字秒表硬件电路基本原理图

本设计中,数码管显示的数据存放在内存单元31H-33H中。其中31H存放分钟变量,32H存放秒钟变量,33H存放10ms计数值,即存放毫秒位数据,每一地址单元内均为十进制BCD码。由于采用软件动态扫描实现数据显示功能,显示用十进制BCD码数据的对应段码存放在ROM表中。显示时,先取出31H-33H某一地址中的数据,然后查得对应的显示位,并从P1口输出,就能显示该地址单元的数据值。

计时通过中断完成,定时溢出中断周期为1ms,当一处中断后向CPU发出溢出中断请求,每发出一次中断请求就对毫秒计数单元进行加一,达到10次就对十毫秒位进行加一,依次类推,直到4.59.99秒重新复位。

再看按键的处理。这两个键可以采用中断的方法,也可以采用扫描的方法来识别。复位键主要功能在于数值复位,对于时间的要求不是很严格。而开始和停止键则是用于对时间的锁定,需要比较准确的控制。因此可以对复位按键采取扫描的方式。而对开始和停止键采用外部中断的方式。

设计中包括硬件电路的设计和系统程序的设计。其硬件电路主要有主控制器,显示电路和回零、启动、查看、停表电路等。主控制器采用单片机STC89C52,显示电路采用LCD显示计时时间,两个按键均采用触点式按键。

2.背景知识介绍

2.1 单片机相关知识

本课题在选取单片机时,充分借鉴了许多成形产品使用单片机的经验,并根据自己的实际情况,  选择了STC89S51。

STC89C52单片机采用40引脚的双列直插封装方式。图1.2为引脚排列图, 40条引脚说明如下:

主电源引脚Vss和Vcc

①  Vss接地

②  Vcc正常操作时为+5伏电源

外接晶振引脚XTAL1和XTAL2

①  XTAL1内部振荡电路反相放大器的输入端,是外接晶体的一个引脚。当采用外部振荡器时,此引脚接地。   

②  XTAL2内部振荡电路反相放大器的输出端。是外接晶体的另一端。当采用外部振荡器时,此引脚接外部振荡源。

图1.2    STC89C52单片机引脚图

控制或与其它电源复用引脚RST/VPD,ALE//Vpp

①  RST/VPD  当振荡器运行时,在此引脚上出现两个机器周期的高电平(由低到高跳变),将使单片机复位在Vcc掉电期间,此引脚可接上备用电源,由VPD向内部提供备用电源,以保持内部RAM中的数据。

②  ALE/正常操作时为ALE功能(允许地址锁存)提供把地址的低字节锁存到外部锁存器,ALE 引脚以不变的频率(振荡器频率的1/6)周期性地发出正脉冲信号。因此,它可用作对外输出的时钟,或用于定时目的。但要注意,每当访问外部数据存储器时,将跳过一个ALE脉冲,ALE 端可以驱动(吸收或输出电流)八个LSTTL电路。对于EPROM型单片机,在EPROM编程期间,此引脚接收编程脉冲(功能)

③  外部程序存储器读选通信号输出端,在从外部程序存储取指令(或数据)期间,在每个机器周期内两次有效。同样可以驱动八LSTTL输入。

④  /Vpp、/Vpp为内部程序存储器和外部程序存储器选择端。当/Vpp为高电平时,访问内部程序存储器,当/Vpp为低电平时,则访问外部程序存储器。对于EPROM型单片机,在EPROM编程期间,此引脚上加21伏EPROM编程电源(Vpp)。

输入/输出引脚P0.0 - P0.7,P1.0 - P1.7,P2.0 - P2.7,P3.0 - P3.7。

①  P0口(P0.0 - P0.7)是一个8位漏极开路型双向I/O口,在访问外部存储器时,它是分时传送的低字节地址和数据总线,P0口能以吸收电流的方式驱动八个LSTTL负载。

②  P1口(P1.0 - P1.7)是一个带有内部提升电阻的8位准双向I/O口。能驱动(吸收或输出电流)四个LSTTL负载。

③  P2口(P2.0 - P2.7)是一个带有内部提升电阻的8位准双向I/O口,在访问外部存储器时,它输出高8位地址。P2口可以驱动(吸收或输出电流)四个LSTTL负载。

④  P3口(P3.0 - P3.7)是一个带有内部提升电阻的8位准双向I/O口。能驱动(吸收或输出电流)四个LSTTL负载。

AT89C52具有以下标准功能:8k字节Flash,256字节RAM,32 位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,AT89C52可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU停止工作,允许RAM、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。CPU是单片机的核心部件。它由运算器和控制器等部件组成。

(1) 运算器

运算器的功能是进行算术运算和逻辑运算。可以对半字节(4位)、单字节等数据进行操作。例如能完成加、减、乘、除、加1、减1、BCD码十进制调整、比较等算术运算和与、或、异或、求补、循环等逻辑操作,操作结果的状态信息送至状态寄存器。

89C52运算器还包含有一个布尔处理器,用来处理位操作。它是以进位标志位C为累加器的,可执行置位、复位、取反、等于1转移、等于0转移、等于1转移且清0以及进位标志位与其他可寻址的位之间进行数据传送等位操作,也能使进位标志位与其他可移位寻址的位之间进行逻辑与、或操作。

(2) 程序计数器PC

程序计数器PC用来存放即将要执行的指令地址,共16位,可对64K程序存储器直接寻址。执行指令时,PC内容的低8位经P0口输出,高8位经P2口输出。

(3) 令寄存器

指令寄存器中存放指令代码。CPU执行指令时,由程序存储器中读取的指令代码送入指令寄存器,经译码后由定时与控制电路发出相应的控制信号,完成指令功能。

本设计采用ATMEL的AT89C52微处理器,主要基于以下几个因素:

①  AT89C52为51内核,仿真调试的软硬件资源丰富。

②  性价比高,货源充足。

③  功耗低,功能强,灵活性高。

④  DIP40封装,体积小,便于产品小型化。

⑤  为EEPROM程序存储介质,1000次以上擦写周期,便于编程调试。

⑥  工作电压范围宽:2.7V-6V,便于交直流供电。

2.2  TC1602

LCD 的构造是在两片平行的玻璃当中放置液态的晶体,两片玻璃中间有许多垂直和水平的细小电线,透过通电与否来控制杆状水晶分子改变方向,将光线折射出来产生画面。比CRT要好的多,但是价钱较其贵。

1)LCD的特点

低压微功耗

  平板型结构

  被动显示型(无眩光,不刺激人眼,不会引起眼睛疲劳)

  显示信息量大(因为像素可以做得很小)

  易于彩色化(在色谱上可以非常准确的复现)

  无电磁辐射(对人体安全,利于信息保密)

长寿命(这种器件几乎没有什么劣化问题,因此寿命极长,但是液晶背光寿命有限,不过背光部分可以更换)

1602的管脚功能

三、硬件设计

本系统中,硬件电路主要有电源电路,晶振电路,复位电路,显示电路,以及一些按键电路等。

1.单片机简介

本系统设计采用C51系列单片机。

ST89C51是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8位微处理器。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容(由于在微机原理中学过C-51的具体知识,这里不再详细说明)。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ST89C51是一种高效的微控制器。

2.电源电路

电源电路是系统最基本的部分,任何电路都离不开电源部分,由于三端集成稳压器件所组成的稳压电源线路简单,性能稳定,工作可靠,调整方便,已逐渐取代分立元件,在生产中被广泛采用,由于是小系统,我们采用7809电源提供+5V稳压电压。

3.晶体振荡电路

MCS--51单片机内部的振荡电路是一个高增益反相放大器,引线 XTAL1和XTAL2分别为反向振荡放大器的输入及内部时钟工作电路的输入和来自反向振荡器的输出,该反向放大器可以配置为片内振荡器。

这里,我们选用51单片机12MHZ的内部振荡方式,电路如下:电容器C1,C2起稳定振荡频率,快速起振的作用,C1和C2可在20-100PF之间取,这里取30P,接线时要使晶体振荡器X1尽可能接近单片机。

图2 晶体振荡电路

4.复位电路

采用上电+按键复位电路,上电后,由于电容充电,使RST持续一段高电平时间。当单片机已在运行之中时,按下复位键也能使用使RST持续一段时间的高电平,从而实现上电加开关复位的操作。这不仅能使单片机复位,而且还能使

单片机的外围芯片也同时复位。当程序出现错误时,可以随时使电路复位。

电路图如下:

图3 复位电路

5.显示电路

显示电路既可以选用液晶显示器,也可以选用数码管显示。我们采用的是数码管显示电路。用2个共阳极LED显示,LED是七段式显示器,内部有7个条形发光二极管和1个小圆点发光二极管组成,根据各管的亮暗组合成字符。

在用数码管显示时,我们有静态和动态两种选择,静态显示程序简单,显示稳定,但是占用端口比较多;动态显示所使用的端口比较少,可以节省单片机的I/O口。

在设计中,我们采用LED动态显示,用P0口驱动显示。由于P0口的输出级是开漏电路,用它驱动时需要外接上拉电阻才能输出高电平。

电路图如下所示:

图4 显示电路

6.键盘电路

在按键电路中,我们可以在I/O口上直接接按键,或者通过I/O口设计一个键盘,然后通过键盘扫描程序判断是否有键按下等。键盘扫描电路节省I/O口,但编程有些复杂,在这里,由于我们所用的按键较少,且系统是一个小系统,有足够的I/O口可以使用,为了使程序简化,我们采用按键电路,用部分P3口做开关,P3.3为开始停止,P3.4为清零,用外部中断INT1开始,另外用软件法消除抖动。电路图如下所示:

图5 键盘电路

硬件主电路图设计

用pretues画出其硬件主电路图如下:

四、    软件设计

4.1软件设计概述

在软件设计中,一般采用模块化的程序设计方法,它具有明显的优点。把一个多功能的复杂的程序划分为若干个简单的、功能单一的程序模块,有利于程序的设计和调试,有利于程序的优化和分工,提高了程序的阅读性和可靠性,使程序的结构层次一目了然。

应用系统的程序由包含多个模块的主程序和各种子程序组成。各程序模块都要完成一个明确的任务,实现某个具体的功能,在具体需要时调用相应的模块即可。

功能描述:用LCD1602液晶显示"秒表",显示时间为0.00.00—4.59.99秒,每秒自动加1;一个"开始""暂停"键,一个"清零"键。

4.2主程序流程图

这里采用顺序结构,通过对按键的扫描,判断要实现什么功能。如下所示:

五、    测试数据及设计结果

1、按下INT1管脚的开关时,显示数据,如下图所示

2、按下T0管脚的开关时,数据清零,如下图所示

六、调试中出现的错误及解决方法

(1)   实验中遇到的问题及解决方法

问题:LCD显示模糊

原因:VEE接高电平,LCD的对比度太低,从而无法正常显示数据。

解决方法:将VEE接地,提高了LCD的对比度,数据显示清晰。

2)实验心得

XXX

接到题目时,发现是关于电子秒表的设计,先在网上查阅了一些有关电子秒表设计的材料,熟悉了设计思想与工作原理,并且具体的分析了单片机、数码管显示器的工作过程,从理论上分析了该工作过程。

在理解了该系统的工作原理并完成电路图的设计与仿真后,开始焊接电路板,在焊接时通过查阅,熟悉了各个管角的焊接原则,在焊接过程中,考虑到数码管布线相对较多,所以换用作LCD,焊接相对简单。

电路板焊接完成后,将程序考入单片机后开始测试,刚开始时LCD显示器无数据显示,经过对电路板各模块的重新测试,发现并无问题,经过和同学的探讨,发现LCD的VEE管脚接高电平时,因对比度低,导致LCD无数据显示;而当VEE接低电平时,因对比度高,LCD正常显示。

通过此次课程设计,熟悉了电子秒表的设计思想,在实践中测试电路、分析数据、排除故障,最终实现了设计要求。虽然这次课程设计相对简单,但并未一次性成功,所以同样需要严谨的态度。在整个过程中不但增强了自己的学习能力,还提高了自己的团队合作能力,这些能力在以后的工作中是很重要的!

XXX

上周三开始焊接设计好久的电路板,到今天基本已经完成了主要的焊接,初步总结一下这几天的心得。

1. 焊接cup时,首先要检查cpu的各个管脚,保证没有弯曲或者错位,不然焊上去之后就比较难搞了。然后将CUP各个管脚跟pcb板上的焊盘仔细的对齐(一定要保证顺序,cup右上角O标记顺时针方向的第一个管脚为1),然后用电烙铁轻轻烫一下管脚,由于CPU管脚和焊盘上均有少量的残锡,可以将CPU固定住,然后用电烙铁依次将管脚压平。接下来最关键的步骤:补锡。先在cup管脚的一端点少量焊锡,然后将一排管脚涂满松香,快速而缓慢的划过管脚......

2. 焊接电路要有分块化的思想,首先焊接电源模块,然后测试各个供电电压;然后焊接CPu模块,最后成功后焊接引出的管脚。

3. 晶振(Crystal)即为石英振荡器,是一种机电器件,是用电损耗很小的石英晶体经精密切割磨削并镀上电极焊上引线做成。这种晶体有一个很重要的特性,如果给他通电,他就会产生机械振荡,反之,如果给他机械力,他又会产生电,这种特性叫机电效应。他们有一个很重要的特点,其振荡频率与他们的形状,材料,切割方向等密切相关。由于石英晶体化学性能非常稳定,热膨胀系数非常小,其振荡频率也非常稳定,由于控制几何尺寸可以做到很精密,因此,其谐振频率也很准确。根据石英晶体的机电效应,我们可以把它等效为一个电磁振荡回路,即谐振回路。他们的机电效应是机-电-机-电....的不断转换,由电感和电容组成的谐振回路是电场-磁场的不断转换。在电路中的应用实际上是把它当作一个高Q值的电磁谐振回路。由于石英晶体的损耗非常小,即Q 值非常高,做振荡器用时,可以产生非常稳定的振荡,作滤波器用,可以获得非常稳定和陡削的带通或带阻曲线。

总体来说,这次的电路焊接还是比较顺利的。因为设计图设计的很好,所以在焊接结束后,板子的功能也全都如愿的顺利实现了。

XXX

这学期的课程设计,是利用单片机设计一些简单控制系统的相关实验,每个班有四个题目,我们分到的题目是:利用STC89C52单片机设计电子秒表,通过LCD显示器显示百、分、秒,通过按键实现计时、暂停、清零等功能,并且最大计时时间为300秒(即计时范围为0.00.00-4.59.99)。

  刚刚拿到题目时,就听周围的同学说,这次课设我们的“电子秒表”是最简单,课程设计的第一天老师就要求每个组必须选一位组长,并且每组组员必须分工合作,我有幸被选为组长。老师讲完后,我就针对每位组员的具体情况进行工作分配,我负责查资料和电路的设计及部分编程、张雪珍同学负责编程、张辛超同学负责焊电路板、夏沅睿同学负责写实验报告,大家分头行动,气乐融融。

  在电路设计初期,我对于如何设计“电子秒表”有点困惑,不了解百分秒的意思,为了让自己心里有个底,我先在图书馆找了相关书籍,并且在网上查了一些“秒表”的制作实例,在资料查询、分析并请教同学后,我发现直接用STC89C52和液晶显示屏1602设计最简单。

  确定了用什么器件后,我查了STC89C52的相关知识,它们的引脚图和各引脚的功能,以及其相关控制字,尤其是LCD1602的控制字及其初始化和显示编程。查清楚了个器件的功能后,我开始设计电路图。电路很简单,最难的是软件编程部分。硬件焊接方面,我们组的张辛超同学当仁不让,我给他说了我的想法后,他称焊接没问题,而且通过以前的课程设计我也见识过他的焊功,对他的硬件焊接很有信心。这个问题解决了,在数字的显示方面遇到点麻烦,老师要求我们用LED显示,但要按老师要求的去做,完全显示就要接5个数码管,这根本在PCD板上会很难焊,后来结合实际情况,我们借了一个LCD液晶显示屏,用个底座就完全OK了。这样不仅硬件焊接简单,对于编程也简单了许多。

  硬件电路设计好了,开始软件编程和仿真,软件仿真我是在Proteus软件上仿真的。由于我们的编程能力不是很强,我和组员张雪珍一起研究程序,遇到不懂、不会的地方就查阅资料,或者请教其他编程能力比较强的同学,经过三天的编程调试,最终在周四我们的电路和程序完全没问题,电路也就确定了。

周三我和组员张辛超在实验室焊接电路。他焊接电路,我在旁边订正,由于电路比简单,经过近三个小时的“奋战”终于焊接完工,焊接过程中我、也充分见识到了张辛超同学的焊接功底。

  焊接完成,周四开始调试,给89C51烧进程序,将芯片全部装好,接通电源发现LCD上什么都不显示,我仔细检查才发现LCD的第3管脚接高电平了,这导致LCD的对比度太低,无法正常数字,经更正后显示完全正常,正式请老师验收、答辩。

  通过这次课程设计使我懂得,脚踏实地,认真严谨,实事求是的学习态度,不怕困难、坚持不懈、吃苦耐劳的精神是我在这次设计中最大的收益。我想这是一次意志的磨练,是对我实际能力的一次提升,也会对我未来的学习和工作有很大的帮助。在这次课程设计中也使我和同学关系更进一步了,同学之间互相帮助,有什么不懂的大家在一起商量,听听不同的看法对我们更好的理解知识。

通过这次课设更大程度上锻炼了我的团队合作精神和领导能力。对我以后的学习生活有很大的帮助,它使我相信了“人的潜力是无限的”这句话,也使我懂得:只要用心,一定会发现每个人身上都有闪光点,只要正确运用,对别人可以增强他们的自信心,对自己会快速正确的完成任务。总之,对他人和自己都有莫大的帮助。

XXX

这次课程设计我们组的题目是设计一个电子秒表,有启动,暂停、复位等键。计时最长长度为300秒,需显示百分秒。据说是相对简单的题目。

分好组后我们每人都有分工,我的主要任务就是完成课程设计报告,基本算是后期工作,所以刚开始我们一起查资料讨论方案。在设计电路初期,由于我们没有设计经验,通过查阅一些资料,我们的设计渐渐有了头绪,基本确立设计方案和流程图。就是LED显示屏驱动电路的设计是个比较头疼的问题,接线非常复杂, 焊电路板就会比较麻烦。后来实验室提供LCD液晶显示屏,就好办了许多,解决了这个问题。我们很快确定了电路以及需要的器件,然后就是编程和仿真,开始时也遇到了很多的问题,经过静下心来思考,和同学讨论,理清了思路,慢慢修改,终于仿真成功了。

布线时,对电路的设计、布局要先有一个好的构思,才显得电路板美观、大方,在张辛超同学的努力下,做得还挺工整。电路板焊好后,检查了没有错误,将程序考入单片机后开始测试,刚开始时LCD显示器无数据显示,经过对电路板各模块的重新测试,发现并无问题,向别的同学请教,发现LCD的VEE管脚接高电平时,因对比度低,导致LCD无数据显示;而当VEE接低电平时,因对比度高,LCD可以清晰显示。

通过这次设计,我学到了很多知识,将学习的理论知识通过实验融会贯通,让我对它的理解更加深刻。由于这次课程设计不仅设计编程方面的知识,还涉及了其它学科的知识,例如PROTEUS等的基本知识。总之,通过这次课程设计,不仅加深了我对单片机理论方面的理解,将理论更好的运用的实践方面,而且锻炼了我们各方面的能力,培养了坚强的毅力和做事的耐心和细心,同时也认识到在团队工作中需要有合作精神,我想这会为今后自己踏上工作岗位、更好地融入新的团队打下良好的基础。

附录:(程序)

; 定义计时单元地址

    MIN    EQU  31H          ;存放分钟变量

    SEC    EQU  32H          ;存放秒钟变量

    DEDA   EQU  33H          ;存放10ms计数值    

; 按键端口状况值

    K1_N   EQU  34H          ;存放按键当前端口状况值

    K1_P   EQU  35H          ;存放按键上次端口状况值

    K1_C   EQU  37H          ;存放按键计数单元     

    X      EQU  36H          ;LCD 地址变量                

; 按键引脚定义

    K1     EQU  P3.3         ;按键1引脚定义

    K2     EQU  P3.4         ;按键2引脚定义

;LCD 引脚定义

    RS     EQU  P3.5         ;LCD RS引脚定义

    RW     EQU  P3.6         ;LCD RW引脚定义

    E      EQU  P3.7         ;LCD RS引脚定义        

   ORG   0000H               ;程序由地址0开始执行

   JMP   MAIN

   ORG   0BH                 ;定时器0中断地址设置

   JMP   T0_INT

 ;————————————— 主程序 ——————————————

  MAIN:                      ;开始

    MOV   SP,#60H            ;堆栈指针指向60H  

    CLR   E                  ;E=0,禁止读/写LCD

    ACALL SET_LCD            ;调LCD控制子程序

    ACALL INIT               ;初始化变量

    MOV   K1_P,#01H          ;按键上次端口设置1

    ACALL INIT_TIMER         ;调用初始化定时器

    ACALL MEU                ;调用工作菜单子程序

  LOOP:ACALL  CONV           ;时间计数处理

    ACALL LOOP1              ;调用清零键子程序

    ACALL KEY                ;判断是否有键按下

    JZ    LOOP               ;无键按下转LOOP

    MOV   K1_P,K1_N          ;交换数据

    ACALL KEY0               ;调用按键功能子程序

    JMP   LOOP               ;跳LOOP处循环         

; 初始变量清零子程序

  INIT:                     ;初始变量清零

    CLR  A                  ;A清为零

    MOV  K1_C,A             ;K1_C 初始为0

    MOV  DEDA,A             ;百分秒DEDA初始为0

    MOV  SEC,A              ;秒SEC初始为0

    MOV  MIN,A              ;分MIN初始为0

   

    MOV  K1_N,A             ;K1_N初始为0

    MOV  K1_P,A             ;K1_P初始为0

    CLR  TR0                ;启动中断

    RET                                       

 ;—————————————————————

 ;定时器初始化设置子程序

   INIT_TIMER:             ;定时器初始化

    MOV TMOD,#00000001B    ;定时器0模式1

    MOV IE,  #10000010B    ;开通中断

    MOV TL0,#LOW(65536-10000);定时初值装入低位

    MOV TH0,#HIGH(65536-10000);定时初值装入高位

    RET                                       

;中断服务程序

   T0_INT:                   ;定时器T0中断程序

    PUSH  ACC                ;入栈保护

    MOV TL0,#LOW(65536-10000) ;重加载

    MOV TH0,#HIGH(65536-10000)

    INC  DEDA

    MOV  A,DEDA              ;10ms 计数值加1

    CJNE  A,#100,TT

    MOV  DEDA,#0

    INC  SEC                 ;秒加1

    MOV  A,SEC

    CJNE  A,#60,TT

    INC  MIN                 ;分加1

    MOV  SEC,#0

    MOV  A,MIN

    CJNE  A,#05,TT

    MOV  DEDA,#0             ;百、分、秒单元清0

    MOV  SEC,#0            

    MOV  MIN,#0

  TT: POP  ACC               ;出栈

    RETI                     ;中断程序返回      

 ;—————————————————————

 ;判断键是否按下子程序

LOOP1:

 JB  K2,LOOP2             ;判清零键是否按下

     

       JMP  MAIN            ;跳转主程序处

  LOOP2: RET                                   

; 判断K1键是否按下

  KEY:   

     CLR  A                ;A清零

     MOV  K1_N,A           ;A值送入K1_N

     MOV  C,K1             ;K1值送入C

     RLC  A                ;同进位标志左移一位

     ORL  K1_N,A           ;两个位作逻辑OR运算

     MOV  A,K1_N           ;K1_N值送入A

     XRL  A,K1_P           ;有键按下,A 中内容不为零

     RET               

;功能键子程序

 ;K1键第一次按功能子程序

  KEY0:              

     MOV  A, K1_P          ;K1_P值送入A

     JB   ACC.0,KEY3       ;A的0位是1,转KEY3

     INC  K1_C             ;K1_C加1

     MOV  A, K1_C          ;K1_C值送入A

     CJNE A,#01H,KEY1      ;K1键是否第一次按?

     MOV  DPTR,#MENU1      ;是,存入MENU1信息

     MOV  A,#1             ;设置第一行显示

     CALL LCD_PRINT        ;调用显示字符子程序

     SETB TR0              ;启动中断

     RET                                

;K1键第二次按功能子程序

  KEY1:       

     MOV   A,K1_C           ;K1_C值送入A

     CJNE  A,#02H,KEY2      ;K1键是否第二次按?

     MOV   DPTR,#MENU2      ;是,存入MENU2信息

     MOV   A,#1             ;设置第一行显示

     CALL  LCD_PRINT        ;调用显示字符子程序

     CLR   TR0              ;停止中断

     RET                    ;           

  ;K1键第三次按功能子程序

KEY2:              

     MOV   A, K1_C          ;K1_C值送入A

     CJNE  A, #03H,KEY3     ;K1键是否第三次按?

     MOV   DPTR,#MENU3      ;是,存入MENU3信息

     MOV   A, #1            ;设置第一行显示

     CALL  LCD_PRINT        ;调用显示字符子程序

     SETB  TR0              ;启动中断

     RET                                     

;K1键第四按功能子程序

KEY3:                  

   MOV   A,K1_C           ;K1_C值送入A

     CJNE  A,#04H,KEY4      ;K1键是否第四次按?

     MOV   DPTR,#MENU4      ;是,存入MENU4信息

     MOV   A,#1             ;设置第一行显示

     CALL  LCD_PRINT        ;调用显示字符子程序

     CLR   TR0              ;启动中断

  KEY4:   

     RET                    ;子程序返回  

;————————————— LCD显示 ——————————————

 ; LCD控制子程序

  SET_LCD:            ;    

       CLR  E

       ACALL INIT_LCD      ;初始化 LCD

       MOV   R5,#10

       ACALL DELAY

       MOV   DPTR,#LMESS1  ;指针指到显示消息1

       MOV   A,#1          ;显示在第一行

       ACALL LCD_PRINT     ;调用显示字符子程序

       MOV   DPTR,#LMESS2  ;指针指到显示消息2

       MOV   A,#2          ;显示在第二行

       ACALL LCD_PRINT     ;调用显示字符子程序

       RET                                    

  LMESS1:  DB  "         ",0  ;LCD 第一行显示消息

  LMESS2:  DB  "TIME     ",0  ;LCD 第二行显示消息

 ;LCD初始化子程序

  INIT_LCD:   

     MOV   A,#38H          ;设置8位、2行、5x7点阵 

     ACALL WR_COMM         ; 调用写指令子程序

     ACALL DELAY1          ;调用延时子程序

     MOV   A,#0CH          ;开显示,光标不闪烁

     ACALL WR_COMM         ;调用写指令子程序      ;

     ACALL DELAY1          ;调用延时子程序

     MOV   A,#01H          ;清除 LCD 显示屏

     ACALL WR_COMM         ;调用写指令子程序    ;

     ACALL DELAY1          ;调用延时子程序

     RET                                  

;写指令子程序  

  WR_COMM:                        

      MOV  P1,A          

      CLR  RS              ;RS=0,选择指令寄存器

      CLR  RW              ;RW=0,选择写模式

      SETB E               ;E=1,允许读/写LCM

      ACALL DELAY1         ;调用延时子程序   

      CLR  E               ;E=0,禁止读/写LCM

      RET                                      

 ;写数据子程序

  WR_DATA:                

       MOV   P1,A    

       SETB  RS            ;RS=1,选择数据寄存器

       CLR   RW            ;RW=0,选择写模式

       SETB  E             ;E=1,允许读/写LCD

       ACALL DE            ;调用延时子程序

       CLR   E             ;E=0,禁止读/写LCD

       ACALL DE            ;调用延时子程序

       RET                                               

  ;清除该行 LCD 的字符

 CLR_LINE:       MOV  R0,#24

   CL1: MOV  A,#' '

     ACALL  WR_DATA

     DJNZ   R0,CL1

     RET                                    

;LCD 存入工作菜单

  MEU:                  

    MOV  DPTR,#MENU0        ;存入工作菜单

    MOV  A,#1               ;第一行

CALL LCD_PRINT

    RET

; 工作菜单

   MENU0:   DB  " SECOND-CLOCK 0 ",0

   MENU1:   DB  " BEGIN COUNT  1 ",0

   MENU2:   DB  " PAUST COUNT  2 ",0

   MENU3:   DB  " BEGIN COUNT  3 ",0

   MENU4:   DB  " PAUST COUNT  4 ",0            

;菜单显示子程序

 ;一行、二行显示字符

  LCD_PRINT: 

     CJNE  A,#1,LINE2       ;判断是否为第一行

  LINE1:

     ACALL  CLR_LINE        ;清除该行字符数据

     MOV    A, #80H         ;设置 LCD 的第一行地址

     ACALL  WR_COMM         ;写入命令

     JMP    FILL

  LINE2:

     ACALL  CLR_LINE        ;清除该行字符数据

     MOV    A,#0C0H         ;设置 LCD 的第二行地址

     ACALL  WR_COMM

  FILL: CLR A               ;填入字符

     MOVC   A,@A+DPTR       ;由消息区取出字符

     CJNE   A,#0,LC1        ;判断是否为结束码

     RET                                         

  ;写入数据

  LC1: ACALL WR_DATA     

     INC   DPTR             ;指针加1

     JMP   FILL             ;继续填入字符

     RET                                    

;转换数据子程 

  CONV:        ;转换为 ASCII 码并显示

     MOV  X,#5              ;设置位置

     ACALL  SKOW_LINE2      ;显示数据

     INC  X                 ;

     MOV  A,#':'            ;

     MOV  B,X               ;

     ACALL  LCDP2           ;

     MOV  A,MIN             ;加载分钟数据

     INC  X                 ;设置位置

     ACALL  SKOW_LINE2      ;显示数据

     INC  X                 ;

     MOV  A,#':'            ;

     MOV  B,X               ;

     ACALL  LCDP2           ;

     MOV  A,SEC             ;加载秒数数据

     INC  X                 ;设置位置

     ACALL  SKOW_LINE2      ;显示数据

     INC  X                 ;

     MOV  A,#':'            ;

     MOV  B,X               ;

     CALL  LCDP2            ;

     MOV  A,DEDA            ;加载秒数数据

     INC  X                 ;设置位置

     ACALL  SKOW_LINE2      ;显示数据

     RET                   ;              

;在 LCD 的第二行显示数字 

  SKOW_LINE2:    

      MOV  B,#10           ;设置被除数

      DIV  AB              ;结果A存商数,B存余数

      ADD  A,#30H          ;A为十位数,转换为字符

      PUSH B               ;B放入堆栈暂存

      MOV  B,X             ;设置 LCD 显示的位置

      ACALL LCDP2          ;由 LCD 显示出来

      POP  B               ;出栈

      MOV  A,B             ;B为个位数

      ADD  A,#30H          ;转换为字符

      INC  X               ;LCD 显示位置加1

      MOV  B,X             ;设置 LCD 显示的位置

      ACALL  LCDP2         ;由 LCD 显示出来    

      RET                                     

;在LCD的第二行显示字符

  LCDP2:     

      PUSH ACC              ;

      MOV  A,B              ;设置显示地址

      ADD  A,#0C0H          ;设置LCD的第二行地址

      CALL WR_COMM          ;写入命令

      POP  ACC              ;由堆栈取出A

      CALL WR_DATA          ;写入数据          

      RET                                     

;延时10MS

DELAY:                       

   MOV  R6,#50

     D1:MOV  R7,#100

     DJNZ  R7,$

     DJNZ  R6,D1

     DJNZ  R5,DELAY

     RET                                  

;延时5MS子程序

  DELAY1:              

     MOV  R6,#25

  DEY: MOV R7,#100

     DJNZ  R7,$

     DJNZ  R6,DEY

     RET                                     

  ;延时500微秒

  DE:                       

    DJNZ  R7,$

    RET                              

    END                     ;程序结束

Proteus电路图

相关推荐