分享51电子时钟,LCD1602显示,DS1302,DS18B20

作者:BrightBell                 时间:2016年1月初

单片机:STC89C52RC            时钟芯片:DS1302
测温元件:DS18B20            显示元件:LCD1602
信息保持:STC单片机内部EEPROM

备注:
1.DS1302没有第二电源,掉电不走时,误差 < 1s/5天
2.时间、背光开关时间、蜂鸣器整点报时时间、LCD背光亮度、按键音皆可设置
3.长按KEY0马上开/关LCD背光,长按KEY1进入系统设置界面,长按KEY2进入时间设置界面
4.每3秒读取一次DS18B20温度
5.每一小时更新一次EEPROM中的时间信息,重新设置时间后马上更新
6.进行一次系统设置后,马上更新EEPROM中的系统设置信息,下次启动时会先加载

 

部分源文件预览:

#ifndef _DS1302_H_
#define _DS1302_H_


void DS1302ByteWrite(unsigned char dat) //向DS1302写入一个字节
{
unsigned char mask;
for(mask=0x01; mask!=0; mask<<=1) //低位在先
{
if((mask&dat) != 0)
DS1302IO = 1;
else
DS1302IO = 0;
DS1302CK = 1;
DS1302CK = 0;
}
DS1302IO = 1;
}

unsigned char DS1302ByteRead(void) //从DS1302读取一个字节
{
unsigned char mask;
unsigned char dat = 0;
for(mask=0x01; mask!=0; mask<<=1)
{
if(DS1302IO != 0)
dat |= mask;
DS1302CK = 1;
DS1302CK = 0;
}
return dat;
}

void DS1302SingleWrite(unsigned char reg, unsigned char dat) //写入DS1302的某一寄存器
{
DS1302CE = 1;
DS1302ByteWrite((reg<<1)|0x80);
DS1302ByteWrite(dat);
DS1302CE = 0;
}

unsigned char DS1302SingleRead(unsigned char reg) //读取DS1302的某一寄存器
{
unsigned char dat;
DS1302CE = 1;
DS1302ByteWrite((reg<<1)|0x81);
dat = DS1302ByteRead();
DS1302CE = 0;
return dat;
}

void DS1302BurstWrite(unsigned char *dat) //Brust模式写入时间信息
{
unsigned char i;
DS1302CE = 1;
DS1302ByteWrite(0xBE);
for(i=0; i<8; i++)
{
DS1302ByteWrite(dat[i]);
}
DS1302CE = 0;
}

void DS1302BurstRead(unsigned char *dat) //Brust模式读出时间信息
{
unsigned char i;
DS1302CE = 1;
DS1302ByteWrite(0xBF);
for(i=0; i<8; i++)
{
dat[i] = DS1302ByteRead();
}
DS1302CE = 0;
}

//欲写入的是十进制的时间信息,不是BCD码,已进行转换
struct TIME Bcd1302ToDec(struct TIME *time)
{
struct TIME dectime;
dectime.year = (time->year >> 4) * 10;
dectime.year = (time->year & 0x0F) + dectime.year;
dectime.mon = (time->mon >> 4) * 10;
dectime.mon = (time->mon & 0x0F) + dectime.mon;
dectime.day = (time->day >> 4) * 10;
dectime.day = (time->day & 0x0F) + dectime.day;
dectime.hour = (time->hour >> 4) * 10;
dectime.hour = (time->hour & 0x0F) + dectime.hour;
dectime.min = (time->min >> 4) * 10;
dectime.min = (time->min & 0x0F) + dectime.min;
dectime.sec = (time->sec >> 4) * 10;
dectime.sec = (time->sec & 0x0F) + dectime.sec;

dectime.week = time->week & 0x0F;

return dectime;
}

//获取到的是十进制的时间信息,不是BCD码,获取后已进行转换
void GetRealTime(struct TIME *time) //获取时间信息,并保存在时间结构体中
{
unsigned char buf[8];
struct TIME temp;
DS1302BurstRead(buf);
temp.year = buf[6];
temp.mon = buf[4];
temp.day = buf[3];
temp.hour = buf[2];
temp.min = buf[1];
temp.sec = buf[0];
temp.week = buf[5];

*time = Bcd1302ToDec(&temp); //将BCD码转为十进制
}

struct TIME DecToBcd1302(struct TIME *time)
{
struct TIME bcdtime;
bcdtime.year = (time->year / 10 % 10) * 16;
bcdtime.year = (time->year % 10) + bcdtime.year;
bcdtime.mon = (time->mon / 10 % 10) * 16;
bcdtime.mon = (time->mon % 10) + bcdtime.mon;
bcdtime.day = (time->day / 10 % 10) * 16;
bcdtime.day = (time->day % 10) + bcdtime.day;
bcdtime.hour = (time->hour / 10 % 10) * 16;
bcdtime.hour = (time->hour % 10) + bcdtime.hour;
bcdtime.min = (time->min / 10 % 10) * 16;
bcdtime.min = (time->min % 10) + bcdtime.min;
bcdtime.sec = (time->sec / 10 % 10) * 16;
bcdtime.sec = (time->sec % 10) + bcdtime.sec;

bcdtime.week = time->week % 10;

return bcdtime;
}

