实现实时时钟,电源拔插时间不重置(内置电池供电维持时间变化)。功能有查看日期,查看星期,查看闹钟和分别的调整时间,调整日期,调整闹钟,调整星期。且默认情况下不可以调整,当按下可调控键之后才可以调整、再次按可调控键关闭变为不可调整状态。还有整点报时功能(有个小瑕疵就是闹钟正好是整点的时候和这个整点报时同时间的时候不会报时和闹钟,这个很容易改好,因为下午3点要答辩了,懒得改了机子老是写不进去,学校穷便宜机子没办法)。然后这个闹钟可以设置星期几几点闹也可以设置为普通的每天的这个时间点闹铃,这些都是可以调控的。时钟所有的功能都有,只差一个秒表,,这个很简单,,,外部中断来一个或者定时器T1中断来一个都可以,我没弄,因为我这个已经代码很长了,头疼、加中断还得加显示函数和秒表变化函数if分大于60 时++啥的,但因为这个采用的显示是低四位高四位控制的,我强行加一个也比较麻烦所有就没加了。欢迎下载干货,难看懂的都有备注,写了断断续续一周+时间左右(恕在下才疏学浅,因为书上上课的时候没学过I2C总线和pcf8563所以写的比较久。)部分代码如下:
#define MAIN_Fosc 22118400L //定义主时钟 频率也是计数计时周期一秒的计数值
#include "STC15Fxxxx.H"
/***********************************************************/
#define DIS_DOT 0x20
#define DIS_BLACK 0x10
#define DIS_ 0x11
/****************************** 用户定义宏***********************************/
#define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率,1000次/秒 频率倍数计数即周期 周期为1秒 除以一千就是1000次每秒
/*****************************************************************************/
/************* 本地常量声明 **************/
u8 code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F //共阴
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
u8code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码 取反就是书上213面 0从低位到高位
/************* IO口定义 **************/
sbit P_HC595_SER = P4^0; //pin 14 SER datainput
sbit P_HC595_RCLK = P5^4; //pin 12 RCLk store(latch) clock
sbit P_HC595_SRCLK = P4^3; //pin 11 SRCLK Shift data clock
sbit led=P1^7;
sbit led1=P4^7;
sbit key=P3^2;
/************* 本地变量声明 **************/
u8 LED8[8]; //显示缓冲
u8 display_index; //显示位索引
bit B_1ms; //1ms标志
u8IO_KeyState, IO_KeyState1, IO_KeyHoldCnt; //行列键盘变量
u8 KeyHoldCnt; //键按下计时
u8 KeyCode; //给用户使用的键码, 1~16有效
u8 cnt50ms;
u8hello;
u8nao;
u8minute2;
u8KeyCode0;
u8 hour,hour1,minute,minute1,second,day,week,week1,month,year; //RTC变量
u16 msecond;
u16msecond1;
u8hello;
u8naofu;
u8zhuangtai;
u8xunhuan;
u8tuinao; //闹钟控制开启退出
u8xinqinao;//星期·闹钟
/************* 本地函数声明 **************/
void CalculateAdcKey(u16 adc);
void IO_KeyScan(void); //50ms call
void WriteNbyte(u8 addr, u8 *p, u8 number);
void ReadNbyte( u8 addr, u8 *p, u8 number);
void DisplayRTC(void);
void DisplayRTC1(void);
void DisplayRTC2(void);
void ReadRTC(void);//读取时钟
void ReadRTC1(void);
void ReadRTC2(void);
void ReadRTC3(void);
void WriteRTC(void);
void WriteRTC1(void);
void WriteRTC2(void);
void WriteRTC3(void);
void DisplayRTC3(void);
void DisplayRTC4(void);
void DisplayRTC5(void);
/**************** 外部函数声明和外部变量声明*****************/
/**********************************************/
voidmain(void)
{
u8 i;
P0M1= 0; P0M0 = 0; //设置为准双向口
P1M1= 0; P1M0 = 0; //设置为准双向口
P2M1= 0; P2M0 = 0; //设置为准双向口
P3M1= 0; P3M0 = 0; //设置为准双向口
P4M1= 0; P4M0 = 0; //设置为准双向口
P5M1= 0; P5M0 = 0; //设置为准双向口
P6M1= 0; P6M0 = 0; //设置为准双向口
P7M1= 0; P7M0 = 0; //设置为准双向口
display_index= 0;
AUXR= 0x80;//T0时钟无分频
TMOD=0x00; //Timer0 set as 1T, 16 bits timer auto-reload,T0时钟无分频,16位自动重装
TH0= (u8)(Timer0_Reload / 256); //定时器取其高低8位为状态值
TL0= (u8)(Timer0_Reload % 256);
ET0= 1; //Timer0 interrupt enable T0中断允许
TR0= 1; //Tiner0 run T0启动
EA= 1; //打开总中断 ,总中断允许
hello=0;
if(nao==1){}//断电重置
elseif(nao==2){}
else
{
nao=0;
}
for(i=0;i<8; i++) LED8[i] = 0x10; //上电消隐 dp高位 防止极短时间内出现两个数字的重叠
ReadRTC();//读取时钟
ReadRTC1();
F0= 0;
if(second>= 60) F0 = 1; //错误
if(minute>= 60) F0 = 1; //错误
if(hour >= 24) F0= 1; //错误
if(F0==1) //有错误, 默认12:00:00
{
second= 0;
minute= 0;
hour = 12;
WriteRTC();
}
if(day>=32) F0=2;
if(week>=8) F0=2;
if(month>=13)F0=2;
if(year>=100)F0=2;
if(F0==2) //有错误, 默认12:00:00
{
day=6;
week=3;
month=6;
year=18;
WriteRTC1();
}
if(minute1>= 60) F0 = 3; //错误
if(hour1 >= 24) F0= 3; //错误
if(F0==3)
{
minute1=30;
hour1=7;
WriteRTC2();
}
if(week1>=8)
{
WriteRTC3();
}
DisplayRTC();
KeyHoldCnt= 0; //键按下计时
KeyCode= 0; //给用户使用的键码,1~16有效
IO_KeyState= 0;
IO_KeyState1= 0;
IO_KeyHoldCnt= 0;
cnt50ms= 0;
zhuangtai=0;
KeyCode0=0;
tuinao=0;
minute2=61;
naofu=0;//控制闹钟加1加5与分钟同步
xunhuan=0;//控制循环闹钟
xinqinao=0;//星期闹钟控制
if(msecond1==0){}
else
{
msecond1=0;
}
while(1)
{
if(B_1ms) //1ms到
{
B_1ms= 0;
if(++msecond>= 500) //1秒到 刷新时钟
{
if(hello==0)
{
ReadRTC();
DisplayRTC();
if(minute==0) //整点报时
{
if(hour==hour1)
{
if(minute==minute1)
{}else{
led1=0;
}
}else
{
led1=0;
}
}
else{
led1=1;
}
if(hour==hour1) //闹钟实现块
{
if(second==0)//保证和时钟分钟同步++乘其下一分钟前进行+5 +1操作
{
msecond1=0;
naofu=1;
}
else
{
if(naofu==1)
{
if(++msecond1>=60)
{msecond1=0;
naofu=0;
}
}
}
if(minute==minute1-1)//取出闹钟分钟值
{ ReadRTC2();
minute2=minute1;
}