#ifndef _DS1302_H_
#define _DS1302_H_
#include<AT89X52.H>
#include<intrins.h>
typedef struct __SYSTEMTIME__
{
unsigned char Second;
unsigned char Minute;
unsigned char Hour;
unsigned char Week;
unsigned char Day;
unsigned char Month;
unsigned char Year;
unsigned char datestr[11];
unsigned char timestr[9];
}systime; //定義的時間類型
#define uchar unsigned char
#define uint unsigned int
#define am(x) x
#define pm(x) (x+12) // 轉成24小時制
#define dssecond 0x80 //時鐘芯片的寄存器位置,存放時間
#define dsminute 0x82
#define dshour 0x84
#define dsweek 0x8A
#define dsday 0x86
#define dsmonth 0x88
#define dsyear 0x8C
#define dsbaohu 0x8E
#define on 0x80
#define off 0x00
extern uchar change(uchar x);
extern uchar bcdtohex(uchar val);
extern void wr1302b(uchar temp);
extern void wr1302(uchar add,uchar dat);
extern uchar re1302b();
extern uchar re1302(uchar address);
extern void dsinit(void);
extern void dsgettime(systime *ds1302);
extern void timetostr(systime *ds1302);
extern void datetostr(systime *ds1302);
#endif
////////////////////////////////////////////////////////////c程序////////////////////////////////////////////////////
#include <AT89X52.H>
#include "ds1302.h"
#include <intrins.h>
//管角定義
sbit ACC0 = ACC^0;
sbit ACC7 = ACC^7;
sbit dssck=P1^0;
sbit dssda=P1^1;
sbit dsrst=P1^2;// DS1302復位
systime currenttime; //定義結構體變量不可以在點h文件中定義
uchar flaghour,flagmin,flagsec,flagyear,flagmonth,flagday,flagweek,week_value[2];
/*************************************
函數名:change
函數功能:十進制轉換成十六進制
參數:x(十六進制數)
返回:y(十進制數)
備注:無
*************************************/
uchar bcdtohex(uchar val)
{
uchar i;
i = val&0x0f; //按位與,i得到低四位數。
val >>= 4; //右移四位,將高四位移到低四位的位置,得到高四位碼值。
val &= 0x0f; //防止移位時高位補進1,只保留高四位碼值
val *= 10; //高位碼值乘以10
i += val; //然后與第四位碼值相加。
return i; //將得到的十進制數返回
}
/*************************************
函數名:wr1302b
函數功能:實時時鐘寫入一個字節
參數:d
返回:無
備注:配合wr1302使用
*************************************/
void wr1302b(uchar d)
{
unsigned char i;
ACC = d;
for(i=8; i>0; i--)
{
dssda = ACC0; //相當于匯編中的 RRC
dssck = 1;
dssck = 0;
ACC = ACC >> 1;
}
}
/*************************************
函數名:wr1302
函數功能:向1302中寫數據
參數:ucAddr(DS1302地址), ucData(要寫的數據)
返回:無
備注:無
*************************************/
void wr1302(uchar ucAddr, uchar ucDa)
{
dsrst = 0;
dssck = 0;
dsrst = 1;
wr1302b(ucAddr); // 地址,命令
wr1302b(ucDa); // 寫1Byte數據
dssck = 1;
dsrst = 0;
}
/*************************************
函數名:re1302b
函數功能:實時時鐘讀取一字節
參數:無
返回:ACC
備注:配合re1302使用
*************************************/
uchar re1302b(void)
{
unsigned char i;
for(i=8; i>0; i--)
{
ACC = ACC >>1; //相當于匯編中的 RRC
ACC7 = dssda;
dssck = 1;
dssck = 0;
}
return(ACC);
}
/*************************************
函數名:re1302
函數功能:讀數據
參數:ucAddr(地址)
返回:ucData(數據)
備注:無
*************************************/
uchar re1302(uchar ucAddr) //讀取DS1302某地址的數據
{
unsigned char ucData;
dsrst = 0;
dssck = 0;
dsrst = 1;
wr1302b(ucAddr|0x01); // 地址,命令
ucData = re1302b(); // 讀1Byte數據
dssck = 1;
dsrst = 0;
return(ucData);
}
/*************************************
函數名:dsinit
函數功能:時鐘初始化
參數:無
返回:無
備注:無
*************************************/
void dsinit(void) //時鐘初始化可以不填
{
wr1302(dsbaohu,off);
wr1302(dsyear,0x09);
wr1302(dsmonth,0x11);
wr1302(dsday,0x02);
wr1302(dsweek,0x01);
wr1302(dshour,0x23);
wr1302(dsminute,0x57);
wr1302(dssecond,0x55);
wr1302(dsbaohu,on);
}
/*************************************
函數名:dsgettime
函數功能:獲取時間到時間型指針
參數:systime *ds1302(時間型數據指針)
返回:無
備注:無
*************************************/
void dsgettime(systime *ds1302) //獲取時鐘芯片的時鐘數據到自定義的結構型數組
{
unsigned char ReadValue;
ReadValue = re1302(dssecond);
ds1302->Second = bcdtohex(ReadValue);
ReadValue = re1302(dsminute);
ds1302->Minute = bcdtohex(ReadValue);
ReadValue = re1302(dshour);
ds1302->Hour = bcdtohex(ReadValue);
ReadValue = re1302(dsday);
ds1302->Day = bcdtohex(ReadValue);
ReadValue = re1302(dsweek);
ds1302->Week = bcdtohex(ReadValue);
ReadValue = re1302(dsmonth);
ds1302->Month =bcdtohex(ReadValue);
ReadValue = re1302(dsyear);
ds1302->Year = bcdtohex(ReadValue);
}
/*************************************
函數名:timetostr
函數功能:將時間轉換液晶顯示字符放入數組timestr[]
參數:systime *ds1302(時間型數據指針)
返回:無
備注:無
*************************************/
void timetostr(systime *ds1302)
{ if(flaghour<2)
{
ds1302->timestr[0] = ds1302->Hour/10 + '0';
ds1302->timestr[1] = ds1302->Hour%10 + '0';
}
else
{
ds1302->timestr[0] = ' ';
ds1302->timestr[1] = ' ';
}
ds1302->timestr[2] = ':';
if(flagmin<2)
{
ds1302->timestr[3] = ds1302->Minute/10 + '0';
ds1302->timestr[4] = ds1302->Minute%10 + '0';
}
else
{
ds1302->timestr[3] = ' ';
ds1302->timestr[4] = ' ';
}
ds1302->timestr[5] = ':';
if(flagsec<2)
{
ds1302->timestr[6] = ds1302->Second/10 + '0';
ds1302->timestr[7] = ds1302->Second%10 + '0';
}
else
{
ds1302->timestr[6] = ' ';
ds1302->timestr[7] = ' ';
}
ds1302->timestr[8] = '\0';
}
/*************************************
函數名:datetostr
函數功能:將日期轉換液晶顯示字符放入數組datestr[]
參數:systime *ds1302(時間型數據指針)
返回:無
備注:無
*************************************/
void datetostr(systime *ds1302) //將時間年,月,日,星期數據轉換成液晶顯示字符串,放到數組里DateString[]
{ if(flagyear<2) //這里的if,else語句都是判斷位閃爍,<2顯示數據,>2就不顯示,輸出字符串為 2007/07/22
{
ds1302->datestr[0] = '2';
ds1302->datestr[1] = '0';
ds1302->datestr[2] = ds1302->Year/10 + '0';
ds1302->datestr[3] = ds1302->Year%10 + '0';
}
else
{
ds1302->datestr[0] = ' ';
ds1302->datestr[1] = ' ';
ds1302->datestr[2] = ' ';
ds1302->datestr[3] = ' ';
}
ds1302->datestr[4] = '/';
if(flagmonth<2)
{
ds1302->datestr[5] = ds1302->Month/10 + '0';
ds1302->datestr[6] = ds1302->Month%10 + '0';
}
else
{
ds1302->datestr[5] = ' ';
ds1302->datestr[6] = ' ';
}
ds1302->datestr[7] = '/';
if(flagday<2)
{
ds1302->datestr[8] = ds1302->Day/10 + '0';
ds1302->datestr[9] = ds1302->Day%10 + '0';
}
else
{
ds1302->datestr[8] = ' ';
ds1302->datestr[9] = ' ';
}
if(flagweek<2)
{
week_value[0] = ds1302->Week%10 + '0';
//星期的數據另外放到 week_value[]數組里,跟年,月,日的分開存放,因為等一下要在最后顯示
}
else
{
week_value[0] = ' ';
}
week_value[1] = '\0';
ds1302->datestr[10] = '\0'; //字符串末尾加 '\0' ,判斷結束字符
}