功能:
通过8位数码管实现实时时钟,可以设置时间,切换显示模式,显示年月日,时分秒信息;可通过按键修改信息,增加、减少、确定、取消、上一个、下一个、切换模式、设置等功能。
时分秒
年月日:
部分程序:
#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)??????????????????????????????? //月增加
{
1865