单片机课程设计实验报告(时钟、日历)

基于单片机的电子钟设计

目录

第一章电子时钟设计---------------------------------2

1.1 设计原理简介-------------------------------------2

1.2 设计功能------------------------------------------3

第二章主要电路元器件介绍------------------------3

2.1 STC89C52 单片机简介----------------------------3

2.1.1 单片机简介----------------------------------------3

2.1.2 主要特性------------------------------------------3

2.1.3 管脚功能说明--------------------------------------4

2.1.4  LCD1602-----------------------------------------5

第三章单元电路的硬件设计------------------------6

3.1 硬件原理框图---------------------------------------6

3.2 单片机 STC89C52 系统的设计-------------------------6

3.3 时钟电路-------------------------------------------7

3.4 复位电路-----------------------------------------------------------------------------7

3.5 键盘接口电路---------------------------------------8

3.6 LCD1602显示----------------------------------------8

第四章  设计总原理图---------------------9

第五章  心得体会-------------------------9

第六章   源程序---------------------------------------10

前言:

摘要 

数字钟已成为人们日常生活中必不可少的必需品,广泛用于个人家庭以及办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大的方便。由于数字集成电路技术的发展和采用了先进的石英技术,使数字钟具有走时准确、性能稳定、携带方便等优点,它还用于计时、自动报时及自动控制等各个领域。尽管目前市场上已有现成的数字钟集成电路芯片出售,价格便宜、使用也方便,但鉴于单片机的定时器功能也可以完成数字钟电路的设计,因此进行数字钟的设计是必要的。在这里我们将已学过的比较零散的数字电路的知识有机的、系统的联系来用于实际,来培养我们的综合分析和设计电路,写程序、调试电路的能力。单片

机具有体积小、功能强可靠性高、价格低廉等一系列优点,不仅已成为工业控领域普遍采用的智能化控制工具,而且已渗入到人们工作和和生活的各个角落,有力地推动了各行的技术改造和产品的更新换代,应用前景广阔。

一、作品介绍

该电子钟使用AT89S51为核心,采用LCD1602液晶屏显示,动态显示技术。产用外部接5V电源供电,内部添加了一个4.8V左右的电池以防突然断电后还能保持原先数据不变。该产品简单易于操作,可以实现以下功能:

1、显示年份,格式“年、月、日” 

2、时间显示为24小时制,格式“时时”“分分”“妙妙”

3、显示星期,用英文字符表示如星期一“MON”

二、 设计目的 

1、巩固、加深和扩大51系列单片机应用的知识面,提高综合及灵活运用所学知识解决工业控制的能力; 

2、 学会怎么使用LCM602,并且要知道它的组成与构造。 

3、学会查阅书籍,并且要能够熟练编写程序、仿真、绘画流程图、原理图及BCP图。 

4、对课题设计方案的分析、选择、比较、熟悉用51单片机做系统开发、研制的过程,软硬件设计的方法、内容及步骤。

三、设计要求 

1上电以后自动进入计时状态。 

2、设计键盘调整时间,完成年月日、星期、时间的设计。

3、采用AT89S51为核心控制芯片,用LCD1602作为显示屏。

第一章

1.1 设计原理简介

该设计设计一个电子时钟,我们采用的是 STC89C52 单片机用软件实现计数和显示。该单片机是一个微型计算机,包括中央处理器 CPU,RAM,ROM、I/O 接口电路、定时计数器、串行通讯等,是时钟计数设计的核心。该时钟原理框图如图 1.1,总体原理为:利用 STC89C52 单片机构造电子时钟,可显示年、月、日、星期、时、分、秒,通过 C 语言对单片机的编程即可产生相应的计时功能,并可以通过键盘进行时间的调整的控制。

图 2.1   信号发生器原理框图

    本方案其主要模块包括复位电路、时钟信号、键盘控制、LCD1602 显示。其各个模块的作原理如下:

    (1)复位电路是为单片机复位使用,使单片机接口初始化;89C52 等 CMOS51 系列

