自己看教程后写的,测试过可以用。水平业余,大佬轻喷…
/*********************************************************
*《DS1302时钟模块驱动》
*文件:DS1302.c DS1302.h
*
*Description:
extern unsigned char *DS1302ReadClock():
读取时钟日历数据,返回值为数组DS1302TempClockData[7]首地址,值为10进制
extern unsigned char *DS1302ClockData2String(unsigned char DS1302clockData[7], unsigned char returnType):
时钟数据格式化输出预处理
DS1302clockData[7]:要处理的时钟数据数组首地址,一般由DS1302ReadClock函数返回
returnType:返回类型,0或1;0返回 “W HHMMSS”共8位字符串;1返回“YYYYMMDD”
extern bit DS1302SetClock(unsigned char clockDataInDecimal[7]):
设定时钟为指定日期与时间,默认设定即启动,十进制,返回bit型:0设定不成功(输入日期不规范),1设定成功
clockDataInDecimal[7]:要设定的时钟数据数组,传入首地址
extern void DS1302Clock_Pause():
时钟暂停
extern void DS1302Clock_Start():
时钟继续
extern unsigned char DS1302ClockDataIllegalCode:
输出8位二进制,第1位恒为0,后7为分别对应秒分时日月周年出错情况,为1则出错
时钟数据数组ClockData[7]元素从0-6分别为秒(0-59)/分(0-59)/时(0-23)/日/月/周/年(0-9999)
*Version:1.0
*********************************************************/
#include "reg52.h"
#include "DS1302.h"
#include
#include
typedef unsigned char uC;
typedef unsigned int uI;
typedef unsigned long int uLI;
//external variable
uC DS1302InitialClock[7] = { 0, 0, 0x12, 0x07, 0x05, 0x06, 0x16 };
uC DS1302ClockDataIllegalCode = 0xff;//输出时用二进制,第1位恒为0,后7为分别对应秒分时日月周年出错情况,为1则出错
uC DS1302tempStr[9] = { 0,0,0,0,0,0,0,0,'\0' };
//external function
//interal varible
uC DS1302TempClockData[7] = { 0, 0, 0x12, 0x07, 0x05, 0x06, 0x16 };
//日历读写 秒分时日月周年 地址表
uC code DS1302Address_Clock_Read[7] = { 0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d };
uC code DS1302Address_Clock_Write[7] = { 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c };
//转BCD码,num须不大于255,正常值0~99
uC Convert2BCD(uC num)
{
uC BCDCode = 0;
uC temp1 = num;
BCDCode |= (temp1 % 10);//余数为10进制最低位,其二进制直接写入最终输出变量的最低位
temp1 = temp1 / 10;
BCDCode |= ((temp1)<<4);
return BCDCode;
}
//BCD byte解码
static uC BCDDecoding(uC BCDcode)
{
uC temp = 0;
temp = ((BCDcode >> 4) * 10 + (BCDcode & 0x0f));
return temp;
}
//检查要写入的十进制时钟变量合法性
static bit CheckClockDataLegal(uC clockDataInDecimal[7])
{
uC i = 0;
DS1302ClockDataIllegalCode = 0x00;
for (i = 0; i < 7; i++)
{
switch (i)
{
default:
break;
case 0://Check Sec
if (clockDataInDecimal[i]>59)
{
DS1302ClockDataIllegalCode |= 1;
}
break;
case 1://Check Min
if (clockDataInDecimal[i]>59)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 2://Check Hour
if (clockDataInDecimal[i]>23)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 3://Check Day
if (clockDataInDecimal[i]>31)
{
DS1302ClockDataIllegalCode = 1;
}
else
{
switch (clockDataInDecimal[4])
{
default:
break;
case 2:
if (clockDataInDecimal[i]>29)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 4:
if (clockDataInDecimal[i]>30)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 6:
if (clockDataInDecimal[i]>30)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 9:
if (clockDataInDecimal[i]>30)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 11:
if (clockDataInDecimal[i]>30)
{
DS1302ClockDataIllegalCode = 1;
}
break;
}
}
break;
case 4://Check Mon
if (clockDataInDecimal[i]>12)
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 5://Check Week
if ( !(clockDataInDecimal[i]<8 || clockDataInDecimal[i]>0) )
{
DS1302ClockDataIllegalCode = 1;
}
break;
case 6://Check Year
if (clockDataInDecimal[i]>100)
{
DS1302ClockDataIllegalCode = 1;
}
break;
}
DS1302ClockDataIllegalCode <<= 1;
}
if (DS1302ClockDataIllegalCode==0)//合法则返回1
{
return 1;
}
else
{
return 0;
}
}
//转码BCD写入DS1302ClockData[7]数组, 若传入参数不合法返回0, 错误代码查询 外部变量 DS1302ClockDataIllegalCode,;否则返回1
static void PrepareClockDataInBCD(uC clockDataInDecimal[7])
{
uC i = 0;
for (i = 0; i < 7; i++)
{
DS1302TempClockData[i] = Convert2BCD(clockDataInDecimal[i]);
}
}
static uC ReadByte(uC address)//读DS1302数据到DS1302TempClockData[7]
{
uC i = 0;
uC dat = 0;
DS1302_CLK = 0;
_nop_();
DS1302_RST = 1;
_nop_();
for (i = 0; i < 8; i++)//写地址 低位起
{
DS1302_IO = address & 0x01;
DS1302_CLK = 1;
address >>= 1;
_nop_();
DS1302_CLK = 0;
_nop_();
}
for (i = 0; i < 8; i++)//读byte 低位起,写地址最后一个时钟下跳沿已经准备好第一个数据
{
dat = (dat >> 1) | (DS1302_IO * 0x80);
DS1302_CLK = 1;
_nop_();
DS1302_CLK = 0;
_nop_();
}
DS1302_RST = 0;
//读取IO口不外置上拉电阻的话,将IO口拉低然后再释放就可以解决读取不稳定
_nop_();
DS1302_IO = 0;
_nop_();
DS1302_IO = 1;
_nop_();
return dat;
}
static void WriteByte(uC address, uC dat)
{
uC i = 0;
uC tempData = dat;
DS1302_RST = 0;
_nop_();
DS1302_CLK = 0;
_nop_();
DS1302_RST = 1;
_nop_();
for (i = 0; i < 8; i++)//写地址 低位起
{
DS1302_IO = address & 0x01;
address >>= 1;
DS1302_CLK = 1;
_nop_();
DS1302_CLK = 0;
_nop_();
}
for (i = 0; i < 8; i++)//写数据
{
DS1302_IO = tempData & 0x01;
tempData >>= 1;
DS1302_CLK = 1;
_nop_();
DS1302_CLK = 0;
_nop_();
}
DS1302_RST = 0;
_nop_();
}
//操作写保护:传参1开启,0关闭
static void SetWriteProtect(bit WPflag)
{
if (WPflag)
{
WriteByte(0x8E, 0X80);
}
else
{
WriteByte(0x8E, 0X00);
}
}
void DS1302Clock_Pause()
{
DS1302TempClockData[0]=ReadByte(DS1302Address_Clock_Read[0]);//获取当前秒寄存器值
SetWriteProtect(0);
WriteByte(DS1302Address_Clock_Write[0], DS1302TempClockData[0] | (0x80));//秒寄存器最高位置1
SetWriteProtect(1);
}
void DS1302Clock_Start()
{
DS1302TempClockData[0]=ReadByte(DS1302Address_Clock_Read[0]);//获取当前秒寄存器值
SetWriteProtect(0);
WriteByte(DS1302Address_Clock_Write[0],DS1302TempClockData[0] & (0x7f));//秒寄存器最高位清0
SetWriteProtect(1);
}
//设定DS1302时钟,成功返回1,否则返回0
bit DS1302SetClock(uC clockDataInDecimal[7])
{
uC i = 0;
if (!CheckClockDataLegal(clockDataInDecimal))
{
return 0;
}
PrepareClockDataInBCD(clockDataInDecimal);
SetWriteProtect(0);
for (i = 0; i < 7; i++)
{
WriteByte(DS1302Address_Clock_Write[i], DS1302TempClockData[i]);
}
// WriteByte(0x80, 0x99);写入秒值
SetWriteProtect(1);
return 1;
}
//读取DS1302时钟
uC *DS1302ReadClock()
{
uC i = 0;
uC readBuff=0;//秒将特殊处理
for (i = 0; i < 7; i++)
{
readBuff=ReadByte(DS1302Address_Clock_Read[i]);
if(i==0)//秒数据解码时只送低7为,最高位暂停标志位剔除
{
readBuff&=0x7f;
}
DS1302TempClockData[i] =BCDDecoding(readBuff);
}
return DS1302TempClockData;
}
static uC num2str(uC num)
{
return num + '0';
}
static void Round2Double(uC num, uC *str)
{
if (num>99)
{
return;
}
if (num<10)
{
*str = '0';
*(str+1) = num2str(num);
}
else
{
*str = num2str(num / 10);
*(str + 1) = num2str(num % 10);
}
}
uC *DS1302ClockData2String(uC DS1302clockData[7], uC returnType)
{
uC sec=0;
sec=DS1302clockData[0];
switch (returnType)
{
case 0://time and week "W HHMMSS"
*DS1302tempStr =num2str( DS1302clockData[5]) ;//week
*(DS1302tempStr + 1) = ' ';
Round2Double(DS1302clockData[2], DS1302tempStr+2);//hh
Round2Double(DS1302clockData[1], DS1302tempStr + 4);//mm
Round2Double(sec, DS1302tempStr + 6);//ss
break;
case 1://Year and Month "yyyy/MM/dd"
*(DS1302tempStr + 0) = '2';
*(DS1302tempStr + 1) = '0';
Round2Double(DS1302clockData[6], DS1302tempStr + 2);//yy
Round2Double(DS1302clockData[4], DS1302tempStr + 4);//mm
Round2Double(DS1302clockData[3], DS1302tempStr + 6);//dd
break;
default:
break;
}
return DS1302tempStr;
}
头文件:
#include "reg52.h"
#include
#include
sbit DS1302_IO = P3 ^ 4;
sbit DS1302_RST = P3 ^ 5;
sbit DS1302_CLK = P3 ^ 6;
//external variable
extern unsigned char DS1302ClockDataIllegalCode;//输出时用二进制,第1位恒为0,后7为分别对应秒分时日月周年出错情况,为1则出错
//external function
extern unsigned char *DS1302ReadClock();
extern unsigned char *DS1302ClockData2String(unsigned char DS1302clockData[7], unsigned char returnType);
extern bit DS1302SetClock(unsigned char clockDataInDecimal[7]) ;
extern void DS1302Clock_Pause();
extern void DS1302Clock_Start();