可编程作息时间控制器设计

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2012~2013学年第一学期
《单片机原理与应用》
课程设计报告
题目:可编程作息时间控制器设计专业:电子信息工程
班级:10电子信息(2)
姓名:牛然、付强、刘小朋
陈丽华、支发云
指导教师:周珍艮、崔雪英
电气工程系
2012年10月21日
《可编程作息时间控制器设计》任务书
课题名称数字电压表设计
指导教师(职称)周珍艮(副教授)崔雪英(讲师)
执行时间2012~2013学年第一学期第7周学生姓名学号承担任务
牛然1009121112 方案的总体设计、修改响铃时间功能及模拟手动控制功能的设计
付强1009121022 软件protues的仿真及PCB硬件图支发云1009121128 摘要及日期和时钟显示功能的设计陈丽华1009121100 绪论及上下课打铃功能的设计
刘小朋1009121044 日期和时钟显示功能的设计
设计目的1、掌握汇编语言的基本结构及应用;
2、掌握各个部分功能的设计及应用;
3、学会使用protues软件进行电路仿真。

设计要求1、按照给定的时间模拟控制实现上下课打铃、灯光控制(屏
幕显示);
2、具有各日期和时钟显示。

摘要
本课题是应用89C51为核心控制器件的作息时间控制钟,由键盘、声音输出模块、电源转换模块和存储模块四部分组成。

它利用89C51的定时/计数器来计算时间,并用存储器记录数据,保证了系统的可靠性。

89C51单片机是整个设计的核心控制器件,根据从键盘接受的数据控制整个设计的工作流程。

整体性好,人性化强,可靠性高,实现了对时间控制的智能化,摆脱了传统由人来控制时间的长短的不便,可对一些以24小时为周期的开关量进行自动控制。

如上下课打铃及扩音设备的开与关。

采用89C51单片机来实现对上述开关量的控制,利用24C02芯片来存储数据,设有六位数码管、可以实时显示时间、系统还设有输入键盘,用以修改实时实时时钟,体现了系统简单、工作稳定可靠、价廉、控制时间精确及系统体积小等特点。

首先设计各个模块的屏幕显示,其次是各个模块需要调用的小程序,有PC 机的日期和时钟,响铃声音,按键,屏幕显示以及延时的调用等等,最后是将各个功能模块与其中需要的小程序通过正确的汇编语言组建起来。

这样便完成了源文件的建立。

再通过.ASM源文件生成的.EXE可执行文件进行仿真。

该仿真可以模拟实现:与PC机日期时钟保持一致的显示功能,仿照已设定的响铃时间进行打铃功能,根据已设定的早晚作息时间灯光控制的功能,键盘输入修正响铃时间,随时手动按键实现响铃的功能。

关键词:89C51单片机仿真设计时钟电路作息时间控制汇编语言
Abstract
This topic is application 89C51 as the core of the daily routine of the control device to control the clock, and is composed of four parts, keyboard, voice output module, power conversion module and storage module. It uses the 89C51 timer / counter to calculate the time and memory record data to ensure the reliability of the system. 89C51 microcontroller core of the entire design control devices to accept data from the keyboard to control the entire design process. Good integrity, humane, high reliability, realized the intelligent control of the time, to get rid of the tradition by people to control the length of time the inconvenience, the automatic control of the 24-hour cycle switch. Above class playing bell and amplifying equipment on and off. 89C51 microcontroller to achieve control of the switch using 24C02 chip to store data, with six digital tube time, the system also has input keyboard can be displayed in real time, to modify real-time real-time clock, embodies a simple system, reliable, accurate and inexpensive, control time system is small.
First, the design of each module screen display, followed each module need to call a small program, date and time clock of the PC, bell sound, buttons, screen display, as well as the delay of the call, etc., and finally the various functional modules which need a small program is set up through the correct assembly language. This will complete the establishment of the source file. Then through the ASM source files generated. EXE executable simulation. The simulator can simulate achieve: consistent with the date of the PC clock display function, modeled on the set ring time a bell function, according to the morning and evening daily routine lighting control function, set the keyboard input correction rings always manually key rings.
Keywords: 89C51 microcontroller simulation design clock circuit rest time control assembly language
目录
摘要 .................................................................................................................. - 2 -目录 .................................................................................................................. - 4 -第一章绪论 ........................................................................................................ - 5 -
1.1 课题研究的目的与意义............................................................................ - 5 -
1.2 研究内容及采用方法................................................................................ - 5 -
1.2.1 主要研究内容................................................................................. - 5 -
1.2.2 主要采用方法................................................................................. - 5 -
1.3课题的研究原理......................................................................................... - 6 -第2章可编程作息时间控制器的方案设计 ...................................................... - 7 -
2.1总体方案组成框图及设计流程图........................................................... - 7 -
2.2具体步骤实施........................................................................................... - 9 -
2.2.1日期和时钟显示功能的设计......................................................... - 9 -
2.2.2 上下课打铃功能的设计............................................................... - 11 -
2.2.3 灯光显示功能的设计................................................................... - 14 -
2.2.4 修改响铃时间功能的设计........................................................... - 14 -
2.2.5 模拟手动控制功能的设计........................................................... - 15 -第3章可编程作息时间控制器的protues仿真 ............................................ - 17 -
3.1 仿真结果................................................................................................... - 17 -
3.2性能及误差分析....................................................................................... - 19 -附录 ................................................................................................................ - 20 -参考文献 .......................................................................................................... - 27 -
第一章绪论
1.1 课题研究的目的与意义
20世纪末,电子技术得到了飞速的发展。