void SetRealTime(struct TIME *time) //通过时间结构体设置时间
{
unsigned char buf[8];
struct TIME temp;
temp = DecToBcd1302(time);
buf[7] = 0;
buf[6] = temp.year;
buf[5] = temp.week;
buf[4] = temp.mon;
buf[3] = temp.day;
buf[2] = temp.hour;
buf[1] = temp.min;
buf[0] = temp.sec;
DS1302BurstWrite(buf);
}

void InitDS1302(void) //初始化DS1302
{
unsigned char dat;
struct TIME eepromtime;
DS1302CE = 0;
DS1302CK = 0;
dat = DS1302SingleRead(0);
if((dat & 0x80) != 0) //检测时间在掉电时是否停止过,停1走0,如果停过就从新写入初始化时间
{
GetE2promTime(&eepromtime); //停止过,获取EEPROM里的时间
DS1302SingleWrite(7, 0x00); //撤销保护
SetRealTime(&eepromtime);
}

lcdShowStr(0, 0, "20 - -");
lcdShowStr(3, 1, ": :");
}

void lcdShowWeek(unsigned char x, unsigned char y, unsigned char week)
{
unsigned char str[5];
lcdShowStr(x-4, y, "week");
str[0] = week % 10 + '0';
str[1] = '\0';
lcdShowStr(x, y, str);
}

void RefreshTime(struct TIME *time)
{
static unsigned char dayBF = 88;
if(dayBF != time->day) //日期发生变化,更新年月日周
{
lcdShowNum(2, 0, time->year);
lcdShowNum(5, 0, time->mon);
lcdShowNum(8, 0, time->day);
lcdShowWeek(15,0, time->week);
dayBF = time->day;
}
lcdShowNum(1, 1, time->hour);
lcdShowNum(4, 1, time->min);
lcdShowNum(7, 1, time->sec);
}

void HourlyWork(struct TIME *time) //小时事件
{
static char hourBF = 88;
static char lightlevelBF = 3;
if(time->hour != hourBF) //时有变
{
if(time->hour==lcdlighton) //判断是否有背光开关
{
lcdlight = 0;
if(lightlevelBF != 0)
lcdlightlevel = lightlevelBF;
else
lcdlightlevel = 4;
}
else if(time->hour==lcdlightoff) //判断是否有背光开关
{
lcdlight = 1;
lightlevelBF = lcdlightlevel;
lcdlightlevel = 0;
}

if((time->hour>=ZDBSbegin)&&(time->hour<=ZDBSend))
{
if(hourlybuzz != 0) //整点报时开
flagZD = 1;
}

SaveTimeToE2prom(time); //每小时更新EEPROM里的时间信息

hourBF = time->hour; //更新备份值
}
}

void LedWaterShow() //流水灯效果
{
static unsigned char ledshow = 0x01;
static bit dir = 0;
ledDB = ledshow;
if(dir == 0)
{
ledshow = ledshow << 1;
if(ledshow == 0x00)
{
dir = 1;
ledshow = 0x40;
}
}
else
{
ledshow = ledshow >> 1;
if(ledshow == 0x00)
{
dir = 0;
ledshow = 0x02;
}
}
}

/*******************************************************************************
补偿值计算方法:当X秒后时间慢Y秒,则:实减=X/当前值;应减=实减-Y; 补偿值=X/应减
********************************************************************************/
void TimeBuChang(struct TIME *time)
{
static char flagBC = 0;
static unsigned int BCcnt = 0;
static struct TIME BCtime;
if(flagBC != 0)
{
flagBC = 0;
SetRealTime(&BCtime); //写入上一秒时间,相当于减一秒
}

BCcnt++;
if(BCcnt > secBuChang) //每X秒减1秒
{
timemenu = 88; //禁止时间更新
BCcnt = 0;
BCtime = *time; //备份上一秒时间
flagBC = 1;
timemenu = 0; //开时间更新
}
}

void UpdateTime()
{
static unsigned char secBF = 88;
static unsigned int ds18b20cnt = 0;
struct TIME buftime; //从DS1302中读取出来的值
GetRealTime(&buftime);
if(buftime.sec != secBF)
{
RefreshTime(&buftime);
secBF = buftime.sec;

ds18b20cnt++;
if(ds18b20cnt > GetTempSpace)
{
ds18b20cnt = 0;
RefreshTemp();
}

HourlyWork(&buftime);
LedWaterShow();

TimeBuChang(&buftime); //时间补偿
}
}

void RefreshTimeNow()
{
struct TIME buftime;
GetRealTime(&buftime);
lcdShowStr(0, 0, "20 - -");
lcdShowStr(3, 1, ": :");
lcdShowNum(2, 0, buftime.year);
lcdShowNum(5, 0, buftime.mon);
lcdShowNum(8, 0, buftime.day);
lcdShowNum(1, 1, buftime.hour);
lcdShowNum(4, 1, buftime.min);
lcdShowNum(7, 1, buftime.sec);
lcdShowWeek(15,0, buftime.week);
if(hourlybuzz != 0)
lcdShowImage(0, 1, image0, 0);
else
lcdShowStr(0, 1, " ");
lcdShowImage(15, 1, image1, 1);
}

#endif

完整版下载:

http://www.eeskill.com/file/id/41618

永不止步步 发表于11-01 11:49 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:308117个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号