单片机的复位引脚 RET 是施密特触发输入脚,内部有一个上拉低电阻,当振荡器起振以后,在 RST 引脚上输出 2 个机械周期以上的高电平,器件变进入复位状态开始,此时ALE、PSEN、P0、P1、P2、P3 输出高电平,RST 上输入返回低电平以后,变退出复位状态开始工作。该方案采用的是人工开关复位,在系统运行时,按一下开关,就在 RST 断出现一段高电平,使器件复位。

    (2)时钟信号是产生单片机工作的时钟信号,控制着计算机的工作节奏,可以通过提高时钟频率来提高 CPU 的速度。89C52 内部有一个可控的反相放大器,引脚 XTAL1、XTAL2为反相放大器输入端和输出端,在 XTAL1、XTAL2 上外接 12MHZ 晶振和 30pF 电容便组成振荡器。时钟信号常用于 CPU 定时和计数。

(3)键盘模块是是用于控制信号输入的类型,当按键按下时,可以通过单片机编STC89C52单片机数接口电路键盘输入程读取闭合的键号,实现相应的时间调整。其步骤主要是 a、断是否有键按下;b、去抖动,延时 20ms 左右;c、识别被按下的键号;d、处理,实现功能。

(4)LCD1602显示,通过单片机控制把数据送到LCD1602上显示。

1.2 设计功能

    (1)本设计利用 3 位(P3.0 、P3.1、P3.2)控制时间的调整,其中当 P3.0=0对要调整的年、月、日、星期、时、分、秒的切换;当 P3.1=0进行加1设置;当 P3.2=0进行减1设置。

(2)本设计利用LCD1602液晶显示进行时间的显示,由单片机的P0端口进行数据的传输;LCD的4(RS)接P2.5, 5(RW)接P2.6,  6(E)接P2.7。

             第二章主要电路元器件介绍

2.1 STC89C52 单片机简介

2.1.1 单片机简介

AT89C51是一种带4K字节FLASH存储器的低电压、高性能 CMOS 8 位微处理器,俗称单片机。该芯片具有优异的性价比,集成度高,体积小,可靠性强,控制功能强等优点。其外形及引脚排列如图 2.1 所示。

                    

2.1.2 主要特性                                    图  2.1

(1)兼容性能强

(2)4K 字节可编程 FLASH 存储器

(3)全静态工作:0Hz-24MHz

(4)128×8 位内部 RAM

(5)32 可编程 I/O 线

(6)两个 16 位定时器/计数器

(7)5 个中断源

(8)可编程串行通道

(9)低功耗的闲置和掉电模式

(10)片内振荡器和时钟电路

2.1.3 管脚功能说明

VCC:供电电压。

GND:接地。

P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8个TTL门电流。当P0口的管脚第一次写“1”时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的第八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,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:反向振荡放大器的输入及内部时钟工作电路的输入。

XTAL2:来自反向振荡器的输出。

2.1.4  LCD1602

    这里介绍的字符型液晶模块是一种用 5x7 点阵图形来显示字符的液晶显示器,根据显示的容量可以分为 1 行 16 个字、2 行 16 个字、2 行 20个字等等,这里以常用的 2 行 16 个字的 1602 液晶模块来介绍它的编程方法。1602 采用标准的 16 脚接口,其中:

第 1 脚:VSS 为地电源

第 2 脚:VDD 接 5V 正电源

第 3 脚:V0 为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高,对比度过高时会产生“鬼影”,使用时可以通过一个10K 的电位器调整对比度

第 4 脚:RS 为寄存器选择,高电平时选择数据寄存器、低电平时选择指令寄存器。

第 5 脚:RW 为读写信号线,高电平时进行读操作,低电平时进行写操作。当 RS 和 RW 共同为低电平时可以写入指令或者显示地址,当 RS 为低电平 RW 为高电平时可以读忙信号,当 RS 为高电平 RW 为低电平时可以写入数据。

第 6 脚:E 端为使能端,当 E 端由高电平跳变成低电平时,液晶模块执行命令。

第 7~14 脚:D0~D7 为 8 位双向数据线。

第15脚:背光电源正极

第16脚:背光电源负极

第三章单元电路的硬件设计

   

    硬件原理硬件电路的设计决定一个系统的的功能,是设计的基础所在,而一般设计的标:可靠,简洁,高效,优化,好的硬件电路可以给程序的编写带来极大的优势,同时使可以很好的提高该信号设计的精度和灵敏度,使整个系统工作协调有序。

3.1 硬件原理框图

对于该电子时钟的设计,我们采用了以STC89C52单片机芯片作为核心处理器,编程实现时间的计时,最后通过 LCD1602的显示。结构简单,思路仅仅有条,而根据设计的基本要求,我们又把其细分为不同的功能模块,各个功能模块相互联系,相互协调,通过单片机程序构成一个统一的整体,其整体电路原理框