在其推动下,现代电子产品几乎渗透到了社会的各个领域,有力的推动和提高了社会生产力的发展与信息化程度,同时也使现代电子产品性能进一步提升,产品更新换代的节奏也越来越快。

时间对于人来说总是那么珍贵,工作的忙碌性和繁杂让人容易忘记当前时间。

然而遇到重大事情的时候,一旦忘记时间,就会给自己或他人造成更大的麻烦。

对于学校来说作息时间尤为重要。

如今,在电子计算机基础上发展而来的可编程作息时间控制器,它可以利用电子计算机的内部时间,通过程序判断处理,完成对作息时间的精确控制,并且由于是程序控制,所以可通过改变程序而进而灵活改变作息时间,同时可以实时显示时间,并实现打铃功能。

可编程时间控制器可实现对时间控制的智能化,摆脱由人控制时间的长短不同的不便,并且可以在必要时人工切入控制,,完美的满足作息时间控制。

1.2 研究内容及采用方法
1.2.1 主要研究内容
利用PC机的时钟,用汇编语言编写作息时间控制程序,按照给定的时间模拟控制,上下课打铃、灯光控制(屏幕显示),并且具备日期和时钟显示。

给定的时间可修改,可模拟手动控制,用扬声器模拟打铃。

1.2.2 主要采用方法
通过汇编语言编程,先在数据段中开几段缓冲区,以存放需要显示的提示信息以及存储PC机内部时钟日期等等,调用子程序的清屏部分来显示已经设定好的屏幕部分,再调用DOS的日期及时钟调用功能,读取PC机内部日期和时钟,并将数据存入显示缓冲区,然后调用时间和日期显示功能,把程序设计成用刷新的方式来不断获取系统时间,这样就有了一秒一秒走动的日期时钟显示,在此过程需要用到延时程序,所以把延时程序单独做成一个子程序,然后在需要的时候调用它,使得时间显示程序更加精炼,此时日期和时钟显示功能已经完成;而后设计灯光控制(屏幕显示),采用比较跳转的方式即可,当到达设定的时间区域
时通过比较来判断是亮灯还是灭灯;随后是上下课打铃的模拟,需要调用DOS 显示功能,将设定好的时间在屏幕上显示出来,然后调用PC机内部时钟,判断时钟与给定时间是否相同,进而判断是否响铃,若响铃则调用设定好的响铃程序,并实现屏幕模拟显示;给定时间修改是调用键盘I/O中断功能号,获取键值的方法来进入,先确定应该修改哪个响铃,再将新的响铃时间数据存入要修改时钟的缓冲区,并将其覆盖来实现;模拟手动控制、用扬声器模拟打铃,同样采用调用键盘I/O中断功能号,获取键值的方法,判断是否与设定的手动按键相同,若相同则进入手动控制,进入后调用响铃程序,而后自动退出响铃,开始其他响应功能。

