目 录
第一章 引言..................................... 1
第二章 设计方案论证............................. 2
2.1方案论证与设计.................................. 2
2.2 电路设计最终方案决定........................ 3
第三章 系统硬件电路设计.......................... 4
3.1电路设计框图..................................... 4
3.2 系统硬件概述..................................... 4
3.3主要单元电路的设计............................... 4
第四章 系统软件电路设计......................... 11
4.1主程序流程图.................................... 11
4.2 按键调整流程图.................................. 11
第五章 系统硬件和软件的调试..................... 13
5.1 系统硬件的焊接与调试............................ 13
5.2 系统软件的调试.................................. 13
致谢........................................... 14
参考文献........................................ 14
附录一 电路原理图.............................. 15
附录二 程序清单................................ 16
第一章 引 言
随着微电子技术的高速发展,单片机在国民经济的个人领域得到了广泛的运用。单片机以体积小、功能全、性价比高等诸多优点,在工业控制、家用电器、通信设备、信息处理、尖端武器等各种测控领域的应用中独占鳌头,单片机开发技术已成为电子信息、电气、通信、自动化、机电一体化等专业技术人员必须掌握的技术。而电子万年历作为电子类小设计不仅是市场上的宠儿,也是是单片机实验中一个很常用的题目。因为它的有很好的开放性和可发挥性,因此对作者的要求比较高,不仅考察了对单片机的掌握能力更加强调了对单片机扩展的应用。而且在操作的设计上要力求简洁,功能上尽量齐全,显示界面也要出色。数字显示的日历钟已经越来越流行,特别是适合在家庭居室、办公室、大厅、会议室、车站和广场等使用,电子日历越来越受到人们的青睐。所以,电子万年历无论作为比赛题目还是练习题目都是很有价值。
本文通过对一个基于单片机的能实现万年历功能电子时钟的设计,从而达到学习、了解单片机相关指令在各方面的应用。系统由主控制器AT89S52、时钟电路DS1302、显示电路、按键电路、和复位电路等部分构成,能实现时钟日历显示的功能,能进行年、月、日、星期、时、分、秒的显示。
第二章 设计方案论证
2.1方案论证与设计
2.1.1单片机芯片的选择方案和论证
方案一:
采用89C51芯片作为硬件核心,采用Flash ROM,内部具有4KB ROM 存储空间,能于3V的超低压工作,而且与MCS-51系列单片机完全兼容,但是运用于电路设计中时由于不具备ISP在线编程技术, 当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,对芯片的多次拔插会对芯片造成一定的损坏。
方案二:
采用AT89S52,片内ROM全都采用Flash ROM;能以3V的超底压工作;同时也与MCS-51系列单片机完全该芯片内部存储器为8KB ROM 存储空间,同样具有89C51的功能,且具有在线编程可擦除技术,当在对电路进行调试时,由于程序的错误修改或对程序的新增功能需要烧入程序时,不需要对芯片多次拔插,所以不会对芯片造成损坏。
所以选择采用AT89S52作为主控制系统.
2.1.2时钟芯片的选择方案和论证
方案一:
直接采用单片机定时计数器提供秒信号,使用程序实现年、月、日、星期、时、分、秒计数。采用此种方案虽然减少芯片的使用,节约成本,但是,实现的时间误差较大。所以不采用此方案。
方案二:
采用DS1302时钟芯片实现时钟,DS1302芯片是一种高性能的时钟芯片,可自动对秒、分、时、日、周、月、年以及闰年补偿的年进行计数,而且精度高,位的RAM做为数据暂存区,工作电压2.5V~5.5V范围内,2.5V时耗电小于300nA。
所以选择DS1302时钟芯片。
2.1.3显示部分的选择方案和论证
方案一:
采用点阵式数码管显示,点阵式数码管是由八行八列的发光二极管组成,对于显示文字比较适合,如采用在显示数字显得太浪费,且价格也相对较高,所以不用此种作为显示。
方案二:
采用LED数码管动态扫描,虽然LED数码管价格适中,但要显示多个数字所需要的个数偏多,功耗较大,所以也不用此种作为显示。
方案三:
采用LCD液晶显示屏,液晶显示屏的显示功能强大,可显示大量文字,图形,显示多样,清晰可见,与普通数码管相比功耗较小,硬件连接简单。
所以选择液晶LCD1602作为显示。
2、2电路设计最终方案决定
综上各方案所述,对此次作品的方案选定: 采用AT89S52作为主控制系统; DS1302提供时;液晶LCD1602作为显示。
|
第三章 系统硬件电路设计
3.1电路设计框图
图3-1 电路设计框图
3.2 系统硬件概述
本电路是由STC89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作;时钟电路由DS1302提供,它是一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31*8的用于临时性存放数据的RAM寄存器。可产生年、月、日、周日、时、分、秒,具有使用寿命长,精度高和低功耗等特点,同时具有掉电自动保存功能,本电路采用DS1302单字节传送方式实现与主控机之间数据的传送;显示部份由液晶LCD1602构成。
3.3主要单元电路的设计
3.3.1单片机主控制模块的设计
AT89S52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3, MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。
单片机的最小系统如下图3-2所示,18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出.第9引脚为复位输入端,接上电容,电阻及开关后构成上电复位电路,20引脚为接地端,40引脚为电源端。如图3-2 所示
图3-2 主控制系统
3.3.2时钟电路模块
1. DS1302的结构及工作原理
DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。
2. 引脚功能及结构
图3-3所示出DS1302 的引脚排列,其中VCC1 为后备电源,VCC2 为主电源。在主电源关闭的情况下,也能保持时钟的连续运行。DS1302 由VCC1 或VCC2 两者中的较大者供电。当VCC2 大于VCC1+0.2V 时,VCC2 给DS1302供电。当VCC2 小于VCC1 时,DS1302 由VCC1 供电。X1 和X2 是振荡源,外接32.768kHz 晶振。RST 是复位/片选线,通过把RST 输入驱动置高电平来启动所有的数据传送。RST 输入有两种功能:首先,RST 接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST 提供终止单字节或多字节数据的传送手段。当RST 为高电平时,所有的数据传送被初始化,允许对DS1302 进行操作。如果在传送过程中RST 置为低电平,则会终止此次数据传送,I/O 引脚变为高阻态。上电运行时,在VCC≥2.5V 之前,RST 必须保持低电平。只有在SCLK 为低电平时,才能将RST 置为高电平。I/O 为串行数据输入输出端(双向),后面有详细说明。SCLK 始终是输入端。
图3-3 DS1302引脚图
(2) DS1302的控制字节
DS1302的控制字如图3-4所示。控制字节的高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
RAM RD
1 /CK A4 A3 A2 A1 A0 /WR
图3-4 DS1302的控制字格式
(3) 数据输入输出(I/O)
在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。如下图3-5所示。
图3-5 DS1302单字节读/写时序图
(4) DS1302的寄存器
DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见图3-6。
图3-6 DS1302的日历、时间寄存器
此外,DS1302 还有年份寄存器、控制寄存器、充电寄存器、时钟突发寄存器及与RAM相关的寄存器等。时钟突发寄存器可一次性顺序读写除充电寄存器外的所有寄存器内容。 DS1302与RAM相关的寄存器分为两类:一类是单个RAM单元,共31个,每个单元组态为一个8位的字节,其命令控制字为C0H~FDH,其中奇数为读操作,偶数为写操作;另一类为突发方式下的RAM寄存器,此方式下可一次性读写所有的RAM的31个字节,命令控制字为FEH(写)、FFH(读)。
3.3.3 LCD1602显示模块
1、字符型液晶显示模块是一种专门用于显示字母、数字、符号等点阵式 LCD, 目前常用 16*1,16*2,20*2 和 40*2 行等的模块。下面以长沙太阳人电子有限公 司的 1602 字符型液晶显示器为例,介绍其用法。一般 1602 字符型液晶显示器实物如图3-7所示,
图3-7 LCD1602外形图
2、引脚功能说明
1602LCD 采用标准的 14 脚(无背光)或 16 脚(带背光)接口,各引脚接口说明如图3-8所示,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
编号 |
|
符号 |
|
引脚说明 |
|
编号 |
|
符号 |
|
引脚说明 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
|
VSS |
|
电源地 |
|
9 |
|
D2 |
|
数据 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2 |
|
VDD |
|
电源正极 |
|
10 |
|
D3 |
|
数据 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
|
VL |
|
液晶显示偏压 |
|
11 |
|
D4 |
|
数据 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
RS |
|
数据/命令选择 |
|
12 |
|
D5 |
|
数据 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
R/W |
|
读/写选择 |
|
13 |
|
D6 |
|
数据 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
|
E |
|
使能信号 |
|
14 |
|
D7 |
|
数据 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
|
D0 |
|
数据 |
|
15 |
|
BLA |
|
背光源正极 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
|
D1 |
|
数据 |
|
16 |
|
BLK |
|
背光源负极 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
图3-8 LCD1602引脚接口说明表
- 1 脚:VSS 为地电源。
- 2 脚:VDD 接 5V 正电源。
- 3 脚:VL 为液晶显示器对比度调整端,接正电源时对比度最弱,接地时对比 度最高,对比度过高时会产生“鬼影”,使用时可以通过一个 10K 的电位器调整 对比度。
- 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存 器。
- 5 脚:R/W 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 R/W 共同为低电平时可以写入指令或者显示地址,当 RS 为低电平 R/W 为高电 平时可以读忙信号,当 RS 为高电平 R/W 为低电平时可以写入数据。
- 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行令。
第7~14 脚:D0~D7 为 8 位双向数据线。
第15 脚:背光源正极。
第16 脚:背光源负极。
读写操作时序如图3-9所示
图3-9 读操作时序
图3-10 写操作时序
3、1602LCD 的 RAM 地址映射及标准字库表
液晶显示模块是一个慢显示器件,所以在执行每条指令之前一定要确认模块的忙标志为低电平,表示不忙,否则此指令失效。要显示字符时要先输入显示字符地址,也就是告诉模块在哪里显示字符,图3-11是 1602 的内部显示地址。
图3-11 LCD1602 内部显示地址
例如第二行第一个字符的地址是 40H,那么是否直接写入 40H 就可以将光标定位在第二行第 一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 所以实 际写入的数据应该是 01000000B(40H)+10000000B(80H)=11000000B(C0H)。
第四章 系统软件电路设计
LCD电子万年历的软件设计包括显示程序、初始化程序、按键调整程序等。通过各模块的确定来进一步的设计软件。运用计算机进行仿真逐步实现LCD电子万年历的各项性能指标。在程序设计中采用模块化设计思想,能使程序可读性加强,而且编写时很方便,将要实现的功能分成几部分,由于某些功能使用不只一次,将它编成一个子程序,既可随时多次调用,修改时也不会影响其他程序。具体程序见附录二。
4.1主程序流程图
图4-1 主程序流程图
4.2 按键调整流程图
调整时间是由3个按键控制完成的,1个作为移位控制用,另外2个分别作为加调整和减调整用。在调整时间过程中,要调整的位与其他位应该有区别,所以增加了闪烁功能,即调整的位一直在闪烁,直到调整下一位示值给该位。时间调整程序流程图如图4-2所示。
判断是否有键按下 |
Y |
计时停止 |
N |
判断功能键按下次数 |
等待加、减键按下 |
加键按下 |
减键按下 |
对应位时间加1 |
对应位时间减1 |
显示子程序 |
返回,进入主循环 |
=8次 |
≤7次 |
图4-2 按键调整流程图
第五章 系统硬件和软件的调试
5.1 系统硬件的焊接与调试
电子万年历的电路系统中,对于焊接方面不可轻视,电路系统中只要出现一处的微小错误,都会对检测造成很大的不便,使电路不可能正常的工作。在本次电子万年历的设计调试中遇到了很多的问题。主要的问题如下:
(1)误把DS1302晶振连接后又接到电源地端;
(2)1602在显示时间时出现黑格子,遮挡了时间,原因是在第三引脚没加电阻分压导致,加上10K可调电阻后电路正常显示时间。
5.2 系统软件的调试
电子万年历的软件程序还是比较庞大的,思路一定要保持清晰,尤其是对DS1302时钟芯片要有很好的理解,才能灵活的使用和控制。所以在编写程序和调试时出现了相对较多的问题。最后经过多次的调试修改,一步一步的完成,最终解决了软件。在软件的调试过程中主要遇到的问题如下:
(1)对万年历修改时间或日期时,有时时间改变2次,在程序中加上松手检测即可;
(2)1602显示的时间不完整,最后在液晶初始化程序中加上该显示的数字即可;
(3)在调整时间时光标闪烁不规律,原因的由于错用DS1302停振指令所致,最后加上一个变量进行控制即可。
最后经过多次的反复分析与调试,电路达到了本次设计的基本要求。在不断的调试中,对电路的原理及功能更加熟悉,同时提高了设计能力与及对电路的分析能力;在软件的编程方面也得到一定的提高,对编程经验也得到了积累,同时对所学的知识得到很大的提高与巩固。
致谢
历经两个月的毕业设计结束了,过程的曲折可谓一言难尽。从开始时满怀热情到最后汗水背后的复杂心情,点点滴滴无不令我回味无长。本次毕业设计中我设计了一个LCD电子万年历。通过不断的翻阅资料对于单片机及接口技术,以及利用编程语言对单片机进行结构化编程的一般方法和技巧有了很多的理解。对于智能仪器的设计方法有了新的认识。
在设计的过程中也经历了很多自己没有想到的困难。在不断研读程序中,学习到了不少编程知识。这些对于我以后的学习有很大的帮助。在这些日子里我得到了指导教师的悉心指导和同学们的热心帮忙,在此向我们的指导教师致以诚挚的谢意。感谢提供相关技术帮助的老师和同学,你们的支持和鼓励使我们对这次的作品完成有了信心和动力,也给了我们很多无私的帮助和支持,我们在此深表谢意。
毕业设计的结束也意味着我将走出校园,结束学生生涯,走入社会,不管有多么的不舍,但该面对的还是要面对。总之,这两个月的毕业设计真的让我成长很多,在今后的工作中我也要尽可能的多学东西,不断的完善自己!
[1] 郭天祥.51单片机C语言教程.电子工业出版社,2009,147-166.
[2] 李广弟.单片机基础.北京航空航天大学出版社,2007,18-28.
[3] 占跃华.C语言程序设计.北京邮电大学出版社,2010,66-70.
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
//uchar code table1[]={" 2011-12-23 05"} ;
//uchar code table2[]={" 10:59:50"};
sbit lcdrs=P1^0;
sbit lcdrw=P1^1;
sbit lcden=P1^2;
sbit ACC0=ACC^0;
sbit ACC7=ACC^7;
sbit dsio=P1^6;
sbit dsclk=P1^5;
sbit dsrst=P1^7;
sbit set=P2^7;
sbit up=P2^3 ;
sbit down=P2^0;
void keyscan();
void write_sfm(uchar add,uchar shu);
char shi,fen,miao,ri,yue,nian,zhou,flag;
void delay(uchar z)
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
/***********往ds1302写入一字节***************/
void inputbyte(uchar add)
{
uchar i;
ACC=add;
for(i=8;i>0;i--)
{
dsio=ACC0;
dsclk=1;
dsclk=0;
ACC=ACC>>1;
}
}
/**********ds1302输出一字节****************/
uchar outputbyte(void)
{
uchar i;
for(i=8;i>0;i--)
{
ACC=ACC>>1;
ACC7=dsio;
dsclk=1;
dsclk=0;
}
return ACC;
}
/*********往ds1302写入数据*****************/
void write_ds(uchar add,uchar ucda)
{
dsrst=0;
dsclk=0;
dsrst=1;
inputbyte(add);
inputbyte(ucda);
dsclk=1;
dsrst=0;
}
/*********从ds1302读出数据*****************/
uchar read_ds(uchar add)
{
uchar ucda;
dsrst=0;
dsclk=0;
dsrst=1;
inputbyte(add);
ucda=outputbyte();
dsclk=1;
dsrst=0;
return(ucda);
}
/*********往1602液晶写入指令*****************/
void write_com(uchar com)
{
lcdrs=0;
lcdrw=0;
P0=com;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/********往1602液晶写入数据******************/
void write_date(uchar date1)
{
lcdrs=1;
lcdrw=0;
P0=date1;
delay(5);
lcden=1;
delay(5);
lcden=0;
}
/**********设置DS1302****************/
void write_setds(uchar addr,uchar date)
{
write_ds(0x8e,0x00);
write_ds(addr,date);
write_ds(0x8e,0x80);
}
/*************初始化*************/
void init()
{
//uchar i;
lcden=0;
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
delay(5);
write_com(0x80+0x01);
{
write_date(0x32);
delay(2);
}
write_com(0x80+0x02);
{
write_date(0x30);
delay(2);
}
write_com(0x80+0x05);
{
write_date(0x2d);
delay(2);
}
write_com(0x80+0x08);
{
write_date(0x2d);
delay(2);
}
write_com(0x80+0x44);
{
write_date(0x3a);
delay(2);
}
write_com(0x80+0x47);
{
write_date(0x3a);
delay(2);
}
}
/************往1602写入日期**************/
void write_nyr(uchar add,uchar date)
{
uchar shi,ge ;
shi=date/10;
ge=date%10;
write_com(0x80+0x01+add);
write_date(0x30+shi);
write_date(0x30+ge);
}
/*********显示函数*****************/
void display()
{
if(flag!=1)
{
uchar d;
d=read_ds(0x81);
miao=(d/16)*10+(d%16);
write_sfm(8,miao);
d=read_ds(0x83);
fen=(d/16)*10+(d%16);
write_sfm(5,fen);
d=read_ds(0x85);
shi=(d/16)*10+(d%16);
write_sfm(2,shi);
d=read_ds(0x87);
ri=(d/16)*10+(d%16);
write_nyr(8,ri);
d=read_ds(0x89);
yue=(d/16)*10+(d%16);
write_nyr(5,yue);
d=read_ds(0x8b);
zhou=d%16;
write_nyr(12,zhou);
d=read_ds(0x8d);
nian=(d/16)*10+(d%16);
write_nyr(2,nian);
}
}
/*********往1602写入时间*****************/
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 main()
{
init();
write_setds(0x80,0x50);
write_setds(0x82,0x59);
write_setds(0x84,0x10);
write_setds(0x86,0x23);
write_setds(0x88,0x12);
write_setds(0x8a,0x05);
write_setds(0x8c,0x11);
write_setds(0x90,0xa4);
while(1)
{
keyscan();
}
display();
}
void keyscan()
{
uchar aa,bb,rimax;
if(set==0)
{
delay(3);
if(set==0)
{
aa++;
while(!set);
if(aa==1)
{
flag=1;
write_ds(0x8e,0x80);
write_com(0x80+0x40+8);
write_com(0x0f);
write_ds(0x8e,0x00);
bb=read_ds(0x81);
miao=(bb/16)*10+bb%16;
bb=read_ds(0x83);
fen=(bb/16)*10+bb%16;
bb=read_ds(0x85);
shi=(bb/16)*10+bb%16;
bb=read_ds(0x87);
ri=(bb/16)*10+bb%16;
bb=read_ds(0x89);
yue=(bb/16)*10+bb%16;
bb=read_ds(0x8b);
zhou=(bb/16)*10+bb%16;
bb=read_ds(0x8d);
nian=(bb/16)*10+bb%16;
}
if(aa==2)
write_com(0x80+0x40+5);
if(aa==3)
write_com(0x80+0x40+2);
if(aa==4)
write_com(0x80+0x0d);
if(aa==5)
write_com(0x80+0x09);
if(aa==6)
write_com(0x80+6);
if(aa==7)
write_com(0x80+3);
if(aa==8)
{
aa=0;
write_com(0x0c);
write_ds(0x8e,0x80);
flag=0;
}
}
}
if(aa!=0)
{
if(up==0)
{
delay(5) ;
if(up==0)
{
while(!up);
if(aa==1)
{
miao++;
if(miao==60)
miao=0 ;
write_sfm(8,miao);
write_com(0x80+0x40+9);
}
if(aa==2)
{
fen++;
if(fen==60)
fen=0;
write_sfm(5,fen);
write_com(0x80+0x40+6);
}
if(aa==3)
{
shi++;
if(shi==24)
shi=0;
write_sfm(2,shi);
write_com(0x80+0x40+3);
}
if(aa==4)
{
zhou++;
if(zhou==8)
zhou=1;
write_nyr(12,zhou);
write_com(0x80+0x0d);
}
if(aa==5)
{
ri++;
if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
rimax=31;
if(yue==4||yue==6||yue==5||yue==9||yue==11)
rimax=30;
if(yue==2)
{
if(nian%4==0&&nian%100!=0||nian%400==0)
rimax=28;
else
rimax=29;
}
if(ri>rimax)
// if(ri==32)
ri=1;
write_nyr(8,ri);
write_com(0x80+0x0a);
}
if(aa==6)
{
yue++;
if(yue==13)
yue=1;
write_nyr(5,yue);
write_com(0x80+7);
}
if(aa==7)
{
nian++;
if(yue>99)
yue=0;
write_nyr(2,nian);
write_com(0x80+4);
}
}
}
if(down==0)
{
delay(5) ;
if(down==0)
{
while(!down);
if(aa==1)
{
miao--;
if(miao==-1)
miao=59;
write_sfm(8,miao);
write_com(0x80+0x40+9);
}
if(aa==2)
{
fen--;
if(fen==-1)
fen=59;
write_sfm(5,fen);
write_com(0x80+0x40+6);
}
if(aa==3)
{
shi--;
if(shi==-1)
shi=23;
write_sfm(2,shi);
write_com(0x80+0x40+3);
}
if(aa==4)
{
zhou--;
if(zhou==0)
zhou=7;
write_nyr(12,zhou);
write_com(0x80+0x0d);
}
if(aa==5)
{
ri--;
if(ri==0)
{
if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)
ri=31;
if(yue==4||yue==6||yue==5||yue==9||yue==11)
ri=30;
if(yue==2)
{
if(nian%4==0&&nian%100!=0||nian%400==0)
ri=28;
else
ri=29;
}
}
// if(ri==0)
// ri=31;
write_nyr(8,ri);
write_com(0x80+0x0a);
}
if(aa==6)
{
yue--;
if(yue==0)
yue=12;
write_nyr(5,yue);
write_com(0x87);
}
if(aa==7)
{
nian--;
if(nian==-1)
nian=99;
write_nyr(2,nian);
write_com(0x84);
}
}
}
write_ds(0x80,(miao/10)*16+miao%10);
write_ds(0x82,(fen/10)*16+fen%10);
write_ds(0x84,(shi/10)*16+shi%10);
write_ds(0x86,(ri/10)*16+ri%10);
write_ds(0x88,(yue/10)*16+yue%10);
write_ds(0x8a,(zhou/10)*16+zhou%10);
write_ds(0x8c,(nian/10)*16+nian%10);
}
display();
}