如图3.1 所示:                                              图3.1

 3.2 单片机 STC89C52 系统的设计

    89C52 单片机是该信号发生器的核心,具有 2 个定时器,32 个并行 I/O 口,1 个串行 I/O 口,5 个中断源。由于本设计功能简单,数据处理容易,数据存储空间也足够,因为我们采用了片选法选择芯片,进行芯片的选择和地址的译码。

单片机引脚分配如下:

    XTAL1,XTAL2:外接晶振,产生时钟信号;

RES:复位电路;       

P0口:接LCD1602的第7~14脚进行数据的传输;

P2口:LCD的4(RS)接P2.5, 5(RW)接P2.6,  6(E)接P2.7;

P3口:接按键开关,对时间进行设置。

3.3 时钟电路

单片机的时钟信号通常用两种电路形式得到:内部振荡和外部振荡方式。在引脚XTAL1 和XTAL2 外接晶体振荡器,构成了内部振荡方式。由于单片机内部有一个高增益的反相放器,当外接晶振后,就构成了自激振荡,并产生振动时钟脉冲。晶振通常选用 6MHZ、12MHZ、24MHZ。本设计中时钟电路图如图3.2,我们选择了12MHZ和晶振分别接引脚XTAL1和XTAL2,电容 C1,C2 均选择为 30pF,对振荡器的频率有稳定作用。

                                                                                                  

                                                                    图3.2

3.4 复位电路

    复位引脚 RST 通过一个斯密特触发器与复位电路相连,斯密特触发器用来抑制噪声,在每个机器周期的 S5P2,斯密特触发器的输出电平由复位电路采样一次,然后才能得到内部复位操作所需要的信号。复位电路通常采用上电自动复位和按钮复位两种方式。本设计选择了按键复位如图 4.3,在系统运行时,按一下开关,就在 RST 断出现一段高电平,使器件复位。此时 ALE、PSEN、P0、P1、P2、P4 输出高电平,RST 上输入返回低电平以后,变退出复位状态开始工作。

3.5 键盘接口电路

P3.0 、P3.1、P3.2控制时间的调整,其中当 P3.0=0对要调整的年、月、日、星期、时、分、秒的切换;当 P3.1=0进行加1设置;当 P3.2=0进行减1设置。

                       图3.4


3.6 LCD1602显示

    对于1602与单片机的连接方法如图3.5所示:

图3.5


第四章  设计总原理图


五、实验心得体会

   

    该电子时钟在调试时,总是出现许多的错误,软件上出了许多的问题,之后纠正,和组员慢慢调试修改了好多次。可是在仿真时依然存在很多的问题,开始的时候是仿真没有时间显示,之后改了改电路的P0数据传输线后时间就显示出来了。在时间的调整上问题更多,刚开始时按键没有反应,然后加上了消抖延时后才有反应,但是设的延时时间太长就出现按键不灵,再改后就正常了。

   在开发板上调试时,背光是亮着,但是没有数字出现,经过查看1602的资料才发现仿真不需要调节3脚的变位器,而在电路板上时就需要调节变位器才能使它正常显示。

第六章   源程序

#include <reg52.h>

#define uchar unsigned char

#define uint unsigned int

uchar ds1302_readbyte();

void ds1302_writebyte(uchar dat);

uchar ds1302_readdata(uchar addr);

void ds1302_writedata(uchar addr,uchar dat);

void ds1302_settime(uchar *p);

void ds1302_gettime(uchar *p);

void ds1302_initial();

sbit dssclk=P1^6;

sbit dsIO=P1^7;

sbit dsrs=P1^5;

sbit lcd_rs=P2^5;

sbit lcd_write=P2^6;

sbit lcd_en=P2^7;

sbit key1=P3^0;     //设置

sbit key2=P3^1;     //加

sbit key3=P3^2;     //减

uchar table_r[]=" 20##-01-01 MON ";

uchar table_s[]="   00:00:00";

uchar table_week[][3]={'M','O','N',

                    'T','U','E',

                    'W','E','D',

                    'T','H','U',

                    'F','R','I',

                    'S','A','T',

                    'S','U','N'

                      };

uchar i,t,keynum1;

char sec,min,hour,week,day=1,mon=1;

uint year=2013;

uchar Convert(uchar In_Date)

{

    uchar i, Out_Date = 0, temp = 0;

    for(i=0; i<8; i++)

    {

        temp = (In_Date >> i) & 0x01;

        Out_Date |= (temp << (7 - i));

    }

    return Out_Date;

}