1.3课题的研究原理
将定时闹钟改造为4路可调闹钟,从而实现打铃等功能。

当四路闹钟中的任一路到时,均会点亮灯、打铃。

如有需求,可对程序进行调整,增加闹钟的路数,及到时后的处理方式
第2章 可编程作息时间控制器的方案设计
2.1 总体方案组成框图及设计流程图
时间作息控制的主体电路应包括秒信号发生器、时间显示电路按键电路、供电电源以及闹铃指示电路等几部分。

时间作息控制的系统组成框图如图2-1-1所示:
图2-1-1时间作息控制的系统组成框图
复位、时钟等电路
电源供电电路
声光指示电路
LED 显示电路
按钮电路
89C51
图2-1-2介绍了作息时间控制器的大致设计思路
开始
调用清屏程序
系统日期时间并且转二进
制为ACSII码
将日期时间存入显示器
缓冲区
显示日期、时间和界面
灯光控制显示
设定和修正时间

响铃
手动控制
按下Esc?

结束
图2-1-2方案实施流程图
2.2具体步骤实施
2.2.1日期和时钟显示功能的设计
2.2.1.1日期和时钟显示流程图
图2-2-1是时钟和日期设计的大体思路,先在数据段中开辟存储日期时间等的缓冲区,便于后续程序的使用,再调日期和时钟的DOS功能调用中的显示功能,将数据由二进制转换为ASCII码,存储并显示。

数据段存储显示时间提示
开辟存储日期时间缓冲区
代码段中调用日期
二进制转换为A S C I I码
存储缓冲区
调用时间
二进制转换为A S C I I码
存储缓冲区
调用界面和日期时钟显示
图2-2-1 日期和时钟显示流程图
2.2.1.2日期和时钟设计步骤分析
该模块设计中,先在数据段开了两段缓冲区,以存储显示日期和时间的提示Time is以及从PC机读到的日期和时间。

而后是调用DOS的日期功能,其功能号是2ah,日期分别存于cx,dx中,在该设计中调用出来的日期时间均是二进制数,如果要在界面中显示必须要转换成ASCII码。

每一次数制转换后均要将转换后的数据存储于数据段开辟的存储缓冲区tbuf内,接下来便可调用DOS的的9号显示功能,只需将提示信息、日期及时间的存储缓冲区的偏移地址赋予dx,再使用DOS功能,调用9号的显示功能即可。

这样,日期和时间的第一次显示时间完成,由于PC机的日期时间一直在变化,所以需要不断调用PC机的显示时间并显示,因此需要再回转至最初的调用日期程序,这样,显示日期时间的功能才真正完成。

下面是针对数制转换和日期时间的显示做的更为细致的解读。

(1)数制转换
通常在计算机当中,从键盘输入的十进制数的每一位数码或者是向CRT输出的十进制的每一位数,均是以它的ASCII码表示的。

而在机器中的一个十进制数,是以相应的二进制数存放或者是以BCD码的形式存放。

因此,如果我们想将PC机中读取的日期时间显示到.EXE的界面中,必须将从中读取的二进制数转换为ASCII码。

本设计是先将二进制数转换为十进制数,再将十进制数转换为ASCII码的,使其在屏幕上显示出来。

由于调用该小程序段的显示数值都是十位数或个位数,所以该段小程序的设计思路是使用减法,统计需要转换的数值中有多少10、1,即为十进制数中的十、个位上的数,然后将十进制数转换为ASCII码输出。

首先,在数据段中已经设计好了被减数,即const内的数据,用需要数据转换的数据已经在之前的数据中赋值给了ax,使用sub ax,[si]语句实现上述的减法,若不够减,则需要重复减,并累计次数,直至不够减为止,累计的次数即为该数据十位数的数值,此时仍旧通过or dI,30h语句转换为ASCII码,并将转换后的数据都存储于bx中。

