基于51单片机的实时时钟设计

功能:

通过8位数码管实现实时时钟,可以设置时间,切换显示模式,显示年月日,时分秒信息;可通过按键修改信息,增加、减少、确定、取消、上一个、下一个、切换模式、设置等功能。

时分秒

3ef97254e9aa404cb42226dbc4659700.png

年月日:

bbbd5c778d7c4769b1c8d4c2f3829e32.png

部分程序:

#include <reg51.h>

#include "MAX7221.h"

#include "DS1302.h"

void InitTimer0(void);           //定时器T0初始化函数

void Disp(void);                 //时间显示函数

void SSetTime(unsigned char n,unsigned char m,unsigned char *readvalue,unsigned char *Cflag);  //用户设置时间函数

void Delay(unsigned char time);  //延时函数

void SDisp(unsigned char n);     //设置时间,数码管闪烁函数

sbit Next=P1^0;                  //“下一个”按钮

sbit Pre=P1^1;                   //“上一个”按钮

sbit ADD=P1^2;                   //“增加”按钮

sbit SUB=P1^3;                   //“减少”按钮

sbit SET=P1^4;                   //“确定”按钮

sbit Cancel=P1^5;                //“取消”按钮

sbit LED=P2^6;                   //设置指示灯

SYSTEMTIME CurrentTime;          //时间日期类型

signed char DispBuf[16];         //存放时间日期的个位与十位

unsigned char DISPCODE[]={0,1,2,3,4,5,6,7,8,9,0x0A,0x0F};   //数码管显示数组,0x0A数码管显示“-”,0x0F数码管不显示

unsigned int  count=1200;         //用于设定时间/日期在数码管上的显示时间

unsigned char DisFlag=0;         //显示标志,0位时间显示,1位日期显示

unsigned char SetFlag=0;         //设置标志

void main(void)

{

         InitTimer0();                  //定时器初始化

         Init_Max7221(0xFF,0x0A,0x07,0x01);//MAX7221初始化

         Init_DS1302();                 //DS1302初始化;注:1 Warning,由于在中断0中也调用了SetTime()函数,所以有一个警告,可忽略警告;如果你将其注释掉,会出现新的警告,因为你在DS1302中写了Init_DS1302()函数,而你没有调用;标准是一定要调用Init_DS1302()函数的

         IT0=1;                         //设置中断INT0

         EX0=1;

         IT1=1;                         //设置中断INT1

         EX1=1;

         EA=1;

         LED=0;                         //设置指示灯为灭的状态

  while(1)

         {

                  Disp();                      //显示时间/日期 

                  Delay(10);

         }

  return;

}

//时间/日期显示函数

void Disp(void)

{

         GetTime(&CurrentTime);                   //获取时间/日期

         if(DisFlag==0)                           //判断是不是显示时间

         {

                  DispBuf[7]=(CurrentTime.Second)%10;    //秒的个位

                  DispBuf[6]=(CurrentTime.Second)/10;    //秒的十位

                  DispBuf[5]=10;                         //“-”

                  DispBuf[4]=(CurrentTime.Minute)%10;    //分的个位

                  DispBuf[3]=(CurrentTime.Minute)/10;    //分的十位

                  DispBuf[2]=10;                       //“-”

                  DispBuf[1]=(CurrentTime.Hour)%10;      //时的个位

                  DispBuf[0]=(CurrentTime.Hour)/10;      //时的十位

         }

         else if(DisFlag==1)

         {

                  DispBuf[7]=(CurrentTime.Day)%10;       //日的个位

                  DispBuf[6]=(CurrentTime.Day)/10;       //日的十位

                  DispBuf[5]=10;                         //“-”

                  DispBuf[4]=(CurrentTime.Month)%10;     //月的个位

                  DispBuf[3]=(CurrentTime.Month)/10;     //月的十位

                  DispBuf[2]=10;                         //“-”

                  DispBuf[1]=(CurrentTime.Year)%10;      //年的个位

                  DispBuf[0]=(CurrentTime.Year)/10;            //年的十位

         }

  Wr_Max7221(0x08,DISPCODE[DispBuf[7]]);   //显示秒的个位或日的个位

         Wr_Max7221(0x07,DISPCODE[DispBuf[6]]);   //显示秒的十位或日的十位

         Wr_Max7221(0x06,DISPCODE[DispBuf[5]]);   //显示“-”

         Wr_Max7221(0x05,DISPCODE[DispBuf[4]]);   //显示分的个位或月的个位

         Wr_Max7221(0x04,DISPCODE[DispBuf[3]]);   //显示分的十位或月的十位

         Wr_Max7221(0x03,DISPCODE[DispBuf[2]]);   //显示“-”

         Wr_Max7221(0x02,DISPCODE[DispBuf[1]]);   //显示时的个位或年的个位

         Wr_Max7221(0x01,DISPCODE[DispBuf[0]]);   //显示时的十位或年的十位

}