void delay(uchar z)     //延时程序

{  

    uchar x,y;

    for(x=0;x<148;x++)

       for(y=0;y<z;y++);

}

void  write_com(uchar com)// 往液晶中写指令

{

    lcd_rs=0;

    lcd_en=0;

    P0=Convert(com);

    delay(2);

    lcd_en=1;

    delay(2);

    lcd_en=0;

}

void write_data(uchar date)//往液晶中写数据

{

    lcd_rs=1;

    lcd_en=0;

    P0=Convert(date);

    delay(2);

    lcd_en=1;

    delay(2);

    lcd_en=0;

}

void data_refresh_0(uchar add,uchar date)//第一行二位数调整

{

    uchar shi,ge;

    shi=date/10;

    ge=date%10;

    write_com(0x80+add);

    write_data(0x30+shi);

    write_data(0x30+ge);

   

}

void data_refresh_1(uchar add,uchar date)//第二行二位数调整

{

    uchar shi,ge;

    shi=date/10;

    ge=date%10;

    write_com(0x80+0x40+add);

    write_data(0x30+shi);

    write_data(0x30+ge);

   

void data_refresh_2(uchar add,uchar date)     //星期调整

{

   

    switch(date)

       {

          case 0:write_com(0x80+add);

                 write_data(table_week[0][0]);

                 write_data(table_week[0][1]);

                 write_data(table_week[0][2]);

                 break;

          case 1:write_com(0x80+add);

                 write_data(table_week[1][0]);

                 write_data(table_week[1][1]);

                 write_data(table_week[1][2]);

                 break;

          case 2:write_com(0x80+add);

                 write_data(table_week[2][0]);

                 write_data(table_week[2][1]);

                 write_data(table_week[2][2]);

                 break;

          case 3:write_com(0x80+add);

                 write_data(table_week[3][0]);

                 write_data(table_week[3][1]);

                 write_data(table_week[3][2]);

                 break;

          case 4:write_com(0x80+add);

                 write_data(table_week[4][0]);

                 write_data(table_week[4][1]);

                 write_data(table_week[4][2]);

                 break;

          case 5:write_com(0x80+add);

                 write_data(table_week[5][0]);

                 write_data(table_week[5][1]);

                 write_data(table_week[5][2]);

                 break;

          case 6:write_com(0x80+add);

                 write_data(table_week[6][0]);

                 write_data(table_week[6][1]);

                 write_data(table_week[6][2]);

                 break;

       }

}

void data_refresh_4(uchar add,uint date)     //四位数调整

{

    uchar qian,bai,shi,ge;

    qian=date/1000;

    bai=date%1000/100;

    shi=date%1000%100/10;

    ge=date%1000%100%10;

    write_com(0x80+add);

    write_data(0x30+qian);

    write_data(0x30+bai);

    write_data(0x30+shi);

    write_data(0x30+ge);

   

void lcd_init()           //液晶显示初始化

    lcd_write=0;

       lcd_rs=0;

       lcd_en=0;

    write_com(0x38);

    write_com(0x0c);

    write_com(0x06);

    write_com(0x01);

       write_com(0x80);

       for(i=0;i<15;i++)

         {

           write_data(table_r[i]);

              delay(10);

         }

       write_com(0x80+0x40);

       for(i=0;i<11;i++)

         {

           write_data(table_s[i]);

              delay(10);

         }

}

timer0_init()             //定时器0初始化

{

     TMOD=1;

    TH0=(65536-50000)/256;

    TL0=(65536-50000)%256;

    EA=1;

    ET0=1;

    TR0=1;

}

void keyscan()             //按键扫描

{

    if(key1==0)

      {

        delay(5);

        if(key1==0)

          { 

             TR0=0;

             keynum1++;

             delay(10);

             while(!key1);

             write_com(0x80+0x40+10);

             write_com(0x0f);

             if(keynum1==2)//分

               {

                 write_com(0x80+0x40+7);

               }

             if(keynum1==3)//时

               {

                 write_com(0x80+0x40+4);

               }

             if(keynum1==4)//年

               {

                 write_com(0x80+4);

               }

             if(keynum1==5)//月

               {

                 write_com(0x80+7);

               }

             if(keynum1==6)//日

               {

                 write_com(0x80+10);

               }

             if(keynum1==7)//星期

               {

                 write_com(0x80+14);

               }

             if(keynum1==8)

               {

                 keynum1=0;

                 TR0=1;

                 write_com(0x0c);

               }

          }

      }

    if(keynum1!=0)

      {

         if(keynum1==1)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        sec++;

                        if(sec==60) sec=0;

                        delay(10);

                        while(!key2);

                        data_refresh_1(9,sec);

                        write_com(0x80+0x40+10);

                       

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        sec--;

                        if(sec==-1) sec=59;

                        delay(10);

                        while(!key3);

                        data_refresh_1(9,sec);

                        write_com(0x80+0x40+10);

                     }

                }

           }

         if(keynum1==2)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        min++;

                        if(min==60) min=0;

                        delay(10);

                        while(!key2);

                        data_refresh_1(6,min);

                        write_com(0x80+0x40+7);

                       

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        min--;

                        if(min==-1) min=59;

                        delay(10);

                        while(!key3);

                        data_refresh_1(6,min);

                        write_com(0x80+0x40+7);

                     }

                }

           }

         if(keynum1==3)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        hour++;

                        if(hour==24) hour=0;

                        delay(10);

                        while(!key2);

                        data_refresh_1(3,hour);

                        write_com(0x80+0x40+4);

                       

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        hour--;

                        if(hour==-1) hour=23;

                        delay(10);

                        while(!key3);

                        data_refresh_1(3,hour);

                        write_com(0x80+0x40+4);

                     }

                }

           }

         if(keynum1==7)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        week++;

                        if(week==7) week=0;

                        delay(10);

                        while(!key2);

                        data_refresh_2(12,week);

                        write_com(0x80+14);

                       

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        week--;

                        if(week==-1) week=7;

                        delay(10);

                        while(!key3);

                        data_refresh_2(12,week);

                        write_com(0x80+14);

                     }

                }

           }

         if(keynum1==6)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        day++;

                        if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)

                             {

                            

                               if(day==32) day=1;

                          }

                        if(mon==2)

                          {

                             if(year%400==0||(year%100!=0&&year%4==0))

                                {

                                   if(day==30) day=1;

                                }

                             else

                                {

                                    if(day==29) day=1;

                                }

                          }

                        if(mon==4||mon==6||mon==9||mon==11)

                             {

      

                               if(day==31) day=1;

                          }

                        delay(10);

                           while(!key2);

                           data_refresh_0(9,day);

                           write_com(0x80+10);

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        day--;

                        if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)

                             {

                           

                               if(day==0) day=31;

                          }

                        if(mon==2)

                          {

                             if(year%400==0||(year%100!=0&&year%4==0))

                                {

                                   if(day==0) day=29;

                                }

                             else

                                {

                                    if(day==0) day=28;

                                }

                          }

                        if(mon==4||mon==6||mon==9||mon==11)

                             {

      

                               if(day==0) day=30;

                          }

                        delay(10);

                        while(!key3);

                        data_refresh_0(9,day);

                        write_com(0x80+10);

                     }

                }

           }

         if(keynum1==5)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        mon++;

                        if(mon==13) mon=1;

                        delay(10);

                        while(!key2);

                        data_refresh_0(6,mon);

                        write_com(0x80+7);

                       

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        mon--;

                        if(mon==0) mon=12;

                        delay(10);

                        while(!key3);

                        data_refresh_0(6,mon);

                        write_com(0x80+7);

                     }

                }

           }

         if(keynum1==4)

           {

              if(key2==0)

                {

                   delay(5);

                   if(key2==0)

                     {

                        year++;

                        if(year==2100) year=2010;

                        delay(10);

                        while(!key2);

                        data_refresh_4(1,year);

                        write_com(0x80+4);

                       

                     }

                }

              if(key3==0)

                {

                   delay(5);

                   if(key3==0)

                     {

                        year--;

                        if(year==2009) year=2099;

                        delay(10);

                        while(!key3);

                        data_refresh_4(1,year);

                        write_com(0x80+4);

                     }

                }

           }

      }

}