程序片段如下:
btcd:push si
mov si, offset const
mov cx,2
add si,4
conv:mov dI,0
lop:sub ax,[si]
jc next
inc dI
jmp Iop
next:add ax,[si]
or dI,30h
mov[bx],dI
add si,2
inc bx
loop conv
pop si
ret
(2)日期时钟显示功能
9号DOS功能调用可实现日期时钟显示功能,由于需要在.EXE界面显示提示信息mess1中的相关内容,因此调用BIOS功能,置光标于0行0列,将ah 赋值2即可置光标,dh的赋值表示行,dI的赋值表示列,使用Iea dx,messI语句,将messI的偏移地址赋予dx,使用mov ah,9和int 21h语句完成DOS的9号功能调用,这样.EXE界面就出现了mess 1中的相关内容;再使用BIOS功能调用,将光标置于17行21列显示日期时间的提示信息time is,方法与上述介绍的相同,最后即可将光标置于17行37列,显示PC机的日期和时间。

程序片段如下:
push bx ;置光标位置
mov ah,2
mov bh,0
mov dh,17
mov dI,37 ;17行37列
int 10h
pop bx
lea dx,tbuf ;送tbuf偏移地址到dx,显示日期和时间
mov ah,9
int 21h
2.2.2 上下课打铃功能的设计
2.2.2.1上下课打铃设计流程图
如图是上下课打铃设计的大体思路,先于数据段设存储缓冲区,存储设定的响铃时间,将响铃时间由二进制换成ASCII代码,调用DOS的显示功能,显示响铃时间,再调PC机时间与设定的响铃时间比较,相同时响铃,不同时跳转。

数据段设存储缓冲区
响铃时间数值转换
界面显示响铃时间

设PC机时间与响铃比较
时间相等?

响铃
图2-2-2 上下课打铃设计流程图
2.2.2.2上下课打铃设计步骤分析
本部分设计中,先在数据段开辟了四段缓冲区,分别是bel响铃提示信息,tbufl响铃时间存储区,timeh设定好的响铃时间中小时的存储区,timem设定好的响铃时间中的分钟存储区,进入代码段后,便开始将timeh和timem中设定好的响铃时间由二进制数转换成ASCII代码,并将转换后的信息存于tbufl,对于数制转换的内容上文中已有介绍,这里便不再重复了。

这是tbufl中已经包含我最初设定的二十个响铃时间,使用DOS功能调用中的9号显示功能即可将上述二十个响铃时间显示在界面上。

随后需要调用PC机的时间与我设定的时间进行比较,若相等则响铃,响铃后返回,若时间不等同样也返回,去重复上述的显示、调用以及比较的过程。

接下来我会针对PC机时间与我设定的时间比较的程序和响铃程序做较为细致的分析,以使该设计更加清晰明了。

(1)PC机时间与设定响铃时间比较
首先我将存储响铃时间的timeh和timem的偏移地址分别赋给了si和di,随后使用DOS功能调用语句中的mov ah,2ch以及int 21h来完成PC机时间的读取,对于PC机时间的读取,系统自动将小时、分钟分别存于ch、cl中。

接下来便开始比较,先假设设定的响铃均已比较完,缓冲区后区时间为空,则应当先将PC 机时间与设定好的响铃时间比较,若相同则跳转响铃程序,若不相等则继续进行比较直至将设定好的响铃时间均比较完毕,然后进行后续工作。

程序片段如下:
mov si,offset timeh ;控制时间(小时)偏移地址送存
mov di,offset timem ;控制时间(分钟)偏移地址送存
mov cx,20
ling:push cx
mov ah,2ch ;调用dos的时间调用功能
int 21h
cmp ch,00h ;先比较小时位
jz guo ;若果是零则跳转
cmp ch,[si] ;比较小时位
jnz ljx ;不同时进行跳过继续比较
cmp cl,[di] ;小时位相同时比较分钟
jnz ljx ;不同时进行跳过继续比较
cmp dh,0ah ;相同时比较秒钟
jc xiang ;小于十五秒时进行响铃
ljx:inc si ;偏移地址自动加一,准备进行下一次比较inc di
pop cx
loop ling
(2)响铃功能设计分析
IBM PC机系列计算机的发声系统主要由定时器/计数器8253/8254芯片来提高音频信号,最后通过并行接口芯片8255的PB端口控制驱动电路使系统的扬声器发声。

8253/8254芯片共有3个独立的计数通道,其中2号通道分配给系统的扬声器频率控制,它的I/.O端口地址为42H,8253/8254的工作方式与音频频率均由8253/8254的控制寄存器(I/O端口地址42H)控制。

