C51单片机 DS1302 时钟模块 驱动代码

自己看教程后写的,测试过可以用。水平业余,大佬轻喷…

/*********************************************************
*《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();

你可能感兴趣的:(C51单片机 DS1302 时钟模块 驱动代码)