//T0定时器初始化子程序

void InitTimer0(void)

{

         TMOD=0x01;                 //工作方式1

         TH0=(65536-50000)/256;     //定时时间为0.5ms

         TL0=(65536-50000)%256;

         EA=1;                      //开总中断

         ET0=1;                     //允许定时器T0中断

         TR0=1;                     //打开定时器T0

}

//T0定时器服务子程序

void Timer0(void) interrupt 1

{

         TR0=0;                     //关定时器T0                    

         TH0=(65536-50000)/256;     //重载初值

         TL0=(65536-50000)%256;

         count--;

         if(count==0)               //count*0.5ms定时到

         {

                  if(DisFlag==0)           //如果上一个是显示时间

                  {

                                   DisFlag=1;           //改为显示日期  

                            count=100;           //显示5s

                  }

                  else if(DisFlag==1)

                  {

                           count=1200;             //显示60s

                     DisFlag=0;             //改为显示时间 

                  }

         }

         TR0=1;                     //打开定时器T0

}

                      SetFlag=0;                         //清除设置标志

                            break;                             //退出设置模式 

                   }

                   if(Next==0)  n=n-1;                   //“下一个”按钮按下时,某数据设置位标志减1                                

                   if(n<=0)     n=6;                     //若到达0时,回到6设置

                   if(Pre==0)   n=n+1;                   //“上一个”按钮按下时,某数据设置位标志加1

                   if(n>=7)     n=1;                     //若到达0时,回到6设置

                   if(ADD==0)   m=1;                     //“增加”按钮按下时,设置增加标志

                   if(SUB==0)   m=2;                     //“减少”按钮按下时,设置减少标志

                   if((Next==0)||(ADD==0)||(SUB==0))     //判断是否有“下一个”按钮或“增加”按钮或“减少”按钮按下

                   {

                            Delay(50);                         //延时(给一定的释放按钮时间)

               SSetTime(n,m,readvalue,&Cflag);    //进入相关的设置

                   }

                   SDisp(n);                             //显示

                   m=0;                                  //清除“增加”或“减少”标志

         }

         LED=0;                                   //设置完毕,关设置指示灯

         count=1200;                               //设置完毕后,“时间”显示的60s

         DisFlag=0;                               //显示“时间”

         EA=1;                                    //开总中断

}

//时间日期变化子函数

void SSetTime(unsigned char n,unsigned char m,signed char *readvalue,signed char* Cflag)

{

         if(m==1)                                       //设置值增加

         {

    if(n==6)                                     //年增加

                  { 

                           *Cflag|=0x01;                             //年值变化标志

              readvalue[5]=readvalue[5]+1;              //年值加1

                           if(readvalue[5]>=100)  readvalue[5]=00;   //判断是否大于99,若是,将其设置为0

                           DispBuf[0]=readvalue[5]/10;               //保存年的十位

                           DispBuf[1]=readvalue[5]%10;                         //保存年的个位   

                  }

                  else if(n==5)                                //月增加

                  {

  • 8
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白茶丫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值