而且8253/8254有6种工作方式,对于扬声器发声总是选用方式3,因此为了让发生器工作,需要通过mov al,0b6h和out 43h,al来完成音频频率的设置,通过mov al,03h及out 61h,al来开扬声器,实现响铃。

2.2.3 灯光显示功能的设计
2.2.4 修改响铃时间功能的设计
2.2.4.1 修改响铃时间设计流程图
图2-2-3介绍了本模块的大体思路,首先在数据段设置存储时间的缓冲区,其次是调用键盘输入功能,算的修改响铃的个数和修改的起始位置,最后输入的时间替代原时间完成修改响铃时间的功能。

数据段设有存储时间缓冲区
调用键盘输入功能
计算修改几个响铃
计算从第几个开始修改
键盘输入时间代替原时间
图2-2-3 修给响铃时间设计流程图
2.2.4.2 修改响铃时间设计步骤分析
在本模块设计中,首先需要在数据段中开辟出修正提示信息和存储时间的缓冲区,当接收到手控修正响铃时间的信号时,调用键盘输入功能,该功能将扫描到的键盘信息均存储于缓冲区内,第一位为缓冲区位数,第二位为字符个数,将字符个数除以6即可得到修正响铃的时间个数。

由于键盘输入的前两位数字的意义是冲第几个响铃初开始修正,因此需要将前两位数由ASCII码转换成十进制数,将转换得到的数据存储,对于键盘输入时间替代原响铃时间功能的实现,需要根据前面得到的数据,先跳转至修正响铃时间的地址处,然后将键盘输入的响铃时间覆盖原时间,直至完成上述得到修正响铃的个数为止。

在模块的设计中计算修改几个响铃和应从第几个开始修改这两个小部分较为关键,下面是其更为详细的介绍。

(1)计算修改几个响铃
调用键盘输入功能,字符串存入缓冲区,第一位为缓冲区位数,第二位为字符个数,自第三位开始存储输入字符串,取缓冲区内第二个数值将其存于ax 中,由于键盘输入的数据均为00,00这种形式,所以每两个响铃时间均隔五个字符,因此mov cx,06h 和div cx 两语句即可得到修改响铃时间的个数。

(2)计算从第几个开始修改
调出键盘输入的前两位数字即可但由于键盘扫描的数字是以ASCII 码形式表示,而计算机中以二进制数形成存储,因此需要通过sub dh,30h 这种类似的语句进行数字转换,并通过地址循环递加的方式,找到需要修正响铃时间的地址。

2.2.5 模拟手动控制功能的设计 2.2.5.1 模拟手动控制设计流程图
图2-2-4介绍了本模块设计的大体思路,调用键盘I/O 中断功能号1,进行键盘扫描,判断当扫描到Esc 时,退出界面显示,为S 或s 实现响铃功能,即手动控制响铃。

为C 或c 时,跳转至修改响铃时间的程序段。




否 否

图2-2-4模拟手动控制设计流程图
开始 扫描键值 修改响铃时间
响铃
退出
为Esc 为C 或c
为S 或s
2.2.5.2 模拟手动控制设计步骤分析
模拟手动控制主要实现的功能是只要按下键盘的S或s键,便开始响铃,因此在设计时先要调用键盘I/O中断功能号1,获取键值到AL,然后将键值AL与lbh作比较,通过cmp al,lbh和jz quit判断是否按下Esc键,若是,则跳出.EXE 的界面,若不是,则将键值AL与S、s分别作比较,通过cmp al,S以及cmp al,s 和jz shou判断是否按下S或s键,若是跳转至响铃位置,即实现手动控制响铃的功能,若不是再通过cmp al,C以及cmp al,c和jz correct判断是否按下C 或c键,若是则跳转至修改响铃时间的位置。

程序片段如下:
guo:call delay1
mov ah,1 ;调用键盘I/O中断功能号1,获取键值到AL
int 16h
cmp al,1bh
jz quit ;是Esc键,退出程序
cmp al,‘s’ ;是s键,赚到手动控制时间程序
je shou
cmp al,‘S’ ;是S键,赚到手动控制时间程序
je shou
cmp al,‘c’
je correct ;是c键,修正响铃时间
cmp al,‘C’
je correct ;是C键,修正响铃时间
jmp display ;返回显示程序进行下一次循环
第3章可编程作息时间控制器的protues仿真3.1 仿真结果
3-1-1开始仿真初始值
3-1-2 按下K1后进入设定闹钟时间状态
3-1-3 按下K4开始计时
3.2性能及误差分析
该作息时间控制器有四个按键: K1, K2,K3和K4。

