目录
摘要:本文介绍了一款多功能数字时钟系统的软件设计。该系统能够显示当前日期、时间,并且具有日期、时间设置等功能。该系统采用51系列STC公司生产的STC89C51单片机,以及利用LED点阵显示器F3.0来显示数字时钟的结果。实时日历和时钟显示的设计过程在硬件与软件方面进行同步设计。硬件部分主要由AT89C52单片机,LED显示电路,以及调时按键电路等组成,系统通过LED显示数据,所以具有人性化的操作和直观的显示效果。软件方面主要包括时钟程序、键盘程序,显示程序等。本系统以单片机的汇编语言进行软件设计,为了便于扩展和更改,软件的设计采用模块化结构,使程序设计的逻辑关系更加简洁明了,以便更简单地实现调整时间及日期显示功能。所有程序编写完成后,在keil软件中进行调试,确定没有问题后,在Proteus软件中嵌入单片机内进行仿真。
1.绪论
1.1课题意义
LED显示屏可以显示变化的数字、文字、图形图像;不仅可以用于室内环境还可以用于室外环境,具有投影仪、电视墙、液晶显示屏无法比拟的优点。LED之所以受到广泛重视而得到迅速发展,是与它本身所具有的优点分不开的。这些优点概括起来是:亮度高、工作电压低、功耗小、小型化、寿命长、耐冲击和性能稳定。LED的发展前景极为广阔,目前正朝着更高亮度、更高耐气候性、更高的发光密度、更高的发光均匀性,可靠性、全色化方向发展。
1.2课题目的
通过课程设计,进一步熟悉和掌握AT89C51单片机的结构及工作原理,掌握以单片机核心的电路设计的基本方法和技术,了解表关电路参数的计算方法。通过完成一个包括电路设计和程序开发的完整过程,进一步了解开发一单片机应用系统的全过程,通过此综合训练,为以后毕业设计打下一定的基础。
(1)利用74HC595扩展单片机IO口间接控制LED点阵使其显示。
(2)综合运用所学的《单片机原理与应用》理论知识,通过实践加强对所学知识的理解,具备设计单片机应用系统的能力,加深对单片机课程的全面认识。
(3)通过本次课程设计能够对程序进行编写和调试。
(4)通过本次系统设计,增强自己的动手能力。认识单片机在日常生活中的应用的广泛性,实用性。
1.3 数字时钟的应用及发展前景
数字时钟具有走时准确,一钟多用等特点,在生活中已经得到广泛的应用。虽然现在市场上已有现成的电子钟集成电路芯片出售,价格便宜、使用也方便,但是人们对电子产品的应用要求越来越高,数字钟不但可以显示当前的时间,而且可以显示日期、农历、以及星期等,给人们的生活带来了方便。另外数字钟还具备秒表和闹钟的功能,且闹钟铃声可自选,使一款电子钟具备了多媒体的色彩[3]。
数字时钟[4]是采用单片机原理实现对年、月、日、周、时、分、秒,数字显示及到时提醒的计时装置,广泛用于个人家庭,车站, 码头办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表, 钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。诸如定时自动报警、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等,所有这些,都是以钟表数字化为基础的,所以数字时钟有很大的发展前景。
1.4 课题的研究内容及技术要求
1.4.1 本课题的研究内容
本课题只涉及系统的软件部分。具体来说,本设计所研究的主要内容是根据所学的单片机及多种芯片的有关知识,实现数字时钟的功能。设计出一个可以显示出当前日期、时间的数字时钟系统,同时该系统必须具有日期调整和时间调整等功能。
1.4.2 本课题的主要任务
1.4.2.1 功能要求
采用STC89C52单片机和LED点阵显示能显示当前的月、日、时、分、秒,24小时制;月、日、时、分、秒均可以单独设置,设置时该项目闪烁;外接3个按键,一个用于选择需要设置的项目,一个增加、一个减少。
1.4.2.2 主要技术指标
计时精度误差:≤1秒/日。LED显示清晰,不能有明显的残影、乱码。
电源:DC5V、2A。
1.4.2.3 工艺要求
印刷电路板布局合理、走线清晰整洁。IC装在插座上,发热元、器件应考虑散热的方法。在印制板上应留出定位孔及固定支架所占用的位置。焊点大小适中、呈锥状、美观、结实、光亮、无虚焊;跳线整齐美观。程序采用C51语言编写,适当注释,具备良好的编程风格。在PCB版上应明显标识作者姓名。
2 设计要求与方案论证
2.1 设计基本要求
本设计只涉及“基于51单片机的数字时钟系统软件设计”的软件部分,所用的单片机是容易理解和掌握的MCS-51系列单片机中的STC89C52。需要设计出一款实用而且功能较全面的数字时钟。本设计所研究的主要内容是根据所学的单片机知识,利用C51语言编程,再结合数字时钟系统的硬件[5]部分,设计出一个可以显示出当前日期、时间等的数字时钟系统,同时该系统必须具有日期调整和时间调整等功能。
2.2 编程语言方案论证
2.2.1 汇编语言
汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址。在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令。普遍地说,特定的汇编语言和特定的机器语言指令集是一一对应的不同平台之间不可直接移植。
许多汇编程序为程序开发、汇编控制、辅助调试提供了额外的支持机制。有的汇编语言编程工具经常会提供宏,它们也被称为宏汇编器。
汇编语言不像其他大多数的程序设计语言一样被广泛用于程序设计。在今天的实际应用中,它通常被应用在底层,硬件操作和高要求的程序优化的场合。驱动程序、嵌入式操作系统和实时运行程序都需要汇编语言。
2.2.2主要特点
1.面向机器的低级语言,通常是为特定的计算机或系列计算机专门设计的。
2.保持了机器语言的优点,具有直接和简捷的特点。
3.可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端口等。
4.目标代码简短,占用内存少,执行速度快,是高效的程序设计语言。
5.经常与高级语言配合使用,应用十分广泛。
2.2.3简捷性
汇编语言由于采用了助记符号来编写程序,比用机器语言的二进制代码编程要方便些,在一定程度上简化了编程过程。汇编语言的特点是用符号代替了机器指令代码,而且助记符与指令代码一一对应,基本保留了机器语言的灵活性。使用汇编语言能面向机器并较好地发挥机器的特性,得到质量较高的程序。
2.2.4执行过程
用汇编语言编制的程序输入计算机,计算机不能象用机器语言编写的程序一样直接识别和执行,必须通过预先放入计算机的"汇编程序"中进行加工和翻译,才能变成能够被计算机直接识别和处理的二进制代码程序。用汇编语言等非机器语言书写好的符号程序称为源程序,运行时汇编程序要将源程序翻译成目标程序。目标程序是机器语言程序,当它被安置在内存的预定位置上,就能被计算机的CPU处理和执行。
2.2.5独特性
汇编语言是面向具体机型的,它离不开具体计算机的指令系统,因此,对于不同型号的计算机,有着不同的结构的汇编语言,而且,对于同一问题所编制的汇编语言程序在不同种类的计算机间是互不相通的。
2.2.6优点
1.面向机器的低级语言,通常是为特定的计算机或系列计算机汇编语言专门设计的。
2.保持了机器语言的优点,具有直接和简捷的特点。
3.可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端口等。
4.目标代码简短,占用内存少,执行速度快,是高效的程序设计语言。
5.经常与高级语言配合使用,应用十分广泛。
2.2.7缺点
同时还应该认识到,汇编语言是一种层次非常低的语言,它仅仅高于直接手工编写二进制的机器指令码,因此不可避免地存在一些缺点:汇编语言
(1)编写的代码非常难懂,不好维护;
(2)很容易产生bug,难于调试;
(3)只能针对特定的体系结构和处理器进行优化;
(4)开发效率很低,时间长且单调。
2.2.2 C51语言
2.2.2.1 C51语言[12]与标准C语言概述
单片机C51语言是由C语言继承而来的。C51语言能直接对单片机硬件进行操作。C51语言具有C语言结构清晰的优点,便于学习,同时具有汇编语言的硬件操作能力。C语言[8]是Combined Language(组合语言)的中英混合简称。是一种计算机程序设计语言。它既具有高级语言的特点,又具有汇编语言的特点。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序。和C语言不同的是,C51语言运行于单片机C51实验板、单片机平台,而C语言则运行于普通的桌面平台。
2.2.2.2 C51语言的特点
1、单片机C51语言兼备高级语言与低级语言的优点。语法结构和标准C语言基本一致,语言简洁,便于学习。运行于单片机平台,支持的微处理器种类繁多,可移植性好。对于兼容的8051系列单片机,只要将一个硬件型号下的程序稍加修改,甚至不加改变,就可移植到另一个不同型号的单片机中运行。具有高级语言的特点,尽量减少底层硬件寄存器的操作。
2、单片机C51语言提供了完备的数据类型、运算符及函数供使用。C51语言是一种结构化程序设计语言,可以使用一对花括号"{}"将一系列语句组合成一个复合语句,程序结构清晰明了。C51语言代码执行的效率方面十分接近汇编语言,且比汇编语言的程序易于理解,便于代码共享。
2.2.2.3 C51语言与C语言的主要区别
1、库函数的不同。由于标准C语言库函数中的部分库函数不适合嵌入式控制器系统,因此他们被排除在keilC51语言之外。有一些库函数可以继续使用,但是这些库函数必须针对51单片机的特点来做出相应的开发。
2、数据类型有一定的区别。在C51语言中增加了几种针对51单片机特有的
数据类型,在标准C语言的基础上优扩展了种类型。
3、C51语言的变量存储模式与标准C语言中的变量存储模式数据不一样。标准C语言最初是为通用计算机设计的,在通用计算机中只有一个程序和数据统一寻址的内存空间,而C51语言中变量的存储模式与51单片机的存储器紧密相关。
4、数据存储类型的不同。51单片机存储区可分为内部存储区、外部数据存储区以及程序存储区。内部数据存储区可分为3个不同的C51存储类型:data、idata和bdata。外部数据存储区分为2个不同的C51存储类型:xdata和pdata。程序存储区只能读不能写,可能在51单片机外部或者内部。C51语言提供了code存储类型来访问程序存储区。
5、标准C语言没有处理单片机中断的定义,而C51语言中有专门的中断函数。
6、C51语言与标准C语言的输入输出处理不一样。C51语言中的输入输出是通过51单片机的串口进行的,输入输出指令执行前必须对串口进行初始化。
7、头文件不同。C51语言与标准C语言头文件的差异是C51语言头文件必须把51单片机内部的外设硬件资源(如定时器、中断、I/O等)相应的功能寄存器的写入到头文件内。
8、程序结构的差异。由于51单片机的硬件资源有限,他的编译系统不允许太多的程序嵌套。其次,标准C语言所具备的递归特性不被C51语言支持。
通过以上三种语言的比较,可以看出,C51语言要优于汇编语言,编写时连贯性好,容易理解,而且在修改过程中可以很快发现问题所在,修改简便。本次设计选用C51语言作为编程语言。
2.3设计方案分析
2.3.1 利用8*8点阵型LED显示器显示结果
其的主要特点如下:
1、能在低电压、小电流条件下驱动发光,能与CMOS、ITL电路兼容。
2、发光响应时间极短(<0.1µs),高频特性好,单色性好,亮度高。
3、体积小,重量轻,抗冲击性能好。
4、寿命长,使用寿命在10万小时以上,甚至可达100万小时,成本低。
2.3.2利用数码管显示器显示结果
(1)静态显示。静态显示,即当显示器显示某一字符时,相应的发光二极管恒定导通或截止。该方式每一位都需要一个8 位输出口控制。静态显示时较小电流能获得较高的亮度,且字符不闪烁。但因当所需显示的位数较多时,静态显示所需的I/O口数较大,造成资源的浪费。
(2)动态显示。动态显示,即各位数码管轮流点亮,对于显示器各位数码管,每隔一段延时时间循环点亮一次。利用人的视觉暂留功能可以看到整个显示,但须保证扫描速度足够快,人的视觉暂留功能才可察觉不到字符闪烁。显示器的亮度与导通电流、点亮时间及间隔时间的比例有关。调整参数可以实现较高稳定度的显示。动态显示节省了I/O口,降低了能耗。但是要采用多个数码管,故对比之下本次设计选用8*8点阵型LED显示器作为显示器件。
2.4 系统仿真方式方案论证
2.4.1利用Proteus软件仿真实现
Proteus软件是英国Labcenter electronics公司出版的EDA工具软件。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前最好的仿真单片机及外围器件的工具。虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的科技工作者的青睐。Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。迄今为止是世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年即将增加Cortex和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MATLAB等多种编译.
2.4.2特点
Proteus软件具有其它EDA工具软件(例:multisim)的功能。这些功能是:
(1)原理布图
(2)PCB自动或人工布线
(3)SPICE电路仿真
2.4.3 手工焊接电路板
焊接是一门科学,他的原理是通过加热的烙铁将固态焊锡丝加热熔化,再借助于助焊剂的作用,使其流入被焊金属之间,待冷却后形成牢固可靠的焊接点。
当焊料为锡铅合金焊接面为铜时,焊料先对焊接表面产生润湿,伴随着润湿现象的发生,焊料逐渐向金属铜扩散,在焊料与金属铜的接触面形成附着层,使两则牢固的结合起来。所以焊锡是通过润湿、扩散和冶金结合这三个物理,化学过程来完成的[11]。
经过对Proteus软件仿真和手工焊接的对比,Proteus软件仿真在应用范围上比较广泛,实现的功能也很强大。因此,本次设计先利用Proteus进行模拟,之后再手工焊接。
3.硬件电路设计
3.1 单片机STC89C51的工作原理
3.1.1 单片机主要性能参数及引脚功能
9C52是INTEL公司MCS-51系列单片机中基本的产品,它采用ATMEL公司可靠的CMOS工艺技术制造的高性能8位单片机,属于标准的MCS-51的HCMOS产品。它结合了CMOS的高速和高密度技术及CMOS的低功耗特征,它基于标准的MCS-51单片机体系结构和指令系统,属于89C51增强型单片机版本,集成了时钟输出和向上或向下计数器等更多的功能,适合于类似马达控制等应用场合。89C52内置8位*处理单元、512字节内部数据存储器RAM、8k片内程序存储器(ROM)32个双向输入/输出(I/O)口、3个16位定时/计数器和5个两级中断结构,一个全双工串行通信口,片内时钟振荡电路。此外,89C52还可工作于低功耗模式,可通过两种软件选择空闲和掉电模式。在空闲模式下冻结CPU而RAM定时器、串行口和中断系统维持其功能。掉电模式下,保存RAM数据,时钟振荡停止,同时停止芯片内其它功能。89C52有PDIP(40pin)和PLCC(44pin)两种封装形式。
3.1.1.1 STC89C51单片机的主要性能参数[8]有:
(1)与MCS-51产品指令和引脚完全兼容;
(2)4K字节可编程闪烁存储器;
(3)1000次擦写循环;
(4)全静态操作:0Hz—24MHz;
(5)三级加密程序存储器;
(6)128×8字节内部RAM;
(7)32个可编程I/O口线;
(8)2个16位定时/计数器;
(9)5个中断源;
(10)可编程串行通道;
(11)低功耗闲置和掉电模式;
(12)数据保留10年。
3.1.1.2功能特性
· 标准MCS-51内核和指令系统 |
· 片内8kROM(可扩充64kB外部存储器) |
· 32个双向I/O口 |
· 256x8bit内部RAM(可扩充64kB外部存储器) |
· 3个16位可编程定时/计数器 |
· 时钟频率3.5-12/24/33MHz |
· 向上或向下定时计数器 |
· 改进型快速编程脉冲算法 |
· 6个中断源 |
· 5.0V工作电压 |
· 全双工串行通信口 |
· 布尔处理器 |
-帧错误侦测 |
· 4层优先级中断结构 |
-自动地址识别 |
· 兼容TTL和CMOS逻辑电平 |
· 空闲和掉电节省模式 |
· PDIP(40)和PLCC(44)封装形式 |
3.1.1.3管脚说明
VCC:供电电压。 GND:接地。
P0:P0口为一个8位漏级开路双向I/O口,每脚可吸收8个TTL门电流。当P0口的管脚第一次写"1"时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FLASH编程时,P0 口作为原码输入口,当FLASH进行校验时,P0输出原码,此时P0外部必须被拉高。
P1:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4个TTL门电流。P1口管脚写入"1"后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为低八位地址接收。
P2:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写"1"时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址"1"时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。
P3:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入"1"后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。P3作为AT89C51的一些特殊功能口,管脚 备选功能
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 /INT0(外部中断0)
P3.3 /INT1(外部中断1)
P3.4 T0(计时器0外部输入)
P3.5 T1(计时器1外部输入)
P3.6 /WR(外部数据存储器写选通)
P3.7 /RD(外部数据存储器读选通)
RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。
ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的底位字节。
在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。
/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。
/EA / VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。
XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。
3.1.1.4振荡器
外接石英晶体或者陶瓷谐振器以及电容C1、C2接在放大器的反馈回路(AT89C52内部有一个用于构成内部振荡器的高增益反相放大电路,XTAL1、XTAL2分别是该放大器的输入和输出端)中构成并联振荡电路。
为了使装置能够被外部时钟信号激活,XATL1应该有效,而XTAL2应该被悬空。由于输入到内部的时钟信号电路通过了一个二分频的信号,外部信号的工作周期比没有别的要求,但是最大值和最小值的大小可以在数据表上观察出来。
当正常工作时,外部振荡器可以计算出XTAL1上的电容,最大可达到100pF。这是由于振荡器电容和反馈电容之间的相互作用。当外部信号是标准高电平或者低电平时,电容不会超过20pF.
3.1.1.5空置模式
用户的软件都可以调用空置模式。当单片机处于这种模式,耗能就会自然降低。特殊功能端和板子上的随机存储器在空置状态保持各自的电平。但是处理器阻止装置执行指令。空置模式会被激活如果端口处于复位状态或者中断系统有效。
3.1.2 单片机存储器结构及复位电路与时钟电路
MCS-51器件有单独的程序存储器和数据存储器。外部程序存储器和数据存储器都可以64K寻址。
程序存储器:如果EA引脚接地,程序读取只从外部存储器开始。对STC89C51,如果EA接VCC,程序读写先从内部存储器(地址为0000H~1FFFH)开始,接着从外部寻址,寻址地址为:2000H-FFFFH。
数据存储器:STC89C51 有256 字节片内数据存储器。高128字节与特殊功能寄存器重叠。也就是说高128字节与特殊功能寄存器有相同的地址,而物理上是分开的。当一条指令访问高于7FH的地址时,寻址方式决定CPU访问高128字节RAM还是特殊功能寄存器空间。直接寻址方式访问特殊功能寄存器(SFR)。因此,高128字节数据RAM也可用于堆栈空间。
复位是单片机的初始化操作,只要给RESET引脚加上两个机器周期以上的高电平信号,就可使STC89C51单片机复位。复位的主要功能是把程序计数器(PC)初始化为0000H,使单片机从0000H单元开始执行程序,同时复位操作还对一些寄存器有影响。STC89C51的复位是由外部的复位电路来实现的,复位电路分为上电复位和按键复位两种方式。其电路图2所示.
图 2 复位电路图
单片机的时钟频率直接影响单片机的速度,时钟电路的质量也直接影响单片机系统的稳定性。常见的时钟电路有两种方式,一种是内部时钟方式,另一种是外部时钟方式。本系统选用内部时钟方式,STC89C51内部有一个用于构成振荡器的高增益反相放大器,该高增益反相放大器的输入端为芯片引脚XTAL1,输出端为引脚XTAL2。这两个引脚跨接石英晶体振荡器和微调电容,就构成一个稳定的自激振荡器,STC89C51时钟电路如图3所
图3时钟电路
电路中的电容的取值通常在20pF~30pF之间,对外接电容的值没有严格的要求,但电容的大小会影响振荡器频率的高低、振荡器的稳定性和起振的快速性。由于单片机要进行串行通信,为了获得准确的波特率,选择晶振的频率为12MHz。
3.2相关芯片的工作原理
3.2.1 74LS373工作原理
74LS373是三态输出的八D锁存器,共有54S373和74LS373两种线路。373的输出端O0-O7 可直接与总线相连。O0-O7为输出端。极限值:电源电压7V,输入电压55.5V ,输出高阻态时高电平电压5.5V。引脚图见下图4所示。
当三态允许控制端OE 为低电平时,O0-O7 为正常逻辑状态,可用来驱动负载或总线。当OE 为高电平时,O0-O7 呈高阻态,即不驱动总线,也不为总线的负载,但锁存器内部的逻辑操作不受影响。
当锁存允许端LE 为高电平时,O 随数据D 而变。当LE 为低电平时,O 被锁存在已建立的数据电平。当LE 端施密特触发器的输入滞后作用,使交流和直流噪声抗扰度被改善400mV。引出端符号:D0-D7为数据输入端,OE为三态允许控制端(低电平有效)LE锁存允许端。真值表见表1所示。图4 引脚图
图4 引脚图
表1 真值表
Dn |
LE |
OE |
Qn |
H |
H |
L |
H |
L |
H |
L |
L |
X |
L |
L |
Q0 |
X |
X |
H |
高阻态 |
3.2.2 74LS245工作原理
74LS245还具有双向三态功能,既可以输出,也可以输入数据。[8]当8051单片机的P0口总线负载达到或超过P0最大负载能力时,必须接入74LS245等总线驱动器。片选端/CE低电平有效,当DIR="0"时,信号由 B 向 A 传输;(接收)DIR=1",信号由 A 向 B 传输;(发送)当CE为高电平时,A、B均为高阻态.由于P2口始终输出地址的高8位,接口时74LS245的三态控制端1G和2G接地,P2口与驱动器输入线对应相连。P0口与74LS245输入端相连,E端接地,保证数据线畅通。
5 74LS245引脚图
3.2.3 74LS138译码器的的工作原理
①当一个选通端(E1)为高电平,另两个选通端((/E2))和(/E3))为低电平时,可将地址端(A0、A1、A2)的二进制编码在Y0至Y7对应的输出端以低电平译出。(即输出为Y0至Y7的非)比如:A2A1A0=110时,则Y6输出端输出低电平信号。
②利用 E1、E2和E3可级联扩展成 24 线译码器;若外接一个反相器还可级联扩展成 32 线译码器。
③若将选通端中的一个作为数据输入端时,74LS138还可作数据分配器。
3.2.3.8引脚功能
图5引脚图
A0~A2:地址输入端
STA(E1):选通端
/STB(/E2)、/STC(/E3):选通端(低电平有效)
/Y0~/Y7:输出端(低电平有效)
VCC:电源正
GND:地
A0~A2对应Y0--Y7;A0,A1,A2以二进制形式输入,然后转换成十进制,对应相应Y的序号输出低电平,其他均为高电平;
真值表
输入 |
输出 |
||||||||||||
STA |
/STB |
/STC |
A2 |
A1 |
A0 |
/Y0 |
/Y1 |
/Y2 |
/Y3 |
/Y4 |
/Y5 |
/Y6 |
/Y7 |
× |
1 |
× |
× |
× |
× |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
× |
× |
1 |
× |
× |
× |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
× |
× |
× |
× |
× |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
0 |
3.2.3.9 74LS04工作原理
其电源电压7V,输入电压7V。1A-6A 输入端,1Y-6Y 输出端。引脚图见图6所示。
图6 引脚图
图6 引脚图
4.软件设计及程序分析
4.1 软件设计及结构框图
该系统采用了STC89S51单片机系统来控制系统的工作,[7]数字时钟设计包括以下几部分:显示模块、计时模块、按键模块。结构框图见图7所示。为了方便使用,我们把数据采集单独使用一个单片机系统,然后显示模块通过5个8*8点阵型LED显示出来。按键模块通过计数中断次数,赋值给key,根据key的值来选择1-5号点阵并进行加减调整。
该设计可以实现以下功能:
1、能正常显示时间、日期。
2、对错误的时间进行修改。
STC89C51 单片机显示模块按键模块计时模块
图7 结构框图
4.2 软件主程序设计
在主程序的中首先进行程序初始化,主程序流程图见图8所示。然后进行死循环,循环内调用显示程序。当有按键按下则转到相应的功能程序执行。若没有则继续执行显示函数。
begin 写入初值打开中断开始计时显示函数End
图8 主函数流程图
4.3软件子程序设计
4.3.1显示函数
显示函数依次调用秒、分、时、日、月的显示子函数。流程图见图9所示图
图9 显示函数流程图
4.3.1.1显示秒函数
P0口先为低电平,熄灭点阵,之后通过片选选择秒钟的点阵,通过循环,按照前面定义的全局变量数组,依次显示每个数字。每显示一个数字后都将P0口置低电平,以免鬼影的出现。流程图见图10所示。
显示秒函数DISPLAY_SECOND() 让P0置低电平,点阵不亮片选,选择秒的点阵n>8? 选择数组的编码,点亮该点阵P0置低电平, 点阵全灭进行138选择,确定行延时Y 退出n++ N
图10 显示秒函数流程图
4.3.1.2显示分函数
P0口先为低电平,熄灭点阵,之后通过片选选择分钟的点阵,通过循环,按照前面定义的全局变量数组,依次显示每个数字。每显示一个数字后都将P0口置低电平,以免鬼影的出现,流程图见图11所示。
图11 显示分函数流程图
4.3.1.3显示时函数
P0口先为低电平,熄灭点阵,之后通过片选选择小时的点阵,通过循环,按照前面定义的全局变量数组,依次显示每个数字。每显示一个数字后都将P0口置低电平,以免鬼影的出现,流程图见图12所示。
图12 显示时函数流程图
4.3.1.4显示日函数
P0口先为低电平,熄灭点阵,之后通过片选选择天的点阵,通过循环,按照前面定义的全局变量数组,依次显示每个数字。每显示一个数字后都将P0口置低电平,以免鬼影的出现,流程图见图13所示。
图13 显示天函数流程图
4.3.1.5显示月函数
P0口先为低电平,熄灭点阵,之后通过片选选择月份的点阵,通过循环,按照前面定义的全局变量数组,依次显示每个数字。每显示一个数字后都将P0口置低电平,以免鬼影的出现,流程图见图14所示。
图14 显示月函数流程图
5 Proteus仿真
5.1 Proteus仿真图
Proteus仿真
5.2Proteus仿真结果
Proteus仿真结果
5.3仿真结果分析
采用STC89C52单片机和LED点阵显示,能显示当前的月、日、时、分、秒,24小时制,月、日、时、分、秒均可以单独设置,设置时该项目闪烁,外接3个按键,一个用于选择需要设置的项目,一个增加、一个减少,并且计时精度误差:≤1秒/日
LED显示清晰,没有明显的残影和乱码;
6.实验
6.1实物图
6.3.运行结果分析
采用STC89C52单片机和LED点阵显示,能显示当前的月、日、时、分、秒,24小时制,月、日、时、分、秒均可以单独设置,设置时该项目闪烁,外接3个按键,一个用于选择需要设置的项目,一个增加、一个减少,并且计时精度误差:≤1秒/日
LED显示清晰,没有明显的残影和乱码;
7.总结:
课程设计是培养学生综合运用所学知识,发现实际问题、提出实际问题、分析和解决实际问题,锻炼实践能力的重要环节,是对学生实际学习能力、动手能力的具体训练和考察过程。在此次数字钟设计过程中, 在学习新知识的同时,把在课程中学到的理论知识运用到实际作品设计、操作中,更进一步地熟悉了单片机芯片的结构及掌握了其工作原理和具体的使用方法与相关元器件的参数计算方法、使用方法,了解了电路的开发和制作及课程设计报告的编写。加深了对相关理论知识及专业知识的掌握度,增强自身的动手能力,锻炼及提高了理解问题、分析问题、解决问题的能力,更深刻的体会到了理论联系实际的重要性。最后,我通过此次单片机课程设计不仅仅将我门一学期在单片机课程上的所学很好的应用到了实际设计中,更是将理论知识应用到了实践中,这才是真正的学习,不仅仅是读万卷书,更要行万里路,讲知识与实践有机的结合。也十分感谢老师为我们提供了这次单片机课程设计的机会,我们也通过此次课程设计,更清晰更实际的接触到了单片机。
致谢
这次的课程设计总结是在我的指导老师黎老师亲切关怀和悉心指导下完成的。从课程设计选题到设计完成,黎老师给予了我耐心指导与细心关怀,有了莫老师耐心指导与细心关怀我才不会在设计的过程中迷失方向,失去前进动力。黎老师有严肃的科学态度,严谨的治学精神和精益求精的工作作风,这些都是我所需要学习的,感谢黎老师给予了我这样一个学习机会,谢谢! 同时,我还要感谢与我并肩作战的舍友与同学们,感谢关心我支持我的朋友们,感谢学校领导、老师们,感谢你们给予我的帮忙与关怀;
参考文献
[1]蒋辉平,《单片机原理与应用设计》,北京,北京航空航天大学出版社,2007年
[2]李鸿等,《单片机原理及应用》,长沙,湖南大学出版社,2004年
[3]楼然苗,李光飞,《单片机课程设计指导》,北京,北京航空航天出版社,2007年
[4]Kenneth A.Reek,《C和指针》,北京,人民邮电出版社,2008年
[5] 谭浩强.C语言程序设计[M].清华大学出版社2010.
[6] 张毅刚.单片机原理及接口技术(C51编程)[M].人民邮电出版社2011.
[7] 豆丁网帮助中心[OL],http://www.docin.com/p-1610869051.html
[8] 360帮助中心 [OL],http://www.duanmeiwen.com/fanwen/zhuanti/37974.html
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
int second;
int minute;
int hour;
int day;
int month;
int time;
sbit P3_6=P3^6;//外部数据存储器写选通输出/加
sbit P3_7=P3^7;//外部数据存储器读选通输出/减
uchar key;
uchar code DATA_LED_SFM[60][8]=
{
{0xFF,0x99,0x99,0x99,0x99,0x99,0x99,0xFF},{0xFF,0x49,0x49,0x49,0x49,0x59,0x69,0x4F},//00,01
{0xFF,0x19,0x19,0x19,0xF9,0x89,0x89,0xFF},{0xFF,0x89,0x89,0x89,0xF9,0x89,0x89,0xFF},//02,03
{0x8F,0x89,0x89,0xF9,0x99,0x99,0x99,0x9F},{0xFF,0x89,0x89,0x89,0xF9,0x19,0x19,0xFF},//04,05
{0xFF,0x99,0x99,0x99,0xF9,0x19,0x19,0xFF},{0x8F,0x89,0x89,0x89,0x89,0x89,0x89,0xFF},//06,07
{0xFF,0x99,0x99,0x99,0xF9,0x99,0x99,0xFF},{0xFF,0x89,0x89,0XF9,0x99,0x99,0x99,0xFF},//08,09
{0xFF,0x94,0x94,0x94,0x94,0x99,0x96,0xFC},{0xFF,0x44,0x44,0x44,0x44,0x59,0x66,0x4C},//10,11
{0xFF,0x14,0x14,0x14,0xF4,0x84,0x85,0xF6},{0xFF,0x84,0x84,0x84,0xF4,0x89,0x86,0xFC},//12,13
{0x8F,0x84,0x84,0xF4,0x94,0x99,0x96,0x9C},{0xFF,0x84,0x84,0x84,0xF4,0x19,0x16,0xFC},//14,15
{0xFF,0x94,0x94,0x94,0xF4,0x19,0x16,0xFC},{0x8F,0x84,0x84,0x84,0x84,0x89,0x86,0xFC},//16,17
{0xFF,0x94,0x94,0x94,0xF4,0x99,0x96,0xFC},{0xFF,0x84,0x84,0xF4,0x94,0x99,0x96,0xFC},//18,19
{0xFF,0x91,0x91,0x91,0x9F,0x99,0x98,0xFF},{0xFF,0x41,0x41,0x41,0x4F,0x59,0x68,0x4F},//20,21
{0xFF,0x11,0x11,0x11,0xFF,0x88,0x88,0xFF},{0xFF,0x81,0x81,0x81,0xFF,0x88,0x88,0xFF},//22,23
{0x8F,0x81,0x81,0xF1,0x9F,0x98,0x98,0x9F},{0xFF,0x81,0x81,0x81,0xFF,0x18,0x18,0xFF},//24,25
{0xFF,0x91,0x91,0x91,0xFF,0x18,0x18,0xFF},{0x8F,0x81,0x81,0x81,0x8F,0x88,0x88,0xFF},//26,27
{0xFF,0x91,0x91,0x91,0xFF,0x98,0x98,0xFF},{0xFF,0x81,0x81,0xF1,0x9F,0x98,0x98,0xFF},//28,29
{0xFF,0x98,0x98,0x98,0x9F,0x98,0x98,0xFF},{0xFF,0x48,0x48,0x48,0x4F,0x58,0x68,0x6F},//30,31
{0xFF,0x18,0x18,0x18,0xFF,0x88,0x88,0xFF},{0xFF,0x88,0x88,0x88,0xFF,0x88,0x88,0xFF},//32,33
{0x8F,0x88,0x88,0xf8,0x9F,0x98,0x98,0x9F},{0xFF,0x88,0x88,0x88,0xFF,0x18,0x18,0xFF},//34,35
{0xFF,0x98,0x98,0x98,0xFF,0x18,0x18,0xFF},{0x8F,0x88,0x88,0x88,0x8F,0x88,0x88,0xFF},//36,37
{0xFF,0x98,0x98,0x98,0xFF,0x98,0x98,0xFF},{0xFF,0x88,0x88,0xF8,0x9F,0x98,0x98,0xFF},//38,39
{0xF8,0x98,0x98,0x9F,0x99,0x99,0x99,0xF9},{0xFF,0x48,0x48,0x4F,0x49,0x59,0x69,0x49},//40,41
{0xF8,0x18,0x18,0x1F,0xf9,0x89,0x89,0xF9},{0xF8,0x88,0x88,0x8F,0xF9,0x89,0x89,0xF9},//42,43
{0x88,0x88,0x88,0xFF,0x99,0x99,0x99,0x99},{0xF8,0x88,0x88,0x8F,0xF9,0x19,0x19,0xF9},//44,45
{0xF8,0x98,0x98,0x9F,0xF9,0x19,0x19,0xF9},{0x88,0x88,0x88,0x8F,0x89,0x89,0x89,0xF9},//46,47
{0xF8,0x98,0x98,0x9F,0xF9,0x99,0x99,0xF9},{0xF8,0x88,0x88,0xFF,0x99,0x99,0x99,0xF9},//48,49
{0xFF,0x98,0x98,0x98,0x9F,0x91,0x91,0xFF},{0xFF,0x48,0x48,0x48,0x4F,0x51,0x61,0x4F},//50,51
{0xFF,0x18,0x18,0x18,0xFF,0x81,0x81,0xFF},{0xFF,0x88,0x88,0x88,0xFF,0x81,0x81,0xFF},//52,53
{0x8F,0x88,0x88,0xF8,0x9F,0x91,0x91,0x9F},{0xFF,0x88,0x88,0x88,0xFF,0x11,0x11,0xFF},//54,55
{0xFF,0x98,0x98,0x98,0xFF,0x11,0x11,0xFF},{0x8F,0x88,0x88,0x88,0x8F,0x81,0x81,0xFF},//56,57
{0xFF,0x98,0x98,0x98,0xFF,0x91,0x91,0xFF},{0xFF,0x88,0x88,0xF8,0x9F,0x91,0x91,0xFF},//58,59
};//60
/*时分秒的点阵*/
uchar DATA_138[8]={0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00};
void DISPLAY_SECOND();//显示秒
void DISPLAY_MINUTE();//显示分钟
void DISPLAY_HOUR();//显示小时
void DISPLAY_DAY();//显示日期
void DISPLAY_MONTH();//显示月份
void DELAY();//延时函数
//void DELAY1();//延时函数
void DISPLAY();//显示所有信息
void main()
{
TMOD=0x51;//T1=0101工作方式1下的计数器,T0=0001工作方式1下的定时器。
TH0=(65536-50000)/256;//向TH0写入初值高八位,定时50毫秒
TL0=(65536-50000)%256;//向TL0写入初值低八位
TH1=0;//T1的特殊功能寄存器
TL1=0;//T1的特殊功能寄存器
EA=1;
IT0=1; //跳沿触发方式
EX0=1;
ET0=1;
TR0=1;//启动定时器/计数器工作
TR1=1;//启动定时器/计数器工作
while(1)
{DISPLAY();}
}
/********************************************************
*函数名称:DELAY
*功能描述:延时函数
*传递参数:
*********************************************************/
void DELAY(uchar t)
{
int i;
for(t;t>0;t--)
for(i=0;i<60;i++);
}
/*函数名称:DELAY1
功能描述:延时函数
传递参数:
*********************************************************/
{
uchar i;
while(t--)
{for(i=0;i<200;i++);}
}
/********************************************************
*函数名称:T0_isr
*功能描述:计时函数
*传递参数:
*********************************************************/
void T0_isr()interrupt 1
{
ET0=0;//关闭定时器/计数器T0的溢出中断允许位
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
time++;
if(time==20)
{time=0;second++;}
if(second==60)
{second=0;minute++;}
if(minute==60)
{minute=0;hour++;}
if(hour==24)
{hour=0;day++;}
if(day==31)
{day=0;month++;}
if(month==13)
{month=0;}
ET0=1;//打开定时器/计数器T0的溢出中断允许位
}
/********************************************************
*函数名称:T1key_isr
*功能描述:按键函数(T1为计数器)
*传递参数:
*********************************************************/
void T1key_isr()interrupt 0
{
EX0=0;//禁止外部中断0中断
key=TL1;
if(key==1)//选中秒的点阵
{if(P3_6==0)//加
{
second++;
if(second>59)
second=0;
}
if(P3_7==0)//减
{
second--;
if(second<0)
second=59;
}
}
else if(key==2)//选中分的点阵
{
if(P3_6==0)//加
{
minute++;
if(minute>59)
minute=0;
}
if(P3_7==0)//减
{
minute--;
if(minute<0)
minute=59;
}
}
else if(key==3)//选中时的点阵
{
if(P3_6==0)//加
{
hour++;
if(hour>23)
hour=0;
}
if(P3_7==0)//减
{
hour--;
if(hour<0)
hour=23;
}
}
else if(key==4)//选中日的点阵
{
if(P3_6==0)//加
{
day++;
if(day>30)
day=0;
}
if(P3_7==0)//减
{
day--;
if(day<0)
day=30;
}
}
else if(key==5)//选中月的点阵
{
if(P3_6==0)//加
{
month++;
if(month>12)
month=0;
}
if(P3_7==0)//减
{
month--;
if(month<0)
month=12;
}
}
else
{
TL1=1;
EX0=1;//允许外部中断0中断
}
}
/********************************************************
*函数名称:DISPLAY
*功能描述:显示函数
*传递参数:
*********************************************************/
void DISPLAY()
{
DISPLAY_SECOND();//显示秒
DISPLAY_MINUTE();//显示分钟
DISPLAY_HOUR();//显示小时
DISPLAY_DAY();//显示日期
DISPLAY_MONTH();//显示月份
}
/********************************************************
*函数名称:DISPLAY_SECOND
*功能描述:显示秒
*传递参数:
*********************************************************/
void DISPLAY_SECOND()
{
uchar n;
P0=0x00;
P1=0xff;
P1=0xfe; //片选,选中秒的点阵
for(n=0;n<8;n++)
{P2=DATA_138[n];
P0=0x00;
P0=DATA_LED_SFM[second][n];
DELAY(1);
}
}
/********************************************************
*函数名称:DISPLAY_MINUTE
*功能描述:显示分
*传递参数:
*********************************************************/
void DISPLAY_MINUTE()
{
uchar n;
P1=0xfd;//片选,选中分的点阵
for(n=0;n<8;n++)
{P2=DATA_138[n];
P0=0x00;
P0=DATA_LED_SFM[minute][n];
DELAY(1);
}
}
/********************************************************
*函数名称:DISPLAY_HOUR
*功能描述:显示小时
*传递参数:
*********************************************************/
void DISPLAY_HOUR()
{
uchar n;
P1=0xfb;//片选,选中时的点阵
for(n=0;n<8;n++)
{P2=DATA_138[n];
P0=0x00;
P0=DATA_LED_SFM[hour][n];
DELAY(1);
}
}
/********************************************************
*函数名称:DISPLAY_DAY
*功能描述:显示日期
*传递参数:
*********************************************************/
void DISPLAY_DAY()
{
uchar n;
P1=0xf7;//片选,选中日的点阵
for(n=0;n<8;n++)
{P2=DATA_138[n];
P0=0x00;
P0=DATA_LED_SFM[day][n];
DELAY(1);
}
}
/********************************************************
*函数名称:DISPLAY_MONTH
*功能描述:显示月份
*传递参数:
*********************************************************/
void DISPLAY_MONTH()
{
uchar n;
P1=0xef;//片选,选中月的点阵
for(n=0;n<8;n++)