void main()               //主函数

{

    lcd_init();

    timer0_init();

       ds1302_initial();

       ds1302_gettime();

    while(1)

      {

           delay(5);

               keyscan();       //按键扫描

      }  

}

void timer0() interrupt 1       

{

    TH0=(65536-50000)/256;

    TL0=(65536-50000)%256;

    t++;

    if(t==20)

      {

         t=0;

         sec++;

         if(sec==60)

           {

              sec=0;

              min++;

              if(min==60)

                {

                   min=0;

                   hour++;

                   if(hour==24)

                      {

                        hour=0;

                        day++;

                        week++;

                        if(week==7) week=0;

                        if(mon==1||mon==3||mon==5||mon==7||mon==8||mon==10||mon==12)

                          {

                             if(day==32)

                                {

                                   day=1;

                                   mon++;

                                   if(mon==13)

                                      {

                                        mon=1;

                                        year++;

                                        if(year==2100) year=2010;

                                        data_refresh_4(1,year);

                                      }

                                   data_refresh_0(6,mon);

                                }

                          }

                     if(mon==2)

                        {

                            if(year%400==0||(year%100!=0&&year%4==0))

                               {

                                    if(day==30)

                                       {

                                          day=1;

                                          mon++;

                                          if(mon==13)

                                             {

                                               mon=1;

                                               year++;

                                               if(year==2100) year=2010;

                                               data_refresh_4(1,year);

                                             }

                                          data_refresh_0(6,mon);

                                       }

                               }

                            else

                               {

                                   if(day==29)

                                       {

                                          day=1;

                                          mon++;

                                          if(mon==13)

                                             {

                                               mon=1;

                                               year++;

                                               if(year==2100) year=2010;

                                               data_refresh_4(1,year);

                                             }

                                          data_refresh_0(6,mon);

                                       }                                  

                               }

                              

                        }

                     if(mon==4||mon==6||mon==9||mon==11)

                          {

                             if(day==31)

                                {

                                   day=1;

                                   mon++;

                                   if(mon==13)

                                      {

                                        mon=1;

                                        year++;

                                        if(year==2100) year=2010;

                                        data_refresh_4(1,year);

                                      }

                                   data_refresh_0(6,mon);

                                }                      

                          }

                        data_refresh_2(12,week);

                        data_refresh_0(9,day);

                      }

                   data_refresh_1(3,hour);

                }

              data_refresh_1(6,min);

           }

         data_refresh_1(9,sec);

      }

}

