//#include <15f104.h>
#include<reg51.h>
#include<intrins.h>
#include"ds3231.h"
#include"tm1650.h"
#define uchar unsigned char
#define uint unsigned int
sfr INT_CLKO = 0x8f; //外部中断与时钟输出控制寄存器
sfr IE2 = 0xaf; //中断使能寄存器2
sfr T2H = 0xD6; //定时器2高8位
sfr T2L = 0xD7; //定时器2低8位
uint beginYear=2014;
uchar beginMonth=6;
uchar beginDate=7;
uint year,day;
uchar i, setmode,flash,dspmode;
uchar month,date,dayofweek;
uchar hour,minute; //显示缓冲
uchar second;
uchar secMode;
uchar CODE[] = {0xFC,0x84,0xBA,0xAE,0xC6,0x6E,0x7E,0xA4,0xFE,0xEE,0x00};//0-9,全灭
bit sec;//1HZ秒点闪烁
//延时
void delaySt(){
uint j;
uchar k;
for(k=0;k<10;k++){
for(j=0;j<12000;j++){
_nop_();
}
}
}
//从DS3231获取当前日期
void GetDateNow()
{
uchar dstmp,dstmp2,dstmp3;
dstmp = ReadDS3231(RTC_YR_REG_ADDR);
dstmp2 = ReadDS3231(RTC_MON_REG_ADDR);
dstmp3 = ReadDS3231(RTC_DAY_REG_ADDR)-1;
year = dstmp/16*10 + dstmp%16 + ((dstmp2 & 0x80) ? 2000 : 1900);
month = dstmp2&0x7F;
date = ReadDS3231(RTC_DATE_REG_ADDR);
hour = ReadDS3231(RTC_HR_REG_ADDR);
dayofweek = dstmp3?dstmp3:7;
}
//从DS3231获取当前时间
void GetTimeNow()
{
hour = ReadDS3231(RTC_HR_REG_ADDR);
minute = ReadDS3231(RTC_MIN_REG_ADDR);
}
//判断是否闰年
bit RunYear(uint yearc){
return (yearc%400==0||(yearc%100!=0&&yearc%4==0))?1:0;
}
//返回当月天数
uchar DayInMonth(uint yearc,uchar monthc){
int day[12]={31,28,31,30, 31,30,31,31, 30,31,30,31};
if(monthc==2){
return RunYear(yearc)?29:28;
}else{
return day[monthc-1];
}
}
//计算当年天数
uint DaysInYear(uint yearc,uchar monthc,uchar datec){
uint daytmp = 0;
for(i=1;i<monthc;i++){
daytmp += DayInMonth(yearc,i);
}
return daytmp + datec;
}
//计算从开始日期到现在天数
void CalDay(){
uint daytmp;
uint i;
uint beginDays;
uint lastDays;
daytmp = 0;
GetDateNow();
beginDays = DaysInYear(beginYear,beginMonth,beginDate);
lastDays = DaysInYear(year,month/16*10+month%16,date/16*10+date%16);
for(i = beginYear;i<year;i++){
daytmp += RunYear(year)?366:365;
}
day = daytmp + lastDays - beginDays + 1;
}
//显示年
void display_year(){
TM1650_Set(0x68, CODE[year/1000]);
TM1650_Set(0x6A, CODE[year/100%10]);
TM1650_Set(0x6C, CODE[year/10%10]);
TM1650_Set(0x6E, CODE[year%10]);
}
//显示日期
void display_date()
{
uchar dsptmp ;
if(secMode<5){//month-date
if(month/16) {
dsptmp = CODE[month/16];
TM1650_Set(0x68,dsptmp );
} else {
dsptmp = 0x00;
TM1650_Set(0x68,dsptmp);
}
TM1650_Set(0x6A, CODE[month%16]+1);
TM1650_Set(0x6C, CODE[date/16]);
TM1650_Set(0x6E, CODE[date%16]);
}else{//year-dayofweek
if(year>=10) {
dsptmp = CODE[year/10%10];
TM1650_Set(0x68,dsptmp);
} else {
dsptmp = 0x00;
TM1650_Set(0x68,dsptmp);
}
TM1650_Set(0x6A, CODE[year%10]);
TM1650_Set(0x6C, 0x02); //0x02--the center short line
TM1650_Set(0x6E, CODE[dayofweek]);
}
}
//显示天数计数
void display_day()
{
CalDay();
if(day/1000)TM1650_Set(0x68, CODE[day/1000]);else TM1650_Set(0x68, 0x00);
if(day>=100)TM1650_Set(0x6A, CODE[day/100%10]);else TM1650_Set(0x6A, 0x00);
if(day>=10)TM1650_Set(0x6C, CODE[day/10%10]);else TM1650_Set(0x6C,0x00);
TM1650_Set(0x6E, CODE[day%10]);
}
//根据当前时间调整亮度
void AutoLight(){ //auto set the light level of module
if((hour>=0x19)||(hour<7))
TM1650_Set(0x48,0x21);
else
TM1650_Set(0x48,0x51);
}
//显示时间
void display_time()
{
if(hour/16)TM1650_Set(0x68, CODE[hour/16]);else TM1650_Set(0x68, 0x00);
TM1650_Set(0x6A, CODE[hour%16]+(sec?1:0));
TM1650_Set(0x6C, CODE[minute/16]);
TM1650_Set(0x6E, CODE[minute%16]);
}
//初始化单片机定时器
void Timer_init() //定时器,用于调整时间时数码管的闪烁
{
TMOD=0X01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TR0=0;
ET0=1;
INT_CLKO=0x10;//开启外部中断2,下降沿触发
IE2 |= 0x04;
EA=1;
}
//从ds3231读取初始化信息
void DS3232_init()
{
uchar modetmp = ReadDS3231(MODE_REG_ADDR);
if(modetmp==0)
{
//bcd8421
WriteDS3231(RTC_SEC_REG_ADDR,0x00); //second
WriteDS3231(RTC_MIN_REG_ADDR,0x11); //minute
WriteDS3231(RTC_HR_REG_ADDR,0x20); //hour
WriteDS3231(RTC_YR_REG_ADDR,0x17);//year
WriteDS3231(RTC_MON_REG_ADDR,0x82);//month ,&0x08==cent
WriteDS3231(RTC_DAY_REG_ADDR,0x02);//day of week
WriteDS3231(RTC_DATE_REG_ADDR,0x13);//date
WriteDS3231(MODE_REG_ADDR,0x11);// 用闹钟寄存器判断是否掉电
//hex, default is 2014.6.7
WriteDS3231(BEGIN_YR_REG_ADDR,0x0E);//beginyear
WriteDS3231(BEGIN_MON_REG_ADDR,0x86);//beginmonth
WriteDS3231(BEGIN_DATE_REG_ADDR,0x07);//begindate
}
else{
dspmode = modetmp >>4 -1;
setmode = modetmp % 16 -1;
}
}
void main()
{
uchar temp;
uchar dstmp;
uchar numtmp;
uchar dayInMontmp;
uchar yearAdj;//int month-date,year-day mode ,the adjust bit of year
uchar key;
Timer_init();
TM1650_Set(0x48,0x51);//初始化为6级灰度,开显示
DS3232_init(); // DS3231掉电时初始化一下
WriteDS3231(RTC_CTL_REG_ADDR,0x00); //设置INT位为1HZ方波输出
while(1)
{
delaySt();
AutoLight();
switch(dspmode){
case 0: //hour--minute mode**************************
GetTimeNow();
key = Scan_Key();
if(key==0x47) //key set
{
setmode++;
setmode %= 4;
while(Scan_Key()==0x47);//if key be released, its 6th bit turn to 0 ,thus its 0x07
}
switch (setmode)
{
case 0: //GetTimeNow adjust hour:minute
{
INT_CLKO=0x10;
TR0=0;//adjust flash disable
if(key==0x77) //key add
{
while(Scan_Key()==0x77); //if key be released, its 6th bit turn to 0 ,thus its 0x37
dspmode = 1;
setmode = 0;
secMode = 0;
}
break;
}
case 1: //hour adjust
{
INT_CLKO=0x00;
sec=1;
TR0=1;
minute = ReadDS3231(RTC_MIN_REG_ADDR);
if(key==0x77)
{
while(Scan_Key()==0x77);
temp=ReadDS3231(RTC_HR_REG_ADDR);
temp=(temp>>4)*10 + (temp & 0x0F);
temp++;
temp %= 24;
temp = ((temp/10)<<4)|(temp%10);
WriteDS3231(RTC_HR_REG_ADDR,temp);
}
if(flash) hour = ReadDS3231(RTC_HR_REG_ADDR);
else