初始加电时数码管显示时钟计数初值并运行。

按K1键进行校时,可以分别按K2和K3键进行对时及分进行单独校时,使其校正到标准时间;并按K4键退出。

时钟正常显示运行状态时,按K2键显示闪烁并进行定时时间设置,按K1键和K3进行分和时的定时时间设定;并按K4键退出。

该电路显示的误差主要由晶振自身的误差所造成,晶振的误差约为0. 0001~0. 000001。

在软件的编程过程中所产生的误差比较小,另外在中断的过程中,只会在第一次计时时产生时间的偏移,而它所产生累计误差很小,可以忽略。

综合以上分析,本次设计时钟误差较小,能得到比较理想结果,性能稳定。

附录附录一:程序源代码
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit E=P3^4;
sbit RS=P3^5;
sbit key1=P2^4;
sbit key2=P2^5;
sbit key3=P2^6;
sbit key4=P2^7;
sbit mbkey=P2^2;
sbit beep=P2^3;
uchar
count,shi=1,fen=59,miao=58,key1num,flag,flag1 ,xqnum;//flag闹钟
uchar
key2num,jinzhi=3,naonum=1,ms,mbmiao,mbfen ,mbkeynum,num; //ms秒表进数,mbmiao.mbfen秒表的秒.分key2num是key5的计数jinzhi进制转换参数
uint nian=2009,yue=11,ri=19,count2;
uchar code table[]=" 2012-6-06 WED";
uchar code table1[]="24d 01:59:58 ON "; uchar code table2[]="MON,TUE,WED,THU,FRI,SAT,SUN ";
uchar code table3[]="am ,pm ,24d";
uchar code table4[]="ON ,OFF";
uchar code table5[]=" 00:00:00 mb ";
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void di(uint x) //蜂鸣器发声函数
{
beep=0;
delay(x);
beep=1;
}
void write_com(uchar com)//给写液晶命令{
RS=0;
P0=com;
delay(5);
E=1;
delay(5);
E=0;
}
void write_date(uchar date)//给液晶写数据
{
RS=1;
P0=date;
delay(5);
E=1;
delay(5);
E=0;
}
void init() //初始化函数
{
uchar num;
E=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);//清零
write_com(0x80);
for(num=0;num<16;num++)
{
write_date(table[num]);
delay(20);
}
write_com(0x80+0x40); //第二行
for(num=0;num<16;num++)
{
write_date(table1[num]);
delay(20);
}
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
TH1=(65536-10000)/256;
TL1=(65536-10000)%256;
ET1=0;
TR1=0;
}
void write_nian(uchar add , uint date) //年显示函数
{
uchar qian,bai,shi,ge;
qian=date/1000;
bai=(date-1000*qian)/100;
shi=(date-qian*1000-bai*100)/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+qian);
write_date(0x30+bai);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_yue(uchar add , uchar date) //月显示函数
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_ri(uchar add , uchar date) //日显示函数
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_sfm(uchar add ,uchar date) //秒显示函数
{
uchar shi,ge;
shi=date/10;
ge=date%10;
write_com(0x80+0x40+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
void write_week(uchar week)
//星期显示函数
{
uchar week_num;
week_num=week;
switch(week_num)
{
case 1: write_com(0x80+13);
write_date(table2[0]);
write_date(table2[1]);
write_date(table2[2]);
write_com(0x80+13);
break;
case 2: write_com(0x80+13);
write_date(table2[4]);
write_date(table2[5]);
write_date(table2[6]);
write_com(0x80+13);
break;
case 3: write_com(0x80+13);
write_date(table2[8]);
write_date(table2[9]);
write_date(table2[10]);
write_com(0x80+13);
break;
case 4: write_com(0x80+13);
write_date(table2[12]);
write_date(table2[13]);
write_date(table2[14]);
write_com(0x80+13);
break;
case 5: write_com(0x80+13);
write_date(table2[16]);
write_date(table2[17]);
write_date(table2[18]);
write_com(0x80+13);
break;
case 6: write_com(0x80+13);
write_date(table2[20]);
write_date(table2[21]);
write_date(table2[22]);
write_com(0x80+13);
break;
case 7: write_com(0x80+13);
write_date(table2[24]);
write_date(table2[25]);
write_date(table2[26]);
write_com(0x80+13);
break;
}
}
void write_jinzhi(uchar jinzhi)
//jinzhi进制显示函数
{
uchar jznum;
jznum=jinzhi;
switch(jznum)
{
case 1: write_com(0x80+0x40+0);
write_date(table3[0]);
write_date(table3[1]);
write_date(table3[2]);
write_com(0x80+0x40+0);
break;
case 2: write_com(0x80+0x40+0);
write_date(table3[4]);
write_date(table3[5]);
write_date(table3[6]);
write_com(0x80+0x40+0);
break;
case 3: write_com(0x80+0x40+0);
write_date(table3[8]);
write_date(table3[9]);
write_date(table3[10]);
write_com(0x80+0x40+0);
break;
}
}
void write_nao(uchar nao) //闹钟开关显示函数
{
uchar naonum;
naonum=nao;
switch(naonum)
{
case 1: write_com(0x80+0x40+13);
write_date(table4[0]);
write_date(table4[1]);
write_date(table4[2]);
write_com(0x80+0x40+13);
break;
case 2: write_com(0x80+0x40+13);
write_date(table4[4]);
write_date(table4[5]);
write_date(table4[6]);
write_com(0x80+0x40+13);
break;
}
}
void keyboard() //按键扫描函数
{
if(flag==1)
{
//闹钟暂停函数
if(key4==0)
{
delay(5);
if(key4==0)
{
while(!key4);
beep=1;
flag=0;
}
}
}
if(key1==0)
{
delay(5);//消斗
if(key1==0)
{
key1num++;
while(!key1);
// di(1);
if(key1num==1)
{
TR0=0;
write_com(0x80+0x40+10);
write_com(0x0f);//光标闪烁
}
if(key1num==2)
{
write_com(0x80+0x40+7);
}
if(key1num==3)
{
write_com(0x80+0x40+4);
}
if(key1num==4)
{
write_com(0x80+0x40);
}
if(key1num==5)
{
write_com(0x80+2);
}
if(key1num==6)
{
write_com(0x80+7);
}
if(key1num==7)
{
write_com(0x80+10);
}
if(key1num==8)
{
write_com(0x80+13);
}
if(key1num==9)
{
write_com(0x80+0x40+13);
}
if(key1num==10)
{
key1num=0;
write_com(0x0c);//光标停止闪烁
TR0=1;//打开定时器
}
}
}
if(key1num!=0)
{
if(key2==0)
{
delay(5);
if(key2==0)
{
while(!key2);//等待松手
di(100);
if(key1num==1)
{
miao++;
if(miao==60)
miao=0;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(key1num==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(key1num==3)
{
shi++;
if(jinzhi==3)
{
if(shi==24)
shi=0;
}
else
{
if(shi>12) shi=shi-12;
}
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
if(key1num==4)
{
jinzhi++;
if(jinzhi==4)
jinzhi=1;
write_jinzhi(jinzhi);
}
if(key1num==5)
{
nian++;
write_nian(2,nian);
write_com(0x80+2);
}
if(key1num==6)
{
yue++;
if(yue==13)
y ue=1;
write_yue(7,yue);
write_com(0x80+7);
}
if(key1num==7)
{
ri++;
if(ri==32)
ri=1;
write_ri(10,ri);
write_com(0x80+10);
}
if(key1num==8)
{
xqnum++;
if(xqnum==8)
xqnum=1;
write_week(xqnum);
}
if(key1num==9)
{
naonum++;
if(naonum==3)
naonum=1;
write_nao(naonum);
}
if(key1num==10)
{
key1num=0;
write_com(0x0c);//光标停止闪烁
TR0=1;//打开定时器
}
}
}
if(key3==0)
{
delay(5);
if(key3==0)
{
while(!key3);
di(100);
if(key1num==1)
{
miao--;
if(miao==-1)
miao=59;
write_sfm(10,miao);
write_com(0x80+0x40+10);
}
if(key1num==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(7,fen);
write_com(0x80+0x40+7);
}
if(key1num==3)
{
shi--;
/* if(shi==-1)
shi=23;*/
if(jinzhi==3)
{
if(shi==-1)
shi=23;
}
else
{
if(shi<1)
shi=shi+12;
}
write_sfm(4,shi);
write_com(0x80+0x40+4);
}
if(key1num==4)
{
jinzhi--;
if(jinzhi==0)
jinzhi=3;
write_jinzhi(jinzhi);
}
if(key1num==5)
{
nian--;
write_nian(2,nian);
write_com(0x80+4);
}
if(key1num==6)
{
yue--;
if(yue==0)
yue=12;
write_yue(7,yue); write_com(0x80+7);
}
if(key1num==7)
{
ri--;
if(ri==0)
ri=31;
write_ri(10,ri);
write_com(0x80+13); /* if(key1num==8)
{
xqnum--;
if(xqnum==0)
xqnum=7;
write_week(xqnum);
write_com(0x80+10);
}
if(key1num==9)
{
naonum--;
if(naonum==0)
naonum=2;
write_nao(naonum); write_com(0x80+0X40+13);
}
*/
}
}
}
}
}
void mbiao( ) //秒表函数
{
if(mbkey==0)
{
mbkeynum++;
while(!mbkey);
if(mbkeynum==1)
//关闭时钟定时器
{
TR0=0;
ET0=0;
write_com(0x80+0x40);
for(num=0;num<16;num++)
write_date(table5[num]);
ms=0;
mbmiao=0;
mbfen=0;
TR1=0;
ET1=0;
}
if(mbkeynum==2)
//打开秒表定时器关闭时钟定时器
{
TR1=1;
ET1=1;
TR0=0;
ET0=0;
}
if(mbkeynum==3)
//关闭秒表定时器
{
TR1=0;
ET1=0;
TR0=0;
ET0=0;
}
if(mbkeynum==4)
//显示时钟状态打开时钟定时器
{
TR0=1;
ET0=1;
TR1=0;
ET1=0;
write_sfm(10,miao);
write_sfm(7,fen);
write_sfm(4,shi);
write_jinzhi(jinzhi);
write_com(0x80+0x40+13);
write_date(' ');
write_date('O');
write_date('N');
mbkeynum=0;
}
}
}
void main()
{
init();
while(1)
{
keyboard();
mbiao();
if(count==20)
//液晶变化
{
count=0;
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(jinzhi==3)
//24进制时钟
{
if(shi==24)
shi=0;
}
else
{
if(shi>12)
//12进制时钟
{
shi=shi-12;
jinzhi++;
if(jinzhi==3)
jinzhi=1;
}
}
write_sfm(4,shi);
write_jinzhi(jinzhi);
}
write_sfm(7,fen);
}
write_sfm(10,miao);
if(miao==0&&fen==0&&shi==0||(jinzhi== 2&&shi==12&&fen==0&&miao==0))
//日期和星期递变
{
write_com(0x80+9);
ri++;
if(ri==32)
{
ri=1;
yue++;
if(yue==13)
{
yue=1;
nian++;
write_nian(2,nian);
}
write_yue(7,yue);
}
write_ri(10,ri);
xqnum++;
write_week(xqnum);
}
if(fen==0&&miao>=0&&miao<=5)
//整点报时
{
flag=1;
beep=~beep;
}
if(naonum==1&&shi==07&&fen==15&& miao>=0&&miao<=5)
//闹钟
{
flag=1;
beep=~beep;
}
}
}
}
void timer0() interrupt 1 //时钟定时器
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
}
void timer1() interrupt 3 //秒表定时器
{
TH1=(65536100000)/256;
TL1=(65536100000)%256;
ms++;
write_sfm(10,ms);
if(ms==1*30)
{
mbmiao++;
write_sfm(7,mbmiao);
ms=0;
if(mbmiao==60)
{
mbmiao=0;
mbfen++;
write_sfm(4,mbfen);
}
}
}
图一:未布线图
图二:布线后图
参考文献。

相关文档
最新文档