//*********************************************************************************************//

uchar ds1302_readbyte()   //从1302读1字节数据

{

 uchar i;

 uchar dat=0;

 for(i=0;i<8;i++)

   {

       dssclk=0;

        delay(5);

        dat>>=1;

        if(dsIO)

        dat |=0x80;

        dssclk=1;

        delay(5);

   }

   return dat;

}

//****************************************************************************************************//

void ds1302_writebyte(uchar dat)   //向1302写1字节数据

{

 uchar i;

 for(i=0;i<8;i++)

   {

     dssclk=0;

       delay(5);

       dat>>=1;

       dsIO=CY;

       dssclk=1;

       delay(5);

   }

}

//*******************************************************************************************************//

uchar ds1302_readdata(uchar addr)        //读13002某个地址的数据

{

 uchar dat;

 dsrs=0;

  delay(5);

  dssclk=0;

   delay(5);

   dsrs=1;

    delay(5);

    ds1302_writebyte(addr);   //写地址

       dat=ds1302_readbyte();     //读数据

       dssclk=1;

       dsrs=0;

       return dat;

}

//********************************************************************************************************************//

void ds1302_writedata(uchar addr,uchar dat)         //往13002某个地址写数据

{

 dsrs=0;

 delay(5);

 dsrs=1;

 delay(5);

 ds1302_writebyte(addr);   //写地址

 ds1302_writebyte(dat);   //写数据

 dssclk=1;

 dsrs=0;

}

//*****************************************************************************************************************//

void ds1302_settime(uchar *p)     //写入时间

{

 uchar addr=0x80;

 uchar n=7;

 ds1302_writedata(0x8e,0x00);   //允许写

 while(n--)

   {

     ds1302_writedata(addr,*p++);

       addr+=2;

   }

 ds1302_writedata(0x8e,0x80);   //写保护

}

//*****************************************************************************************************************//

void ds1302_gettime(uchar *p)       //读取时间

{

 uchar addr=0x81;

 uchar n=7;

 while(n--)

   {

     *p++=ds1302_readdata(addr);

       addr+=2;

   }

}

//**************************************************************************************************************//

void ds1302_initial()   //初始化1302

{

 dsrs=0;

 dssclk=0;

 ds1302_writedata(0x8e,0x00);   //允许写操作

  ds1302_writedata(0x80,0x00);   //时钟启动

   ds1302_writedata(0x90,0xaa);  

    ds1302_writedata(0x8e,0x80);   //写保护

}

相关推荐